19#include "moc_qgslayoutlegendwidget.cpp"
51#include <QInputDialog>
52#include <QActionGroup>
69 int unfilteredNodeIndex = _unfilteredLegendNodeIndex( legendNode );
71 return ( unfilteredNodeIndex >= 0 && unfilteredNodeIndex < order.count() ? order[unfilteredNodeIndex] : -1 );
74 void _moveLegendNode(
QgsLayerTreeLayer *nodeLayer,
int legendNodeIndex,
int destLegendNodeIndex )
77 const int offset = destLegendNodeIndex - legendNodeIndex;
79 if ( legendNodeIndex < 0 || legendNodeIndex >= order.count() )
81 if ( legendNodeIndex + offset < 0 || legendNodeIndex + offset >= order.count() )
84 int id = order.takeAt( legendNodeIndex );
85 order.insert( legendNodeIndex + offset,
id );
94 , mMapCanvas( mapCanvas )
99 connect( mWrapCharLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
100 connect( mTitleLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
105 connect( mColumnCountSpinBox,
static_cast<void ( QSpinBox::* )(
int )
>( &QSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
106 connect( mSplitLayerCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
107 connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
108 connect( mSymbolWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged );
109 connect( mSymbolHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged );
110 connect( mMaxSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged );
111 connect( mMinSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged );
112 connect( mWmsLegendWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
113 connect( mWmsLegendHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
114 connect( mTitleSpaceBottomSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
115 connect( mGroupSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
116 connect( mGroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged );
117 connect( mSubgroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged );
118 connect( mSpaceBelowGroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
119 connect( mGroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
120 connect( mLayerSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
121 connect( mSpaceBelowSubgroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
122 connect( mSubgroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
123 connect( mSymbolSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
124 connect( mSymbolSideSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
125 connect( mIconLabelSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
126 connect( mBoxSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
127 connect( mColumnSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged );
128 connect( mMaxWidthSpinBox, qOverload< double >( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::maxWidthChanged );
129 connect( mCheckBoxAutoUpdate, &QCheckBox::stateChanged,
this, [=](
int state ) { mCheckBoxAutoUpdate_stateChanged( state ); } );
130 connect( mCheckboxResizeContents, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mCheckboxResizeContents_toggled );
131 connect( mRasterStrokeGroupBox, &QgsCollapsibleGroupBoxBasic::toggled,
this, &QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled );
132 connect( mRasterStrokeWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged );
133 connect( mRasterStrokeColorButton, &
QgsColorButton::colorChanged,
this, &QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged );
134 connect( mExpandAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::expandLegendTree );
135 connect( mCollapseAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::collapseLegendTree );
136 connect( mMoveDownToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveDownToolButton_clicked );
137 connect( mMoveUpToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveUpToolButton_clicked );
138 connect( mRemoveToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mRemoveToolButton_clicked );
139 connect( mAddToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddToolButton_clicked );
140 connect( mEditPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mEditPushButton_clicked );
141 connect( mCountToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mCountToolButton_clicked );
142 connect( mExpressionFilterButton, &QgsLegendFilterButton::toggled,
this, &QgsLayoutLegendWidget::mExpressionFilterButton_toggled );
143 connect( mLayerExpressionButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mLayerExpressionButton_clicked );
144 connect( mFilterByMapCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled );
145 connect( mUpdateAllPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mUpdateAllPushButton_clicked );
146 connect( mAddGroupToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddGroupToolButton_clicked );
147 connect( mFilterLegendByAtlasCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled );
148 connect( mItemTreeView, &QgsLayerTreeView::doubleClicked,
this, &QgsLayoutLegendWidget::mItemTreeView_doubleClicked );
150 connect( mFilterByMapCheckBox, &QCheckBox::toggled, mButtonLinkedMaps, &QWidget::setEnabled );
151 mButtonLinkedMaps->setEnabled(
false );
152 connect( mButtonLinkedMaps, &QToolButton::clicked,
this, [=] {
153 mMapFilteringWidget =
new QgsLayoutLegendMapFilteringWidget( mLegend );
154 openPanel( mMapFilteringWidget );
157 setPanelTitle( tr(
"Legend Properties" ) );
164 mTitleAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
165 mGroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
166 mSubgroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
167 mItemAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
169 mArrangementCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignRight );
171 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignLeft, tr(
"Symbols on Left" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsLeft.svg" ) ) );
172 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignRight, tr(
"Symbols on Right" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsRight.svg" ) ) );
174 mSpaceBelowGroupHeadingSpinBox->setClearValue( 0 );
175 mGroupSideSpinBox->setClearValue( 0 );
176 mSpaceBelowSubgroupHeadingSpinBox->setClearValue( 0 );
177 mSubgroupSideSpinBox->setClearValue( 0 );
178 mSymbolSideSpaceSpinBox->setClearValue( 0 );
180 mMaxWidthSpinBox->setShowClearButton(
true );
181 mMaxWidthSpinBox->setClearValue( 0, tr(
"Disabled" ) );
206 mRasterStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
207 mRasterStrokeColorButton->setAllowOpacity(
true );
208 mRasterStrokeColorButton->setContext( QStringLiteral(
"composer " ) );
210 mMapComboBox->setCurrentLayout( legend->
layout() );
216 mainLayout->addWidget( mItemPropertiesWidget );
218 mItemTreeView->setHeaderHidden(
true );
220 mItemTreeView->setModel( legend->
model() );
221 mItemTreeView->setMenuProvider(
new QgsLayoutLegendMenuProvider( mItemTreeView,
this ) );
222 setLegendMapViewData();
228 connect( layoutAtlas(), &
QgsLayoutAtlas::toggled,
this, &QgsLayoutLegendWidget::updateFilterLegendByAtlasButton );
232 mTitleFontButton->registerExpressionContextGenerator(
this );
233 mGroupFontButton->registerExpressionContextGenerator(
this );
234 mLayerFontButton->registerExpressionContextGenerator(
this );
235 mItemFontButton->registerExpressionContextGenerator(
this );
236 mExpressionFilterButton->registerExpressionContextGenerator(
this );
238 mTitleFontButton->setLayer( coverageLayer() );
239 mGroupFontButton->setLayer( coverageLayer() );
240 mLayerFontButton->setLayer( coverageLayer() );
241 mItemFontButton->setLayer( coverageLayer() );
242 if ( mLegend->layout() )
256 connect( mItemTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsLayoutLegendWidget::selectedChanged );
265 if ( mItemPropertiesWidget )
266 mItemPropertiesWidget->setMasterLayout( masterLayout );
272 mTitleFontButton->setMessageBar( iface->
messageBar() );
273 mGroupFontButton->setMessageBar( iface->
messageBar() );
274 mLayerFontButton->setMessageBar( iface->
messageBar() );
275 mItemFontButton->setMessageBar( iface->
messageBar() );
278void QgsLayoutLegendWidget::setGuiElements()
285 blockAllSignals(
true );
286 mTitleLineEdit->setText( mLegend->title() );
287 whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
291 whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
292 mFilterByMapCheckBox->setChecked( mLegend->legendFilterByMapEnabled() );
293 mButtonLinkedMaps->setEnabled( mLegend->legendFilterByMapEnabled() );
294 mColumnCountSpinBox->setValue( mLegend->columnCount() );
295 mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
296 mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
297 mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
298 mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
299 mMaxSymbolSizeSpinBox->setValue( mLegend->maximumSymbolSize() );
300 mMinSymbolSizeSpinBox->setValue( mLegend->minimumSymbolSize() );
301 mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
302 mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
316 mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
317 mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
319 mMaxWidthSpinBox->setValue( mLegend->autoWrapLinesAfter() );
321 mRasterStrokeGroupBox->setChecked( mLegend->drawRasterStroke() );
322 mRasterStrokeWidthSpinBox->setValue( mLegend->rasterStrokeWidth() );
323 mRasterStrokeColorButton->setColor( mLegend->rasterStrokeColor() );
325 mCheckBoxAutoUpdate->setChecked( mLegend->autoUpdateModel() );
327 mCheckboxResizeContents->setChecked( mLegend->resizeToContents() );
328 mFilterLegendByAtlasCheckBox->setChecked( mLegend->legendFilterOutAtlas() );
329 mWrapCharLineEdit->setText( mLegend->wrapString() );
332 mMapComboBox->setItem( map );
338 blockAllSignals(
false );
340 mCheckBoxAutoUpdate_stateChanged( mLegend->autoUpdateModel() ? Qt::Checked : Qt::Unchecked, false );
341 updateDataDefinedButton( mLegendTitleDDBtn );
342 updateDataDefinedButton( mColumnsDDBtn );
345void QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged(
const QString &text )
349 mLegend->beginCommand( tr(
"Change Legend Wrap" ) );
350 mLegend->setWrapString( text );
351 mLegend->adjustBoxSize();
353 mLegend->endCommand();
357void QgsLayoutLegendWidget::mTitleLineEdit_textChanged(
const QString &text )
362 mLegend->setTitle( text );
363 mLegend->adjustBoxSize();
365 mLegend->endCommand();
369void QgsLayoutLegendWidget::titleAlignmentChanged()
373 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
374 mLegend->beginCommand( tr(
"Change Title Alignment" ) );
375 mLegend->setTitleAlignment( alignment );
377 mLegend->endCommand();
381void QgsLayoutLegendWidget::groupAlignmentChanged()
385 mLegend->beginCommand( tr(
"Change Group Alignment" ) );
388 mLegend->endCommand();
392void QgsLayoutLegendWidget::subgroupAlignmentChanged()
396 mLegend->beginCommand( tr(
"Change Subgroup Alignment" ) );
399 mLegend->endCommand();
403void QgsLayoutLegendWidget::itemAlignmentChanged()
407 mLegend->beginCommand( tr(
"Change Item Alignment" ) );
410 mLegend->endCommand();
414void QgsLayoutLegendWidget::arrangementChanged()
418 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
419 mLegend->beginCommand( tr(
"Change Legend Arrangement" ) );
420 mLegend->setSymbolAlignment( alignment );
422 mLegend->endCommand();
426void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged(
int c )
431 mLegend->setColumnCount(
c );
432 mLegend->adjustBoxSize();
434 mLegend->endCommand();
436 mSplitLayerCheckBox->setEnabled(
c > 1 );
437 mEqualColumnWidthCheckBox->setEnabled(
c > 1 );
440void QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled(
bool checked )
444 mLegend->beginCommand( tr(
"Split Legend Layers" ) );
445 mLegend->setSplitLayer( checked );
446 mLegend->adjustBoxSize();
448 mLegend->endCommand();
452void QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled(
bool checked )
456 mLegend->beginCommand( tr(
"Legend Column Width" ) );
457 mLegend->setEqualColumnWidth( checked );
458 mLegend->adjustBoxSize();
460 mLegend->endCommand();
464void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged(
double d )
469 mLegend->setSymbolWidth( d );
470 mLegend->adjustBoxSize();
472 mLegend->endCommand();
476void QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged(
double d )
481 mLegend->setMaximumSymbolSize( d );
482 mLegend->adjustBoxSize();
484 mLegend->endCommand();
488void QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged(
double d )
493 mLegend->setMinimumSymbolSize( d );
494 mLegend->adjustBoxSize();
496 mLegend->endCommand();
500void QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged(
double d )
505 mLegend->setSymbolHeight( d );
506 mLegend->adjustBoxSize();
508 mLegend->endCommand();
512void QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged(
double d )
517 mLegend->setWmsLegendWidth( d );
518 mLegend->adjustBoxSize();
520 mLegend->endCommand();
524void QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged(
double d )
529 mLegend->setWmsLegendHeight( d );
530 mLegend->adjustBoxSize();
532 mLegend->endCommand();
536void QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged(
double d )
542 mLegend->adjustBoxSize();
544 mLegend->endCommand();
548void QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged(
double d )
554 mLegend->adjustBoxSize();
556 mLegend->endCommand();
560void QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged(
double d )
566 mLegend->adjustBoxSize();
568 mLegend->endCommand();
572void QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged(
double d )
578 mLegend->adjustBoxSize();
580 mLegend->endCommand();
584void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged(
double space )
590 mLegend->adjustBoxSize();
592 mLegend->endCommand();
596void QgsLayoutLegendWidget::spaceGroupSideChanged(
double space )
602 mLegend->adjustBoxSize();
604 mLegend->endCommand();
608void QgsLayoutLegendWidget::spaceSubGroupSideChanged(
double space )
614 mLegend->adjustBoxSize();
616 mLegend->endCommand();
620void QgsLayoutLegendWidget::spaceSymbolSideChanged(
double space )
626 mLegend->adjustBoxSize();
628 mLegend->endCommand();
632void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged(
double d )
638 mLegend->adjustBoxSize();
640 mLegend->endCommand();
644void QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged(
double d )
652 mLegend->adjustBoxSize();
654 mLegend->endCommand();
658void QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged(
double d )
664 mLegend->adjustBoxSize();
666 mLegend->endCommand();
670void QgsLayoutLegendWidget::titleFontChanged()
676 mLegend->adjustBoxSize();
678 mLegend->endCommand();
682void QgsLayoutLegendWidget::groupFontChanged()
688 mLegend->adjustBoxSize();
690 mLegend->endCommand();
694void QgsLayoutLegendWidget::layerFontChanged()
700 mLegend->adjustBoxSize();
702 mLegend->endCommand();
706void QgsLayoutLegendWidget::itemFontChanged()
712 mLegend->adjustBoxSize();
714 mLegend->endCommand();
718void QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged(
double space )
724 mLegend->adjustBoxSize();
726 mLegend->endCommand();
730void QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged(
double d )
735 mLegend->setBoxSpace( d );
736 mLegend->adjustBoxSize();
738 mLegend->endCommand();
742void QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged(
double d )
747 mLegend->setColumnSpace( d );
748 mLegend->adjustBoxSize();
750 mLegend->endCommand();
754void QgsLayoutLegendWidget::maxWidthChanged(
double width )
759 mLegend->setAutoWrapLinesAfter( width );
760 mLegend->adjustBoxSize();
762 mLegend->endCommand();
766void QgsLayoutLegendWidget::mMoveDownToolButton_clicked()
773 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
774 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
775 const QModelIndex parentIndex = sourceIndex.parent();
776 if ( !sourceIndex.isValid() || sourceIndex.row() == mItemTreeView->layerTreeModel()->rowCount( parentIndex ) - 1 )
781 if ( !node && !legendNode )
784 mLegend->beginCommand( tr(
"Moved Legend Item Down" ) );
795 const QModelIndex nextIndex = index.siblingAtRow( index.row() + 1 );
797 if ( nextLegendNode )
799 _moveLegendNode(
legendNode->
layerNode(), _unfilteredLegendNodeIndex( legendNode ), _unfilteredLegendNodeIndex( nextLegendNode ) );
804 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() + 1, 0, parentIndex ) ) );
807 mLegend->endCommand();
810void QgsLayoutLegendWidget::mMoveUpToolButton_clicked()
817 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
818 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
819 const QModelIndex parentIndex = sourceIndex.parent();
820 if ( !sourceIndex.isValid() || sourceIndex.row() == 0 )
825 if ( !node && !legendNode )
828 mLegend->beginCommand( tr(
"Move Legend Item Up" ) );
839 const QModelIndex prevIndex = index.siblingAtRow( index.row() - 1 );
841 if ( prevLegendNode )
843 _moveLegendNode(
legendNode->
layerNode(), _unfilteredLegendNodeIndex( legendNode ), _unfilteredLegendNodeIndex( prevLegendNode ) );
848 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() - 1, 0, parentIndex ) ) );
851 mLegend->endCommand();
854void QgsLayoutLegendWidget::expandLegendTree()
856 mItemTreeView->expandAll();
859void QgsLayoutLegendWidget::collapseLegendTree()
861 mItemTreeView->collapseAll();
864void QgsLayoutLegendWidget::mCheckBoxAutoUpdate_stateChanged(
int state,
bool userTriggered )
868 mLegend->beginCommand( tr(
"Change Auto Update" ) );
870 mLegend->setAutoUpdateModel( state == Qt::Checked );
872 mLegend->endCommand();
876 QList<QWidget *> widgets;
877 widgets << mMoveDownToolButton << mMoveUpToolButton << mRemoveToolButton << mAddToolButton
878 << mEditPushButton << mCountToolButton << mUpdateAllPushButton << mAddGroupToolButton
879 << mExpressionFilterButton << mCollapseAllToolButton << mExpandAllToolButton;
880 for ( QWidget *w : std::as_const( widgets ) )
881 w->setEnabled( state != Qt::Checked );
883 if ( state == Qt::Unchecked )
886 selectedChanged( QModelIndex(), QModelIndex() );
887 mItemTreeView->proxyModel()->setShowPrivateLayers(
true );
891 mItemTreeView->proxyModel()->setShowPrivateLayers(
false );
895void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
911 mLegend->beginCommand( tr(
"Change Legend Map" ) );
912 mLegend->setLinkedMap( map );
914 mLegend->endCommand();
916 setLegendMapViewData();
920void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
927 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
928 mLegend->setResizeToContents( checked );
930 mLegend->adjustBoxSize();
932 mLegend->endCommand();
935void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
942 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
943 mLegend->setDrawRasterStroke( state );
944 mLegend->adjustBoxSize();
946 mLegend->endCommand();
949void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
957 mLegend->setRasterStrokeWidth( d );
958 mLegend->adjustBoxSize();
960 mLegend->endCommand();
963void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
971 mLegend->setRasterStrokeColor( newColor );
973 mLegend->endCommand();
976void QgsLayoutLegendWidget::mAddToolButton_clicked()
983 QList<QgsMapLayer *> visibleLayers;
984 if ( mLegend->linkedMap() )
986 visibleLayers = mLegend->linkedMap()->layersToRender();
988 if ( visibleLayers.isEmpty() )
991 visibleLayers = mMapCanvas->layers(
true );
995 addDialog.setVisibleLayers( visibleLayers );
996 if ( addDialog.exec() == QDialog::Accepted )
998 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
999 if ( !layers.empty() )
1001 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
1004 mLegend->model()->rootGroup()->addLayer( layer );
1006 mLegend->updateLegend();
1008 mLegend->endCommand();
1013void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
1020 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
1021 if ( !selectionModel )
1026 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
1028 QList<QPersistentModelIndex> proxyIndexes;
1029 const QModelIndexList viewSelection = selectionModel->selectedIndexes();
1030 for (
const QModelIndex &index : viewSelection )
1031 proxyIndexes << index;
1034 QHash<QgsLayerTreeLayer *, QList<int>> nodesWithRemoval;
1035 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1040 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex( legendNode ) );
1043 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
1045 QList<int> toDelete = it.value();
1046 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
1049 for (
int i : std::as_const( toDelete ) )
1051 if ( i >= 0 && i < order.count() )
1052 order.removeAt( i );
1056 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
1060 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1062 if ( proxyIndex.isValid() && mItemTreeView->index2node( proxyIndex ) )
1064 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( proxyIndex );
1065 mLegend->model()->removeRow( sourceIndex.row(), sourceIndex.parent() );
1069 mLegend->updateLegend();
1071 mLegend->endCommand();
1074void QgsLayoutLegendWidget::mEditPushButton_clicked()
1081 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
1082 mItemTreeView_doubleClicked( idx );
1085void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
1093 QModelIndex currentIndex = mItemTreeView->currentIndex();
1094 if ( !currentIndex.isValid() )
1113 mLegend->beginCommand( tr(
"Update Legend" ) );
1116 for (
const QString &key : constCustomProperties )
1118 if ( key.startsWith( QLatin1String(
"legend/" ) ) )
1125 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1127 mLegend->updateLegend();
1129 mLegend->endCommand();
1132void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1139 const QList<QModelIndex> selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1140 if ( selectedIndexes.empty() )
1143 mLegend->beginCommand( tr(
"Update Legend" ) );
1144 for (
const QModelIndex &index : selectedIndexes )
1150 currentNode->
setCustomProperty( QStringLiteral(
"showFeatureCount" ), checked ? 1 : 0 );
1152 mLegend->updateFilterByMap();
1153 mLegend->adjustBoxSize();
1154 mLegend->endCommand();
1157void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1159 mLegend->beginCommand( tr(
"Update Legend" ) );
1160 mLegend->setLegendFilterByMapEnabled( checked );
1161 mLegend->adjustBoxSize();
1163 mLegend->endCommand();
1166void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1174 QModelIndex currentIndex = mItemTreeView->currentIndex();
1175 if ( !currentIndex.isValid() )
1186 mLegend->beginCommand( tr(
"Update Legend" ) );
1187 mLegend->updateFilterByMap();
1188 mLegend->adjustBoxSize();
1189 mLegend->endCommand();
1192void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1199 QModelIndex currentIndex = mItemTreeView->currentIndex();
1200 if ( !currentIndex.isValid() )
1207 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1213 QString currentExpression;
1215 currentExpression = QStringLiteral(
"@symbol_label" );
1221 QStringList highlighted;
1224 const QList<QgsLayerTreeModelLegendNode *> legendNodes = model->layerLegendNodes( layerNode,
false );
1225 if ( !legendNodes.isEmpty() )
1227 if (
QgsSymbolLegendNode *symbolNode = qobject_cast<QgsSymbolLegendNode *>( legendNodes.first() ) )
1229 legendContext.
appendScope( symbolNode->createSymbolScope() );
1230 highlighted << QStringLiteral(
"symbol_label" ) << QStringLiteral(
"symbol_id" ) << QStringLiteral(
"symbol_count" );
1243 QgsExpressionBuilderDialog expressiondialog(
nullptr, currentExpression,
nullptr, QStringLiteral(
"generic" ), legendContext );
1244 if ( expressiondialog.exec() )
1247 mItemTreeView->layerTreeModel()->refreshLayerLegend( layerNode );
1250 mLegend->beginCommand( tr(
"Update Legend" ) );
1252 mLegend->adjustBoxSize();
1253 mLegend->endCommand();
1256void QgsLayoutLegendWidget::mUpdateAllPushButton_clicked()
1261void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1265 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1266 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1267 mLegend->updateLegend();
1269 mLegend->endCommand();
1273void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1278 mLegend->setLegendFilterOutAtlas( toggled );
1284void QgsLayoutLegendWidget::updateLegend()
1288 mLegend->beginCommand( tr(
"Update Legend" ) );
1291 mLegend->setAutoUpdateModel(
true );
1292 mLegend->setAutoUpdateModel(
false );
1294 mLegend->endCommand();
1298void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1300 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1301 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1310bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1320 mLegend = qobject_cast<QgsLayoutItemLegend *>( item );
1321 mItemPropertiesWidget->setItem( mLegend );
1323 if ( mMapFilteringWidget )
1324 mMapFilteringWidget->setItem( mLegend );
1328 mItemTreeView->setModel( mLegend->model() );
1337void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1339 mTitleLineEdit->blockSignals( b );
1340 mTitleAlignCombo->blockSignals( b );
1341 mItemTreeView->blockSignals( b );
1342 mCheckBoxAutoUpdate->blockSignals( b );
1343 mMapComboBox->blockSignals( b );
1344 mFilterByMapCheckBox->blockSignals( b );
1345 mColumnCountSpinBox->blockSignals( b );
1346 mSplitLayerCheckBox->blockSignals( b );
1347 mEqualColumnWidthCheckBox->blockSignals( b );
1348 mSymbolWidthSpinBox->blockSignals( b );
1349 mSymbolHeightSpinBox->blockSignals( b );
1350 mMaxSymbolSizeSpinBox->blockSignals( b );
1351 mMinSymbolSizeSpinBox->blockSignals( b );
1352 mGroupSpaceSpinBox->blockSignals( b );
1353 mGroupIndentSpinBox->blockSignals( b );
1354 mSubgroupIndentSpinBox->blockSignals( b );
1355 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1356 mGroupSideSpinBox->blockSignals( b );
1357 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1358 mSubgroupSideSpinBox->blockSignals( b );
1359 mLayerSpaceSpinBox->blockSignals( b );
1360 mSymbolSpaceSpinBox->blockSignals( b );
1361 mSymbolSideSpaceSpinBox->blockSignals( b );
1362 mIconLabelSpaceSpinBox->blockSignals( b );
1363 mBoxSpaceSpinBox->blockSignals( b );
1364 mColumnSpaceSpinBox->blockSignals( b );
1365 mRasterStrokeGroupBox->blockSignals( b );
1366 mRasterStrokeColorButton->blockSignals( b );
1367 mRasterStrokeWidthSpinBox->blockSignals( b );
1368 mWmsLegendWidthSpinBox->blockSignals( b );
1369 mWmsLegendHeightSpinBox->blockSignals( b );
1370 mCheckboxResizeContents->blockSignals( b );
1371 mTitleSpaceBottomSpinBox->blockSignals( b );
1372 mFilterLegendByAtlasCheckBox->blockSignals( b );
1373 mTitleFontButton->blockSignals( b );
1374 mGroupFontButton->blockSignals( b );
1375 mLayerFontButton->blockSignals( b );
1376 mItemFontButton->blockSignals( b );
1377 mWrapCharLineEdit->blockSignals( b );
1378 mMaxWidthSpinBox->blockSignals( b );
1381void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1384 Q_UNUSED( previous )
1386 mLayerExpressionButton->setEnabled(
false );
1388 if ( mLegend && mLegend->autoUpdateModel() )
1399 mLayerExpressionButton->setEnabled(
true );
1403 mCountToolButton->setChecked(
false );
1404 mCountToolButton->setEnabled(
false );
1407 mExpressionFilterButton->blockSignals(
true );
1408 mExpressionFilterButton->setChecked(
false );
1409 mExpressionFilterButton->setEnabled(
false );
1410 mExpressionFilterButton->blockSignals(
false );
1421 mCountToolButton->setChecked( currentNode->
customProperty( QStringLiteral(
"showFeatureCount" ), 0 ).toInt() );
1422 mCountToolButton->setEnabled(
true );
1423 mLayerExpressionButton->setEnabled(
true );
1427 mExpressionFilterButton->blockSignals(
true );
1428 mExpressionFilterButton->setExpressionText( expr );
1429 mExpressionFilterButton->setVectorLayer( vl );
1430 mExpressionFilterButton->setEnabled(
true );
1431 mExpressionFilterButton->setChecked( exprEnabled );
1432 mExpressionFilterButton->blockSignals(
false );
1435void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1437 QAction *a = qobject_cast<QAction *>( sender() );
1438 if ( !a || !mItemTreeView->currentNode() )
1445void QgsLayoutLegendWidget::setLegendMapViewData()
1447 if ( mLegend->linkedMap() )
1451 measurementConverter.
setDpi( dpi );
1454 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1455 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1456 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1460void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1464 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
Qgis::GeometryType::Polygon );
1468void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1470 if ( !mLegend || !idx.isValid() )
1475 if ( mLegend->autoUpdateModel() )
1481 int originalIndex = -1;
1484 originalIndex = _originalLegendNodeIndex( legendNode );
1488 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode, legendNode, originalIndex );
1489 openPanel( widget );
1497QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1502QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1504 if ( !mView->currentNode() )
1507 if ( mWidget->legend()->autoUpdateModel() )
1510 QMenu *menu =
new QMenu();
1514 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1515 menu->addSeparator();
1520 QActionGroup *styleGroup =
new QActionGroup { mWidget };
1521 styleGroup->setExclusive(
true );
1523 QList<Qgis::LegendComponent> lst;
1527 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1528 action->setActionGroup( styleGroup );
1529 action->setCheckable(
true );
1530 action->setChecked( currentStyle == style );
1531 action->setData(
static_cast<int>( style ) );
1546 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1549 setPanelTitle( tr(
"Legend Item Properties" ) );
1558 QString currentLabel;
1561 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1562 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1566 currentLabel = mLayer->name();
1567 QVariant v = mLayer->customProperty( QStringLiteral(
"legend/title-label" ) );
1569 currentLabel = v.toString();
1570 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1572 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1577 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1580 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1581 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1582 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1583 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1584 mPatchGroup->setVisible( mLegendNode || mLayer );
1585 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1586 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1587 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1588 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1589 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1592 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1593 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1597 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1598 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1601 mCustomSymbolCheckBox->setChecked(
false );
1606 patchShape = symbolLegendNode->patchShape();
1608 std::unique_ptr<QgsSymbol> customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() : nullptr );
1609 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1612 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1614 mCustomSymbolButton->setSymbol( customSymbol.release() );
1616 else if ( symbolLegendNode->symbol() )
1618 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1619 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1620 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1623 else if ( !mLegendNode && mLayer )
1625 patchShape = mLayer->patchShape();
1628 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1630 mCustomSymbolCheckBox->setChecked(
true );
1631 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1633 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1637 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1638 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1639 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1646 switch ( qobject_cast<QgsVectorLayer *>( mLayer->layer() )->geometryType() )
1661 mPatchShapeLabel->hide();
1662 mPatchShapeButton->hide();
1665 if ( !patchShape.
isNull() )
1666 mPatchShapeButton->setShape( patchShape );
1670 if ( symbolLegendNode->symbol() )
1672 mPatchShapeButton->setSymbolType( symbolLegendNode->symbol()->type() );
1676 mPatchShapeLabel->hide();
1677 mPatchShapeButton->hide();
1682 mPatchShapeLabel->hide();
1683 mPatchShapeButton->hide();
1688 mLabelGroup->hide();
1689 mColorRampLegendWidget->setSettings( colorRampNode->settings() );
1693 mColorRampLegendWidget->hide();
1706 mCustomSymbolCheckBox->hide();
1715 mLabelEdit->setPlainText( currentLabel );
1716 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1718 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1720 connect( mWidthSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1721 connect( mHeightSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1723 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1726 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1728 connect( mColumnSplitBehaviorComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1732 connectChildPanel( mColorRampLegendWidget );
1735void QgsLayoutLegendNodeWidget::setDockMode(
bool dockMode )
1737 mColorRampLegendWidget->setDockMode( dockMode );
1741void QgsLayoutLegendNodeWidget::labelChanged()
1745 const QString label = mLabelEdit->toPlainText();
1750 else if ( mLegendNode )
1753 mLegend->model()->refreshLayerLegend( mLayer );
1757 mLayer->setCustomProperty( QStringLiteral(
"legend/title-label" ), label );
1761 embeddedNode->setUserLabel( QString() );
1764 mLegend->adjustBoxSize();
1765 mLegend->invalidateCache();
1767 mLegend->endCommand();
1770void QgsLayoutLegendNodeWidget::patchChanged()
1772 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1778 mLegend->model()->refreshLayerLegend( mLayer );
1782 mLayer->setPatchShape( shape );
1783 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1788 mLegend->model()->refreshLayerLegend( mLayer );
1791 mLegend->adjustBoxSize();
1793 mLegend->endCommand();
1796void QgsLayoutLegendNodeWidget::insertExpression()
1804 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1808 if ( mLayer && mLayer->layer() )
1813 context.
setHighlightedVariables( QStringList() << QStringLiteral(
"legend_title" ) << QStringLiteral(
"legend_column_count" ) << QStringLiteral(
"legend_split_layers" ) << QStringLiteral(
"legend_wrap_string" ) << QStringLiteral(
"legend_filter_by_map" ) << QStringLiteral(
"legend_filter_out_atlas" ) );
1817 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1818 if ( exprDlg.exec() == QDialog::Accepted )
1820 expression = exprDlg.expressionText();
1821 if ( !expression.isEmpty() )
1823 mLegend->beginCommand( tr(
"Insert expression" ) );
1824 mLabelEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
1825 mLegend->endCommand();
1830void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1832 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1833 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1838 mLegend->model()->refreshLayerLegend( mLayer );
1842 mLayer->setPatchSize( size );
1843 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1848 mLegend->model()->refreshLayerLegend( mLayer );
1851 mLegend->adjustBoxSize();
1853 mLegend->endCommand();
1856void QgsLayoutLegendNodeWidget::customSymbolChanged()
1858 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1860 if ( mCustomSymbolCheckBox->isChecked() )
1865 mLegend->model()->refreshLayerLegend( mLayer );
1869 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1874 mLegend->model()->refreshLayerLegend( mLayer );
1882 mLegend->model()->refreshLayerLegend( mLayer );
1886 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1891 mLegend->model()->refreshLayerLegend( mLayer );
1895 mLegend->adjustBoxSize();
1897 mLegend->endCommand();
1900void QgsLayoutLegendNodeWidget::colorRampLegendChanged()
1902 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1906 mLegend->model()->refreshLayerLegend( mLayer );
1908 mLegend->adjustBoxSize();
1910 mLegend->endCommand();
1913void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1915 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1920 mLegend->model()->refreshLayerLegend( mLayer );
1924 mLayer->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1928 mNode->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1931 mLegend->adjustBoxSize();
1933 mLegend->endCommand();
1936void QgsLayoutLegendNodeWidget::columnSplitChanged()
1938 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1940 if ( mLayer && !mLegendNode )
1945 mLegend->adjustBoxSize();
1947 mLegend->endCommand();
1954QgsLayoutLegendMapFilteringWidget::QgsLayoutLegendMapFilteringWidget(
QgsLayoutItemLegend *legend )
1956 , mLegendItem( legend )
1959 setPanelTitle( tr(
"Legend Filtering" ) );
1961 setNewItem( legend );
1964bool QgsLayoutLegendMapFilteringWidget::setNewItem(
QgsLayoutItem *item )
1974 mLegendItem = qobject_cast<QgsLayoutItemLegend *>( item );
1981 updateGuiElements();
1986void QgsLayoutLegendMapFilteringWidget::updateGuiElements()
1988 if ( mBlockUpdates )
1991 mBlockUpdates =
true;
1993 if ( mFilterMapItemsListView->model() )
1995 QAbstractItemModel *oldModel = mFilterMapItemsListView->model();
1996 mFilterMapItemsListView->setModel(
nullptr );
1997 oldModel->deleteLater();
2000 QgsLayoutLegendMapFilteringModel *model =
new QgsLayoutLegendMapFilteringModel( mLegendItem, mLegendItem->layout()->itemsModel(), mFilterMapItemsListView );
2001 mFilterMapItemsListView->setModel( model );
2003 mBlockUpdates =
false;
2011 : QSortFilterProxyModel( parent )
2012 , mLayoutModel( layoutModel )
2013 , mLegendItem( legend )
2015 setSourceModel( layoutModel );
2018int QgsLayoutLegendMapFilteringModel::columnCount(
const QModelIndex & )
const
2023QVariant QgsLayoutLegendMapFilteringModel::data(
const QModelIndex &i,
int role )
const
2028 if ( i.column() != 0 )
2033 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( i ) ) );
2041 case Qt::CheckStateRole:
2042 switch ( i.column() )
2047 return Qt::Unchecked;
2049 return mLegendItem->filterByMapItems().contains( mapItem ) ? Qt::Checked : Qt::Unchecked;
2057 return mLayoutModel->data( sourceIndex, role );
2061bool QgsLayoutLegendMapFilteringModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
2065 if ( !index.isValid() )
2068 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2069 if ( !mapItem || !mLegendItem )
2074 mLegendItem->layout()->undoStack()->beginCommand( mLegendItem, tr(
"Change Legend Linked Maps" ) );
2076 QList<QgsLayoutItemMap *> linkedMaps = mLegendItem->filterByMapItems();
2077 if ( value.toBool() )
2079 if ( !linkedMaps.contains( mapItem ) )
2081 linkedMaps.append( mapItem );
2082 mLegendItem->setFilterByMapItems( linkedMaps );
2087 linkedMaps.removeAll( mapItem );
2088 mLegendItem->setFilterByMapItems( linkedMaps );
2090 emit dataChanged( index, index, QVector<int>() << role );
2092 mLegendItem->layout()->undoStack()->endCommand();
2093 mLegendItem->invalidateCache();
2098Qt::ItemFlags QgsLayoutLegendMapFilteringModel::flags(
const QModelIndex &index )
const
2100 Qt::ItemFlags flags = QSortFilterProxyModel::flags( index );
2102 if ( !index.isValid() )
2107 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2108 const bool isMainLinkedMapItem = mLegendItem ? ( mLegendItem->linkedMap() == mapItem ) : false;
2114 if ( !isMainLinkedMapItem )
2116 flags |= Qt::ItemIsEnabled;
2120 flags &= ~Qt::ItemIsEnabled;
2123 switch ( index.column() )
2126 if ( !isMainLinkedMapItem )
2127 return flags | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
2129 return flags | Qt::ItemIsSelectable;
2132 return flags | Qt::ItemIsSelectable;
2136bool QgsLayoutLegendMapFilteringModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
2138 QgsLayoutItem *item = mLayoutModel->itemFromIndex( mLayoutModel->index( source_row, 0, source_parent ) );
LegendComponent
Component of legends which can be styled.
@ Symbol
Symbol icon (excluding label)
@ Group
Legend group title.
@ Hidden
Special style, item is hidden including margins around.
@ Subgroup
Legend subgroup title.
@ SymbolLabel
Symbol label (excluding icon)
void changed()
Emitted when the alignment is changed.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
Settings for a color ramp legend node.
A legend node which renders a color ramp.
A generic dialog for building expression strings.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
static QString findAndSelectActiveExpression(QgsCodeEditor *editor, const QString &pattern=QString())
Find the expression under the cursor in the given editor and select it.
Container of fields for a vector layer.
Layer tree group node serves as a container for layers and further groups.
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position.
void setName(const QString &n) override
Sets the group's name.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group.
QString name() const override
Returns the group's name.
Layer tree node points to a map layer.
void setPatchSize(QSizeF size)
Sets the user (overridden) size for the legend node.
QString labelExpression() const
Returns the expression member of the LayerTreeNode.
LegendNodesSplitBehavior
Legend node column split behavior.
@ AllowSplittingLegendNodesOverMultipleColumns
Allow splitting node's legend nodes across multiple columns.
@ PreventSplittingLegendNodesOverMultipleColumns
Prevent splitting node's legend nodes across multiple columns.
@ UseDefaultLegendSetting
Inherit default legend column splitting setting.
void setLabelExpression(const QString &expression)
set the expression to evaluate
void setPatchShape(const QgsLegendPatchShape &shape)
Sets the symbol patch shape to use when rendering the legend node symbol.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
An abstract interface for legend items returned from QgsMapLayerLegend implementation.
NodeTypes
Types of legend nodes.
@ SimpleLegend
Simple label with icon legend node type.
@ RasterSymbolLegend
Raster symbol legend node type.
@ ImageLegend
Raster image legend node type.
@ DataDefinedSizeLegend
Marker symbol legend node type.
@ WmsLegend
WMS legend node type.
@ EmbeddedWidget
Embedded widget placeholder node type.
@ ColorRampLegend
Color ramp legend.
@ SymbolLegend
Vector symbol legend node type.
@ NodeType
Type of node. Added in 3.16.
QgsLayerTreeModel * model() const
Returns pointer to model owning this legend node.
QgsLayerTreeLayer * layerNode() const
Returns pointer to the parent layer node.
QgsLayerTreeModelLegendNode * legendNodeEmbeddedInParent(QgsLayerTreeLayer *nodeLayer) const
Returns legend node that may be embedded in parent (i.e.
QList< QgsLayerTreeModelLegendNode * > layerOriginalLegendNodes(QgsLayerTreeLayer *nodeLayer)
Returns original (unfiltered) list of legend nodes attached to a particular layer node.
Base class for nodes in a layer tree.
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
QStringList customProperties() const
Returns list of keys stored in custom properties.
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance.
static void setLegendFilterByExpression(QgsLayerTreeLayer &layer, const QString &expr, bool enabled=true)
Sets the expression filter of a legend layer.
static QString legendFilterByExpression(const QgsLayerTreeLayer &layer, bool *enabled=nullptr)
Returns the expression filter of a legend layer.
Extends QTreeView and provides additional functionality when working with a layer tree.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
Used to render QgsLayout as an atlas, by iterating over the features from an associated vector layer.
void toggled(bool enabled)
Emitted when atlas is enabled or disabled.
A common interface for layout designer dialogs and widgets.
virtual QgsMessageBar * messageBar()=0
Returns the designer's message bar.
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
A layout item subclass for map legends.
QgsLegendModel * model()
Returns the legend model.
Layout graphical items for displaying a map.
@ LayoutLegend
Legend item.
Base class for graphical items within a QgsLayout.
@ UndoLegendMinSymbolSize
Legend minimum symbol size.
@ UndoLegendTitleSpaceBottom
Legend title space.
@ UndoLegendIconSymbolSpace
Legend icon symbol space.
@ UndoLegendLayerFont
Legend layer font.
@ UndoLegendBoxSpace
Legend box space.
@ UndoLegendRasterStrokeColor
Legend raster stroke color.
@ UndoLegendTitleFont
Legend title font.
@ UndoLegendItemFont
Legend item font.
@ UndoLegendWmsLegendWidth
Legend WMS width.
@ UndoLegendLayerSpace
Legend layer spacing.
@ UndoLegendColumnSpace
Legend column space.
@ UndoLegendMaxSymbolSize
Legend maximum symbol size.
@ UndoLegendAutoWrapAfter
Legend auto wrap lines after distance.
@ UndoLegendSymbolSpace
Legend symbol spacing.
@ UndoLegendSymbolWidth
Legend symbol width.
@ UndoLegendColumnCount
Legend column count.
@ UndoLegendSymbolHeight
Legend symbol height.
@ UndoLegendGroupSpace
Legend group spacing.
@ UndoLegendSubgroupIndent
Legend subgroup indent.
@ UndoLegendRasterStrokeWidth
Legend raster stroke width.
@ UndoLegendGroupIndent
Legend group indent.
@ UndoLegendText
Legend text.
@ UndoLegendWmsLegendHeight
Legend WMS height.
@ UndoLegendGroupFont
Legend group font.
int type() const override
Returns a unique graphics item type identifier.
A dialog to add new layers to the legend.
Provides a method of converting QgsLayoutMeasurements from one unit to another.
QgsLayoutMeasurement convert(QgsLayoutMeasurement measurement, Qgis::LayoutUnit targetUnits) const
Converts a measurement from one unit to another.
void setDpi(const double dpi)
Sets the dots per inch (dpi) for the measurement converter.
A model for items attached to a layout.
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
@ LegendAutoWrapWidth
Legend text automatic wrapping width.
@ LegendTitle
Legend title.
@ LegendColumnCount
Legend column count.
void layerChanged(QgsVectorLayer *layer)
Emitted when the context's layer is changed.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
QgsLayoutReportContext & reportContext()
Returns a reference to the layout's report context, which stores information relating to the current ...
Item model implementation based on layer tree model for layout legend.
Represents a patch shape for use in map legends.
void setSymbolType(Qgis::SymbolType type)
Sets the symbol type associated with this patch.
bool isNull() const
Returns true if the patch shape is a null QgsLegendPatchShape, which indicates that the default legen...
static void setNodeLegendStyle(QgsLayerTreeNode *node, Qgis::LegendComponent style)
Sets the style of a node.
static Qgis::LegendComponent nodeLegendStyle(QgsLayerTreeNode *node, QgsLayerTreeModel *model)
Returns the style for the given node, within the specified model.
static QString styleLabel(Qgis::LegendComponent s)
Returns a translated string representing a style component, for use in UI.
Map canvas is a class for displaying all GIS data types on a canvas.
static void setLegendNodeOrder(QgsLayerTreeLayer *nodeLayer, const QList< int > &order)
static void setLegendNodeColorRampSettings(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsColorRampLegendNodeSettings *settings)
Sets a custom legend color ramp settings for the legend node belonging to nodeLayer at the specified ...
static void setLegendNodeCustomSymbol(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsSymbol *symbol)
Sets a custom legend symbol for the legend node belonging to nodeLayer at the specified originalIndex...
static void setLegendNodeUserLabel(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QString &newLabel)
static void setLegendNodeSymbolSize(QgsLayerTreeLayer *nodeLayer, int originalIndex, QSizeF size)
Sets the legend symbol size for the legend node belonging to nodeLayer at the specified originalIndex...
static void setLegendNodeColumnBreak(QgsLayerTreeLayer *nodeLayer, int originalIndex, bool columnBreakBeforeNode)
Sets whether a forced column break should occur before the node.
static void setLegendNodePatchShape(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsLegendPatchShape &shape)
Sets the legend patch shape for the legend node belonging to nodeLayer at the specified originalIndex...
static QList< int > legendNodeOrder(QgsLayerTreeLayer *nodeLayer)
Base class for all map layer types.
Interface for master layout type objects, such as print layouts and reports.
static int qtDefaultDpiX()
Returns the default Qt horizontal DPI.
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
Abstract base class for all rendered symbols.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based dataset.
QgsExpressionContextScope * createExpressionContextScope() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
QgsLayerTreeModelLegendNode * legendNode(const QString &rule, QgsLayerTreeModel &model)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.