47#include <QActionGroup>
48#include <QInputDialog>
53#include "moc_qgslayoutlegendwidget.cpp"
55using namespace Qt::StringLiterals;
72 int unfilteredNodeIndex = _unfilteredLegendNodeIndex( legendNode );
74 return ( unfilteredNodeIndex >= 0 && unfilteredNodeIndex < order.count() ? order[unfilteredNodeIndex] : -1 );
77 void _moveLegendNode(
QgsLayerTreeLayer *nodeLayer,
int legendNodeIndex,
int destLegendNodeIndex )
80 const int offset = destLegendNodeIndex - legendNodeIndex;
82 if ( legendNodeIndex < 0 || legendNodeIndex >= order.count() )
84 if ( legendNodeIndex + offset < 0 || legendNodeIndex + offset >= order.count() )
87 int id = order.takeAt( legendNodeIndex );
88 order.insert( legendNodeIndex + offset,
id );
97 , mMapCanvas( mapCanvas )
107 connect( mWrapCharLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
108 connect( mTitleLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
113 connect( mColumnCountSpinBox,
static_cast<void ( QSpinBox::* )(
int )
>( &QSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
114 connect( mSplitLayerCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
115 connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
116 connect( mSymbolWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged );
117 connect( mSymbolHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged );
118 connect( mMaxSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged );
119 connect( mMinSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged );
120 connect( mWmsLegendWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
121 connect( mWmsLegendHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
122 connect( mTitleSpaceBottomSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
123 connect( mGroupSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
124 connect( mGroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged );
125 connect( mSubgroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged );
126 connect( mSpaceBelowGroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
127 connect( mGroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
128 connect( mLayerSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
129 connect( mSpaceBelowSubgroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
130 connect( mSubgroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
131 connect( mSymbolSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
132 connect( mSymbolSideSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
133 connect( mIconLabelSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
134 connect( mBoxSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
135 connect( mColumnSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged );
136 connect( mMaxWidthSpinBox, qOverload< double >( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::maxWidthChanged );
137 connect( mSyncModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ),
this, [
this] { syncModeChanged(
true ); } );
138 connect( mCheckboxResizeContents, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mCheckboxResizeContents_toggled );
139 connect( mRasterStrokeGroupBox, &QgsCollapsibleGroupBoxBasic::toggled,
this, &QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled );
140 connect( mRasterStrokeWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged );
141 connect( mRasterStrokeColorButton, &
QgsColorButton::colorChanged,
this, &QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged );
142 connect( mExpandAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::expandLegendTree );
143 connect( mCollapseAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::collapseLegendTree );
144 connect( mMoveDownToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveDownToolButton_clicked );
145 connect( mMoveUpToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveUpToolButton_clicked );
146 connect( mRemoveToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mRemoveToolButton_clicked );
147 connect( mAddToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddToolButton_clicked );
148 connect( mEditPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mEditPushButton_clicked );
149 connect( mCountToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mCountToolButton_clicked );
150 connect( mExpressionFilterButton, &QgsLegendFilterButton::toggled,
this, &QgsLayoutLegendWidget::mExpressionFilterButton_toggled );
151 connect( mLayerExpressionButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mLayerExpressionButton_clicked );
152 connect( mFilterByMapCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled );
153 connect( mAddGroupToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddGroupToolButton_clicked );
154 connect( mFilterLegendByAtlasCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled );
155 connect( mItemTreeView, &QgsLayerTreeView::doubleClicked,
this, &QgsLayoutLegendWidget::mItemTreeView_doubleClicked );
157 QMenu *resetMenu =
new QMenu( mResetLayersButton );
158 QAction *resetToProjectLayersAction =
new QAction( tr(
"Reset to All Project Layers" ), resetMenu );
159 resetMenu->addAction( resetToProjectLayersAction );
161 QAction *resetToVisibleLayersAction =
new QAction( tr(
"Reset to Visible Layers" ), resetMenu );
162 resetMenu->addAction( resetToVisibleLayersAction );
164 mResetLayersButton->setMenu( resetMenu );
165 mResetLayersButton->setPopupMode( QToolButton::InstantPopup );
167 connect( mFilterByMapCheckBox, &QCheckBox::toggled, mButtonLinkedMaps, &QWidget::setEnabled );
168 mButtonLinkedMaps->setEnabled(
false );
169 connect( mButtonLinkedMaps, &QToolButton::clicked,
this, [
this] {
172 mMapFilteringWidget =
new QgsLayoutLegendMapFilteringWidget( mLegend );
173 openPanel( mMapFilteringWidget );
177 setPanelTitle( tr(
"Legend Properties" ) );
184 mTitleAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
185 mGroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
186 mSubgroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
187 mItemAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
189 mArrangementCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignRight );
191 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignLeft, tr(
"Symbols on Left" ),
QgsApplication::getThemeIcon( u
"/mIconArrangeSymbolsLeft.svg"_s ) );
192 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignRight, tr(
"Symbols on Right" ),
QgsApplication::getThemeIcon( u
"/mIconArrangeSymbolsRight.svg"_s ) );
194 mSpaceBelowGroupHeadingSpinBox->setClearValue( 0 );
195 mGroupSideSpinBox->setClearValue( 0 );
196 mSpaceBelowSubgroupHeadingSpinBox->setClearValue( 0 );
197 mSubgroupSideSpinBox->setClearValue( 0 );
198 mSymbolSideSpaceSpinBox->setClearValue( 0 );
200 mMaxWidthSpinBox->setShowClearButton(
true );
201 mMaxWidthSpinBox->setClearValue( 0, tr(
"Disabled" ) );
226 mRasterStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
227 mRasterStrokeColorButton->setAllowOpacity(
true );
228 mRasterStrokeColorButton->setContext( u
"composer "_s );
230 mMapComboBox->setCurrentLayout( legend->
layout() );
236 mainLayout->addWidget( mItemPropertiesWidget );
238 mItemTreeView->setHeaderHidden(
true );
240 mLegendProxyModel =
new QgsLegendLayerTreeProxyModel( legend,
this );
242 mItemTreeView->setModel( legend->
model(), mLegendProxyModel );
243 mItemTreeView->setMenuProvider(
new QgsLayoutLegendMenuProvider( mItemTreeView,
this ) );
244 setLegendMapViewData();
250 connect( layoutAtlas(), &
QgsLayoutAtlas::toggled,
this, &QgsLayoutLegendWidget::updateFilterLegendByAtlasButton );
254 mTitleFontButton->registerExpressionContextGenerator(
this );
255 mGroupFontButton->registerExpressionContextGenerator(
this );
256 mLayerFontButton->registerExpressionContextGenerator(
this );
257 mItemFontButton->registerExpressionContextGenerator(
this );
258 mExpressionFilterButton->registerExpressionContextGenerator(
this );
260 mTitleFontButton->setLayer( coverageLayer() );
261 mGroupFontButton->setLayer( coverageLayer() );
262 mLayerFontButton->setLayer( coverageLayer() );
263 mItemFontButton->setLayer( coverageLayer() );
264 if ( mLegend->layout() )
278 connect( mItemTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsLayoutLegendWidget::selectedChanged );
287 if ( mItemPropertiesWidget )
288 mItemPropertiesWidget->setMasterLayout( masterLayout );
294 mTitleFontButton->setMessageBar( iface->
messageBar() );
295 mGroupFontButton->setMessageBar( iface->
messageBar() );
296 mLayerFontButton->setMessageBar( iface->
messageBar() );
297 mItemFontButton->setMessageBar( iface->
messageBar() );
300void QgsLayoutLegendWidget::setGuiElements()
307 blockAllSignals(
true );
308 mTitleLineEdit->setText( mLegend->title() );
309 whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
313 whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
314 mFilterByMapCheckBox->setChecked( mLegend->legendFilterByMapEnabled() );
315 mButtonLinkedMaps->setEnabled( mLegend->legendFilterByMapEnabled() );
316 mColumnCountSpinBox->setValue( mLegend->columnCount() );
317 mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
318 mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
319 mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
320 mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
321 mMaxSymbolSizeSpinBox->setValue( mLegend->maximumSymbolSize() );
322 mMinSymbolSizeSpinBox->setValue( mLegend->minimumSymbolSize() );
323 mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
324 mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
338 mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
339 mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
341 mMaxWidthSpinBox->setValue( mLegend->autoWrapLinesAfter() );
343 mRasterStrokeGroupBox->setChecked( mLegend->drawRasterStroke() );
344 mRasterStrokeWidthSpinBox->setValue( mLegend->rasterStrokeWidth() );
345 mRasterStrokeColorButton->setColor( mLegend->rasterStrokeColor() );
347 mSyncModeCombo->setCurrentIndex( mSyncModeCombo->findData( QVariant::fromValue( mLegend->syncMode() ) ) );
349 mCheckboxResizeContents->setChecked( mLegend->resizeToContents() );
350 mFilterLegendByAtlasCheckBox->setChecked( mLegend->legendFilterOutAtlas() );
351 mWrapCharLineEdit->setText( mLegend->wrapString() );
354 mMapComboBox->setItem( map );
360 blockAllSignals(
false );
362 syncModeChanged(
false );
363 updateDataDefinedButton( mLegendTitleDDBtn );
364 updateDataDefinedButton( mColumnsDDBtn );
367void QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged(
const QString &text )
371 mLegend->beginCommand( tr(
"Change Legend Wrap" ) );
372 mLegend->setWrapString( text );
373 mLegend->adjustBoxSize();
375 mLegend->endCommand();
379void QgsLayoutLegendWidget::mTitleLineEdit_textChanged(
const QString &text )
384 mLegend->setTitle( text );
385 mLegend->adjustBoxSize();
387 mLegend->endCommand();
391void QgsLayoutLegendWidget::titleAlignmentChanged()
395 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
396 mLegend->beginCommand( tr(
"Change Title Alignment" ) );
397 mLegend->setTitleAlignment( alignment );
399 mLegend->endCommand();
403void QgsLayoutLegendWidget::groupAlignmentChanged()
407 mLegend->beginCommand( tr(
"Change Group Alignment" ) );
410 mLegend->endCommand();
414void QgsLayoutLegendWidget::subgroupAlignmentChanged()
418 mLegend->beginCommand( tr(
"Change Subgroup Alignment" ) );
421 mLegend->endCommand();
425void QgsLayoutLegendWidget::itemAlignmentChanged()
429 mLegend->beginCommand( tr(
"Change Item Alignment" ) );
432 mLegend->endCommand();
436void QgsLayoutLegendWidget::arrangementChanged()
440 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
441 mLegend->beginCommand( tr(
"Change Legend Arrangement" ) );
442 mLegend->setSymbolAlignment( alignment );
444 mLegend->endCommand();
448void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged(
int c )
453 mLegend->setColumnCount(
c );
454 mLegend->adjustBoxSize();
456 mLegend->endCommand();
458 mSplitLayerCheckBox->setEnabled(
c > 1 );
459 mEqualColumnWidthCheckBox->setEnabled(
c > 1 );
462void QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled(
bool checked )
466 mLegend->beginCommand( tr(
"Split Legend Layers" ) );
467 mLegend->setSplitLayer( checked );
468 mLegend->adjustBoxSize();
470 mLegend->endCommand();
474void QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled(
bool checked )
478 mLegend->beginCommand( tr(
"Legend Column Width" ) );
479 mLegend->setEqualColumnWidth( checked );
480 mLegend->adjustBoxSize();
482 mLegend->endCommand();
486void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged(
double d )
491 mLegend->setSymbolWidth( d );
492 mLegend->adjustBoxSize();
494 mLegend->endCommand();
498void QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged(
double d )
503 mLegend->setMaximumSymbolSize( d );
504 mLegend->adjustBoxSize();
506 mLegend->endCommand();
510void QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged(
double d )
515 mLegend->setMinimumSymbolSize( d );
516 mLegend->adjustBoxSize();
518 mLegend->endCommand();
522void QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged(
double d )
527 mLegend->setSymbolHeight( d );
528 mLegend->adjustBoxSize();
530 mLegend->endCommand();
534void QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged(
double d )
539 mLegend->setWmsLegendWidth( d );
540 mLegend->adjustBoxSize();
542 mLegend->endCommand();
546void QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged(
double d )
551 mLegend->setWmsLegendHeight( d );
552 mLegend->adjustBoxSize();
554 mLegend->endCommand();
558void QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged(
double d )
564 mLegend->adjustBoxSize();
566 mLegend->endCommand();
570void QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged(
double d )
576 mLegend->adjustBoxSize();
578 mLegend->endCommand();
582void QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged(
double d )
588 mLegend->adjustBoxSize();
590 mLegend->endCommand();
594void QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged(
double d )
600 mLegend->adjustBoxSize();
602 mLegend->endCommand();
606void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged(
double space )
612 mLegend->adjustBoxSize();
614 mLegend->endCommand();
618void QgsLayoutLegendWidget::spaceGroupSideChanged(
double space )
624 mLegend->adjustBoxSize();
626 mLegend->endCommand();
630void QgsLayoutLegendWidget::spaceSubGroupSideChanged(
double space )
636 mLegend->adjustBoxSize();
638 mLegend->endCommand();
642void QgsLayoutLegendWidget::spaceSymbolSideChanged(
double space )
648 mLegend->adjustBoxSize();
650 mLegend->endCommand();
654void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged(
double d )
660 mLegend->adjustBoxSize();
662 mLegend->endCommand();
666void QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged(
double d )
674 mLegend->adjustBoxSize();
676 mLegend->endCommand();
680void QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged(
double d )
686 mLegend->adjustBoxSize();
688 mLegend->endCommand();
692void QgsLayoutLegendWidget::titleFontChanged()
698 mLegend->adjustBoxSize();
700 mLegend->endCommand();
704void QgsLayoutLegendWidget::groupFontChanged()
710 mLegend->adjustBoxSize();
712 mLegend->endCommand();
716void QgsLayoutLegendWidget::layerFontChanged()
722 mLegend->adjustBoxSize();
724 mLegend->endCommand();
728void QgsLayoutLegendWidget::itemFontChanged()
734 mLegend->adjustBoxSize();
736 mLegend->endCommand();
740void QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged(
double space )
746 mLegend->adjustBoxSize();
748 mLegend->endCommand();
752void QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged(
double d )
757 mLegend->setBoxSpace( d );
758 mLegend->adjustBoxSize();
760 mLegend->endCommand();
764void QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged(
double d )
769 mLegend->setColumnSpace( d );
770 mLegend->adjustBoxSize();
772 mLegend->endCommand();
776void QgsLayoutLegendWidget::maxWidthChanged(
double width )
781 mLegend->setAutoWrapLinesAfter( width );
782 mLegend->adjustBoxSize();
784 mLegend->endCommand();
788void QgsLayoutLegendWidget::mMoveDownToolButton_clicked()
795 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
796 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
797 const QModelIndex parentIndex = sourceIndex.parent();
798 if ( !sourceIndex.isValid() || sourceIndex.row() == mItemTreeView->layerTreeModel()->rowCount( parentIndex ) - 1 )
803 if ( !node && !legendNode )
806 mLegend->beginCommand( tr(
"Moved Legend Item Down" ) );
817 const QModelIndex nextIndex = index.siblingAtRow( index.row() + 1 );
819 if ( nextLegendNode )
821 _moveLegendNode(
legendNode->
layerNode(), _unfilteredLegendNodeIndex( legendNode ), _unfilteredLegendNodeIndex( nextLegendNode ) );
826 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() + 1, 0, parentIndex ) ) );
829 mLegend->endCommand();
832void QgsLayoutLegendWidget::mMoveUpToolButton_clicked()
839 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
840 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
841 const QModelIndex parentIndex = sourceIndex.parent();
842 if ( !sourceIndex.isValid() || sourceIndex.row() == 0 )
847 if ( !node && !legendNode )
850 mLegend->beginCommand( tr(
"Move Legend Item Up" ) );
861 const QModelIndex prevIndex = index.siblingAtRow( index.row() - 1 );
863 if ( prevLegendNode )
865 _moveLegendNode(
legendNode->
layerNode(), _unfilteredLegendNodeIndex( legendNode ), _unfilteredLegendNodeIndex( prevLegendNode ) );
870 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() - 1, 0, parentIndex ) ) );
873 mLegend->endCommand();
876void QgsLayoutLegendWidget::expandLegendTree()
878 mItemTreeView->expandAll();
881void QgsLayoutLegendWidget::collapseLegendTree()
883 mItemTreeView->collapseAll();
886void QgsLayoutLegendWidget::syncModeChanged(
bool userTriggered )
891 mLegend->beginCommand( tr(
"Change Sync Mode" ) );
893 mLegend->setSyncMode( mode );
895 mLegend->endCommand();
898 mLegendProxyModel->setSyncMode( mode );
901 bool allowEdits =
false;
914 QList<QWidget *> widgets;
916 << mMoveDownToolButton
922 << mResetLayersButton
923 << mAddGroupToolButton
924 << mExpressionFilterButton
925 << mCollapseAllToolButton
926 << mExpandAllToolButton;
927 for ( QWidget *w : std::as_const( widgets ) )
928 w->setEnabled( allowEdits );
933 selectedChanged( QModelIndex(), QModelIndex() );
934 mItemTreeView->proxyModel()->setShowPrivateLayers(
true );
938 mItemTreeView->proxyModel()->setShowPrivateLayers(
false );
942void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
958 mLegend->beginCommand( tr(
"Change Legend Map" ) );
959 mLegend->setLinkedMap( map );
961 mLegend->endCommand();
963 setLegendMapViewData();
967void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
974 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
975 mLegend->setResizeToContents( checked );
977 mLegend->adjustBoxSize();
979 mLegend->endCommand();
982void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
989 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
990 mLegend->setDrawRasterStroke( state );
991 mLegend->adjustBoxSize();
993 mLegend->endCommand();
996void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
1004 mLegend->setRasterStrokeWidth( d );
1005 mLegend->adjustBoxSize();
1007 mLegend->endCommand();
1010void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
1018 mLegend->setRasterStrokeColor( newColor );
1020 mLegend->endCommand();
1023void QgsLayoutLegendWidget::mAddToolButton_clicked()
1030 QList<QgsMapLayer *> visibleLayers;
1031 if ( mLegend->linkedMap() )
1033 visibleLayers = mLegend->linkedMap()->layersToRender();
1035 if ( visibleLayers.isEmpty() )
1038 visibleLayers = mMapCanvas->layers(
true );
1042 addDialog.setVisibleLayers( visibleLayers );
1043 if ( addDialog.exec() == QDialog::Accepted )
1045 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
1046 if ( !layers.empty() )
1048 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
1051 mLegend->model()->rootGroup()->addLayer( layer );
1053 mLegend->updateLegend();
1055 mLegend->endCommand();
1060void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
1067 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
1068 if ( !selectionModel )
1073 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
1075 QList<QPersistentModelIndex> proxyIndexes;
1076 const QModelIndexList viewSelection = selectionModel->selectedIndexes();
1077 for (
const QModelIndex &index : viewSelection )
1078 proxyIndexes << index;
1081 QHash<QgsLayerTreeLayer *, QList<int>> nodesWithRemoval;
1082 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1087 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex( legendNode ) );
1090 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
1092 QList<int> toDelete = it.value();
1093 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
1096 for (
int i : std::as_const( toDelete ) )
1098 if ( i >= 0 && i < order.count() )
1099 order.removeAt( i );
1103 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
1107 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1109 if ( proxyIndex.isValid() && mItemTreeView->index2node( proxyIndex ) )
1111 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( proxyIndex );
1112 mLegend->model()->removeRow( sourceIndex.row(), sourceIndex.parent() );
1116 mLegend->updateLegend();
1118 mLegend->endCommand();
1121void QgsLayoutLegendWidget::mEditPushButton_clicked()
1128 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
1129 mItemTreeView_doubleClicked( idx );
1132void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
1140 QModelIndex currentIndex = mItemTreeView->currentIndex();
1141 if ( !currentIndex.isValid() )
1160 mLegend->beginCommand( tr(
"Update Legend" ) );
1163 for (
const QString &key : constCustomProperties )
1165 if ( key.startsWith(
"legend/"_L1 ) )
1172 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1174 mLegend->updateLegend();
1176 mLegend->endCommand();
1179void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1186 const QList<QModelIndex> selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1187 if ( selectedIndexes.empty() )
1190 mLegend->beginCommand( tr(
"Update Legend" ) );
1191 for (
const QModelIndex &index : selectedIndexes )
1199 mLegend->updateFilterByMap();
1200 mLegend->adjustBoxSize();
1201 mLegend->endCommand();
1204void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1206 mLegend->beginCommand( tr(
"Update Legend" ) );
1207 mLegend->setLegendFilterByMapEnabled( checked );
1208 mLegend->adjustBoxSize();
1210 mLegend->endCommand();
1218 mLegend->beginCommand( tr(
"Update Legend" ) );
1219 mLegend->resetManualLayers( mode );
1221 mLegend->endCommand();
1224void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1232 QModelIndex currentIndex = mItemTreeView->currentIndex();
1233 if ( !currentIndex.isValid() )
1244 mLegend->beginCommand( tr(
"Update Legend" ) );
1245 mLegend->updateFilterByMap();
1246 mLegend->adjustBoxSize();
1247 mLegend->endCommand();
1250void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1257 QModelIndex currentIndex = mItemTreeView->currentIndex();
1258 if ( !currentIndex.isValid() )
1265 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1271 QString currentExpression;
1273 currentExpression = u
"@symbol_label"_s;
1279 QStringList highlighted;
1282 const QList<QgsLayerTreeModelLegendNode *> legendNodes = model->layerLegendNodes( layerNode,
false );
1283 if ( !legendNodes.isEmpty() )
1285 if (
QgsSymbolLegendNode *symbolNode = qobject_cast<QgsSymbolLegendNode *>( legendNodes.first() ) )
1287 legendContext.
appendScope( symbolNode->createSymbolScope() );
1288 highlighted << u
"symbol_label"_s << u
"symbol_id"_s << u
"symbol_count"_s;
1302 if ( expressiondialog.exec() )
1305 mItemTreeView->layerTreeModel()->refreshLayerLegend( layerNode );
1308 mLegend->beginCommand( tr(
"Update Legend" ) );
1310 mLegend->adjustBoxSize();
1311 mLegend->endCommand();
1314void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1318 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1319 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1320 mLegend->updateLegend();
1322 mLegend->endCommand();
1326void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1331 mLegend->setLegendFilterOutAtlas( toggled );
1337void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1339 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1340 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1349bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1359 mLegend = qobject_cast<QgsLayoutItemLegend *>( item );
1360 mItemPropertiesWidget->setItem( mLegend );
1362 if ( mMapFilteringWidget )
1363 mMapFilteringWidget->setItem( mLegend );
1367 mLegendProxyModel =
new QgsLegendLayerTreeProxyModel( mLegend,
this );
1369 mItemTreeView->setModel( mLegend->model(), mLegendProxyModel );
1379void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1381 mTitleLineEdit->blockSignals( b );
1382 mTitleAlignCombo->blockSignals( b );
1383 mItemTreeView->blockSignals( b );
1384 mSyncModeCombo->blockSignals( b );
1385 mMapComboBox->blockSignals( b );
1386 mFilterByMapCheckBox->blockSignals( b );
1387 mColumnCountSpinBox->blockSignals( b );
1388 mSplitLayerCheckBox->blockSignals( b );
1389 mEqualColumnWidthCheckBox->blockSignals( b );
1390 mSymbolWidthSpinBox->blockSignals( b );
1391 mSymbolHeightSpinBox->blockSignals( b );
1392 mMaxSymbolSizeSpinBox->blockSignals( b );
1393 mMinSymbolSizeSpinBox->blockSignals( b );
1394 mGroupSpaceSpinBox->blockSignals( b );
1395 mGroupIndentSpinBox->blockSignals( b );
1396 mSubgroupIndentSpinBox->blockSignals( b );
1397 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1398 mGroupSideSpinBox->blockSignals( b );
1399 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1400 mSubgroupSideSpinBox->blockSignals( b );
1401 mLayerSpaceSpinBox->blockSignals( b );
1402 mSymbolSpaceSpinBox->blockSignals( b );
1403 mSymbolSideSpaceSpinBox->blockSignals( b );
1404 mIconLabelSpaceSpinBox->blockSignals( b );
1405 mBoxSpaceSpinBox->blockSignals( b );
1406 mColumnSpaceSpinBox->blockSignals( b );
1407 mRasterStrokeGroupBox->blockSignals( b );
1408 mRasterStrokeColorButton->blockSignals( b );
1409 mRasterStrokeWidthSpinBox->blockSignals( b );
1410 mWmsLegendWidthSpinBox->blockSignals( b );
1411 mWmsLegendHeightSpinBox->blockSignals( b );
1412 mCheckboxResizeContents->blockSignals( b );
1413 mTitleSpaceBottomSpinBox->blockSignals( b );
1414 mFilterLegendByAtlasCheckBox->blockSignals( b );
1415 mTitleFontButton->blockSignals( b );
1416 mGroupFontButton->blockSignals( b );
1417 mLayerFontButton->blockSignals( b );
1418 mItemFontButton->blockSignals( b );
1419 mWrapCharLineEdit->blockSignals( b );
1420 mMaxWidthSpinBox->blockSignals( b );
1423void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1426 Q_UNUSED( previous )
1428 mLayerExpressionButton->setEnabled(
false );
1441 mLayerExpressionButton->setEnabled(
true );
1445 mCountToolButton->setChecked(
false );
1446 mCountToolButton->setEnabled(
false );
1449 mExpressionFilterButton->blockSignals(
true );
1450 mExpressionFilterButton->setChecked(
false );
1451 mExpressionFilterButton->setEnabled(
false );
1452 mExpressionFilterButton->blockSignals(
false );
1463 mCountToolButton->setChecked( currentNode->
customProperty( u
"showFeatureCount"_s, 0 ).toInt() );
1464 mCountToolButton->setEnabled(
true );
1465 mLayerExpressionButton->setEnabled(
true );
1469 mExpressionFilterButton->blockSignals(
true );
1470 mExpressionFilterButton->setExpressionText( expr );
1471 mExpressionFilterButton->setVectorLayer( vl );
1472 mExpressionFilterButton->setEnabled(
true );
1473 mExpressionFilterButton->setChecked( exprEnabled );
1474 mExpressionFilterButton->blockSignals(
false );
1477void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1479 QAction *a = qobject_cast<QAction *>( sender() );
1480 if ( !a || !mItemTreeView->currentNode() )
1487void QgsLayoutLegendWidget::setLegendMapViewData()
1489 if ( mLegend->linkedMap() )
1493 measurementConverter.
setDpi( dpi );
1496 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1497 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1498 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1502void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1506 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
Qgis::GeometryType::Polygon );
1510void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1512 if ( !mLegend || !idx.isValid() )
1523 int originalIndex = -1;
1526 originalIndex = _originalLegendNodeIndex( legendNode );
1530 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode, legendNode, originalIndex );
1531 openPanel( widget );
1539QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1544QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1546 if ( !mView->currentNode() )
1552 QMenu *menu =
new QMenu();
1556 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1557 menu->addSeparator();
1562 QActionGroup *styleGroup =
new QActionGroup { mWidget };
1563 styleGroup->setExclusive(
true );
1565 QList<Qgis::LegendComponent> lst;
1569 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1570 action->setActionGroup( styleGroup );
1571 action->setCheckable(
true );
1572 action->setChecked( currentStyle == style );
1573 action->setData(
static_cast<int>( style ) );
1588 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1591 setPanelTitle( tr(
"Legend Item Properties" ) );
1600 QString currentLabel;
1603 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1604 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1608 currentLabel = mLayer->name();
1609 QVariant v = mLayer->customProperty( u
"legend/title-label"_s );
1611 currentLabel = v.toString();
1612 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( u
"legend/column-break"_s ).toInt() );
1614 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1619 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( u
"legend/column-break"_s ).toInt() );
1622 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1623 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1624 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1625 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1626 mPatchGroup->setVisible( mLegendNode || mLayer );
1627 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1628 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1629 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1630 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1631 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1634 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1635 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1639 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1640 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1643 mCustomSymbolCheckBox->setChecked(
false );
1648 patchShape = symbolLegendNode->patchShape();
1650 std::unique_ptr<QgsSymbol> customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() :
nullptr );
1651 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1654 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1655 mCustomSymbolButton->setSymbolType( customSymbol->type() );
1656 mCustomSymbolButton->setSymbol( customSymbol.release() );
1658 else if ( symbolLegendNode->symbol() )
1660 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1661 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1662 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1665 else if ( !mLegendNode && mLayer )
1667 patchShape = mLayer->patchShape();
1670 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1672 mCustomSymbolCheckBox->setChecked(
true );
1673 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1674 mCustomSymbolButton->setSymbolType( customSymbol->type() );
1675 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1679 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1680 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1681 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1688 switch ( qobject_cast<QgsVectorLayer *>( mLayer->layer() )->geometryType() )
1703 mPatchShapeLabel->hide();
1704 mPatchShapeButton->hide();
1707 if ( !patchShape.
isNull() )
1708 mPatchShapeButton->setShape( patchShape );
1712 if ( symbolLegendNode->symbol() )
1714 mPatchShapeButton->setSymbolType( symbolLegendNode->symbol()->type() );
1718 mPatchShapeLabel->hide();
1719 mPatchShapeButton->hide();
1724 mPatchShapeLabel->hide();
1725 mPatchShapeButton->hide();
1730 mLabelGroup->hide();
1731 mColorRampLegendWidget->setSettings( colorRampNode->settings() );
1735 mColorRampLegendWidget->hide();
1748 mCustomSymbolCheckBox->hide();
1757 mLabelEdit->setPlainText( currentLabel );
1758 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1760 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1762 connect( mWidthSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1763 connect( mHeightSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1765 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1768 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1770 connect( mColumnSplitBehaviorComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1774 connectChildPanel( mColorRampLegendWidget );
1777void QgsLayoutLegendNodeWidget::setDockMode(
bool dockMode )
1779 mColorRampLegendWidget->setDockMode( dockMode );
1783void QgsLayoutLegendNodeWidget::labelChanged()
1787 const QString label = mLabelEdit->toPlainText();
1792 else if ( mLegendNode )
1795 mLegend->model()->refreshLayerLegend( mLayer );
1799 mLayer->setCustomProperty( u
"legend/title-label"_s, label );
1803 embeddedNode->setUserLabel( QString() );
1806 mLegend->adjustBoxSize();
1807 mLegend->invalidateCache();
1809 mLegend->endCommand();
1812void QgsLayoutLegendNodeWidget::patchChanged()
1814 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1820 mLegend->model()->refreshLayerLegend( mLayer );
1824 mLayer->setPatchShape( shape );
1825 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1830 mLegend->model()->refreshLayerLegend( mLayer );
1833 mLegend->adjustBoxSize();
1835 mLegend->endCommand();
1838void QgsLayoutLegendNodeWidget::insertExpression()
1846 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1850 if ( mLayer && mLayer->layer() )
1856 QStringList() << u
"legend_title"_s << u
"legend_column_count"_s << u
"legend_split_layers"_s << u
"legend_wrap_string"_s << u
"legend_filter_by_map"_s << u
"legend_filter_out_atlas"_s
1861 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1862 if ( exprDlg.exec() == QDialog::Accepted )
1864 expression = exprDlg.expressionText();
1865 if ( !expression.isEmpty() )
1867 mLegend->beginCommand( tr(
"Insert expression" ) );
1868 mLabelEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
1869 mLegend->endCommand();
1874void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1876 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1877 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1882 mLegend->model()->refreshLayerLegend( mLayer );
1886 mLayer->setPatchSize( size );
1887 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1892 mLegend->model()->refreshLayerLegend( mLayer );
1895 mLegend->adjustBoxSize();
1897 mLegend->endCommand();
1900void QgsLayoutLegendNodeWidget::customSymbolChanged()
1902 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1904 if ( mCustomSymbolCheckBox->isChecked() )
1909 mLegend->model()->refreshLayerLegend( mLayer );
1913 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1918 mLegend->model()->refreshLayerLegend( mLayer );
1926 mLegend->model()->refreshLayerLegend( mLayer );
1930 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1935 mLegend->model()->refreshLayerLegend( mLayer );
1939 mLegend->adjustBoxSize();
1941 mLegend->endCommand();
1944void QgsLayoutLegendNodeWidget::colorRampLegendChanged()
1946 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1950 mLegend->model()->refreshLayerLegend( mLayer );
1952 mLegend->adjustBoxSize();
1954 mLegend->endCommand();
1957void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1959 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1964 mLegend->model()->refreshLayerLegend( mLayer );
1968 mLayer->setCustomProperty( u
"legend/column-break"_s, QString( checked ?
'1' :
'0' ) );
1972 mNode->setCustomProperty( u
"legend/column-break"_s, QString( checked ?
'1' :
'0' ) );
1975 mLegend->adjustBoxSize();
1977 mLegend->endCommand();
1980void QgsLayoutLegendNodeWidget::columnSplitChanged()
1982 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1984 if ( mLayer && !mLegendNode )
1989 mLegend->adjustBoxSize();
1991 mLegend->endCommand();
1998QgsLayoutLegendMapFilteringWidget::QgsLayoutLegendMapFilteringWidget(
QgsLayoutItemLegend *legend )
2000 , mLegendItem( legend )
2003 setPanelTitle( tr(
"Legend Filtering" ) );
2005 setNewItem( legend );
2008bool QgsLayoutLegendMapFilteringWidget::setNewItem(
QgsLayoutItem *item )
2018 mLegendItem = qobject_cast<QgsLayoutItemLegend *>( item );
2025 updateGuiElements();
2030void QgsLayoutLegendMapFilteringWidget::updateGuiElements()
2032 if ( mBlockUpdates )
2035 mBlockUpdates =
true;
2037 if ( mFilterMapItemsListView->model() )
2039 QAbstractItemModel *oldModel = mFilterMapItemsListView->model();
2040 mFilterMapItemsListView->setModel(
nullptr );
2041 oldModel->deleteLater();
2044 QgsLayoutLegendMapFilteringModel *model =
new QgsLayoutLegendMapFilteringModel( mLegendItem, mLegendItem->layout()->itemsModel(), mFilterMapItemsListView );
2045 mFilterMapItemsListView->setModel( model );
2047 mBlockUpdates =
false;
2055 : QSortFilterProxyModel( parent )
2056 , mLayoutModel( layoutModel )
2057 , mLegendItem( legend )
2059 setSourceModel( layoutModel );
2062int QgsLayoutLegendMapFilteringModel::columnCount(
const QModelIndex & )
const
2067QVariant QgsLayoutLegendMapFilteringModel::data(
const QModelIndex &i,
int role )
const
2072 if ( i.column() != 0 )
2077 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( i ) ) );
2085 case Qt::CheckStateRole:
2086 switch ( i.column() )
2091 return Qt::Unchecked;
2093 return mLegendItem->filterByMapItems().contains( mapItem ) ? Qt::Checked : Qt::Unchecked;
2101 return mLayoutModel->data( sourceIndex, role );
2105bool QgsLayoutLegendMapFilteringModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
2109 if ( !index.isValid() )
2112 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2113 if ( !mapItem || !mLegendItem )
2118 mLegendItem->layout()->undoStack()->beginCommand( mLegendItem, tr(
"Change Legend Linked Maps" ) );
2120 QList<QgsLayoutItemMap *> linkedMaps = mLegendItem->filterByMapItems();
2121 if ( value.toBool() )
2123 if ( !linkedMaps.contains( mapItem ) )
2125 linkedMaps.append( mapItem );
2126 mLegendItem->setFilterByMapItems( linkedMaps );
2131 linkedMaps.removeAll( mapItem );
2132 mLegendItem->setFilterByMapItems( linkedMaps );
2134 emit dataChanged( index, index, QVector<int>() << role );
2136 mLegendItem->layout()->undoStack()->endCommand();
2137 mLegendItem->invalidateCache();
2142Qt::ItemFlags QgsLayoutLegendMapFilteringModel::flags(
const QModelIndex &index )
const
2144 Qt::ItemFlags flags = QSortFilterProxyModel::flags( index );
2146 if ( !index.isValid() )
2151 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2152 const bool isMainLinkedMapItem = mLegendItem ? ( mLegendItem->linkedMap() == mapItem ) : false;
2158 if ( !isMainLinkedMapItem )
2160 flags |= Qt::ItemIsEnabled;
2164 flags &= ~Qt::ItemIsEnabled;
2167 switch ( index.column() )
2170 if ( !isMainLinkedMapItem )
2171 return flags | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
2173 return flags | Qt::ItemIsSelectable;
2176 return flags | Qt::ItemIsSelectable;
2180bool QgsLayoutLegendMapFilteringModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
2182 QgsLayoutItem *item = mLayoutModel->itemFromIndex( mLayoutModel->index( source_row, 0, source_parent ) );
2195QgsLegendLayerTreeProxyModel::QgsLegendLayerTreeProxyModel(
QgsLayoutItemLegend *legend, QObject *parent )
2211bool QgsLegendLayerTreeProxyModel::nodeShown(
QgsLayerTreeNode *node )
const
2222 switch ( mSyncMode )
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).
LegendSyncMode
Legend synchronization mode.
@ VisibleLayers
Synchronize to map layers. The legend will include layers which are included in the linked map only.
@ AllProjectLayers
Synchronize to all project layers.
@ Manual
No automatic synchronization of legend layers. The legend will be manually populated.
@ ExcludeByDefault
If set, the layer should not be included in legends by default, and must be manually added by a user.
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.
@ NodeLayer
Leaf node pointing to a layer.
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.
NodeType nodeType() const
Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree...
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.
A proxy model for QgsLayerTreeModel, supporting private layers and text filtering.
virtual bool nodeShown(QgsLayerTreeNode *node) const
Returns true if the specified node should be shown.
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.
Qgis::LegendSyncMode syncMode() const
Returns the legend's synchronization mode.
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.
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)
An abstract interface for implementations of legends for one map layer.
Qgis::MapLayerLegendFlags flags() const
Returns flags associated with the legend.
Base class for all map layer types.
QgsMapLayerLegend * legend() const
Can be nullptr.
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.