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;
915 widgets << mMoveDownToolButton << mMoveUpToolButton << mRemoveToolButton << mAddToolButton
916 << mEditPushButton << mCountToolButton << mResetLayersButton << mAddGroupToolButton
917 << mExpressionFilterButton << mCollapseAllToolButton << mExpandAllToolButton;
918 for ( QWidget *w : std::as_const( widgets ) )
919 w->setEnabled( allowEdits );
924 selectedChanged( QModelIndex(), QModelIndex() );
925 mItemTreeView->proxyModel()->setShowPrivateLayers(
true );
929 mItemTreeView->proxyModel()->setShowPrivateLayers(
false );
933void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
949 mLegend->beginCommand( tr(
"Change Legend Map" ) );
950 mLegend->setLinkedMap( map );
952 mLegend->endCommand();
954 setLegendMapViewData();
958void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
965 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
966 mLegend->setResizeToContents( checked );
968 mLegend->adjustBoxSize();
970 mLegend->endCommand();
973void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
980 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
981 mLegend->setDrawRasterStroke( state );
982 mLegend->adjustBoxSize();
984 mLegend->endCommand();
987void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
995 mLegend->setRasterStrokeWidth( d );
996 mLegend->adjustBoxSize();
998 mLegend->endCommand();
1001void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
1009 mLegend->setRasterStrokeColor( newColor );
1011 mLegend->endCommand();
1014void QgsLayoutLegendWidget::mAddToolButton_clicked()
1021 QList<QgsMapLayer *> visibleLayers;
1022 if ( mLegend->linkedMap() )
1024 visibleLayers = mLegend->linkedMap()->layersToRender();
1026 if ( visibleLayers.isEmpty() )
1029 visibleLayers = mMapCanvas->layers(
true );
1033 addDialog.setVisibleLayers( visibleLayers );
1034 if ( addDialog.exec() == QDialog::Accepted )
1036 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
1037 if ( !layers.empty() )
1039 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
1042 mLegend->model()->rootGroup()->addLayer( layer );
1044 mLegend->updateLegend();
1046 mLegend->endCommand();
1051void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
1058 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
1059 if ( !selectionModel )
1064 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
1066 QList<QPersistentModelIndex> proxyIndexes;
1067 const QModelIndexList viewSelection = selectionModel->selectedIndexes();
1068 for (
const QModelIndex &index : viewSelection )
1069 proxyIndexes << index;
1072 QHash<QgsLayerTreeLayer *, QList<int>> nodesWithRemoval;
1073 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1078 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex( legendNode ) );
1081 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
1083 QList<int> toDelete = it.value();
1084 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
1087 for (
int i : std::as_const( toDelete ) )
1089 if ( i >= 0 && i < order.count() )
1090 order.removeAt( i );
1094 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
1098 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1100 if ( proxyIndex.isValid() && mItemTreeView->index2node( proxyIndex ) )
1102 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( proxyIndex );
1103 mLegend->model()->removeRow( sourceIndex.row(), sourceIndex.parent() );
1107 mLegend->updateLegend();
1109 mLegend->endCommand();
1112void QgsLayoutLegendWidget::mEditPushButton_clicked()
1119 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
1120 mItemTreeView_doubleClicked( idx );
1123void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
1131 QModelIndex currentIndex = mItemTreeView->currentIndex();
1132 if ( !currentIndex.isValid() )
1151 mLegend->beginCommand( tr(
"Update Legend" ) );
1154 for (
const QString &key : constCustomProperties )
1156 if ( key.startsWith(
"legend/"_L1 ) )
1163 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1165 mLegend->updateLegend();
1167 mLegend->endCommand();
1170void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1177 const QList<QModelIndex> selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1178 if ( selectedIndexes.empty() )
1181 mLegend->beginCommand( tr(
"Update Legend" ) );
1182 for (
const QModelIndex &index : selectedIndexes )
1190 mLegend->updateFilterByMap();
1191 mLegend->adjustBoxSize();
1192 mLegend->endCommand();
1195void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1197 mLegend->beginCommand( tr(
"Update Legend" ) );
1198 mLegend->setLegendFilterByMapEnabled( checked );
1199 mLegend->adjustBoxSize();
1201 mLegend->endCommand();
1209 mLegend->beginCommand( tr(
"Update Legend" ) );
1210 mLegend->resetManualLayers( mode );
1212 mLegend->endCommand();
1215void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1223 QModelIndex currentIndex = mItemTreeView->currentIndex();
1224 if ( !currentIndex.isValid() )
1235 mLegend->beginCommand( tr(
"Update Legend" ) );
1236 mLegend->updateFilterByMap();
1237 mLegend->adjustBoxSize();
1238 mLegend->endCommand();
1241void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1248 QModelIndex currentIndex = mItemTreeView->currentIndex();
1249 if ( !currentIndex.isValid() )
1256 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1262 QString currentExpression;
1264 currentExpression = u
"@symbol_label"_s;
1270 QStringList highlighted;
1273 const QList<QgsLayerTreeModelLegendNode *> legendNodes = model->layerLegendNodes( layerNode,
false );
1274 if ( !legendNodes.isEmpty() )
1276 if (
QgsSymbolLegendNode *symbolNode = qobject_cast<QgsSymbolLegendNode *>( legendNodes.first() ) )
1278 legendContext.
appendScope( symbolNode->createSymbolScope() );
1279 highlighted << u
"symbol_label"_s << u
"symbol_id"_s << u
"symbol_count"_s;
1293 if ( expressiondialog.exec() )
1296 mItemTreeView->layerTreeModel()->refreshLayerLegend( layerNode );
1299 mLegend->beginCommand( tr(
"Update Legend" ) );
1301 mLegend->adjustBoxSize();
1302 mLegend->endCommand();
1305void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1309 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1310 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1311 mLegend->updateLegend();
1313 mLegend->endCommand();
1317void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1322 mLegend->setLegendFilterOutAtlas( toggled );
1328void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1330 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1331 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1340bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1350 mLegend = qobject_cast<QgsLayoutItemLegend *>( item );
1351 mItemPropertiesWidget->setItem( mLegend );
1353 if ( mMapFilteringWidget )
1354 mMapFilteringWidget->setItem( mLegend );
1358 mLegendProxyModel =
new QgsLegendLayerTreeProxyModel( mLegend,
this );
1360 mItemTreeView->setModel( mLegend->model(), mLegendProxyModel );
1370void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1372 mTitleLineEdit->blockSignals( b );
1373 mTitleAlignCombo->blockSignals( b );
1374 mItemTreeView->blockSignals( b );
1375 mSyncModeCombo->blockSignals( b );
1376 mMapComboBox->blockSignals( b );
1377 mFilterByMapCheckBox->blockSignals( b );
1378 mColumnCountSpinBox->blockSignals( b );
1379 mSplitLayerCheckBox->blockSignals( b );
1380 mEqualColumnWidthCheckBox->blockSignals( b );
1381 mSymbolWidthSpinBox->blockSignals( b );
1382 mSymbolHeightSpinBox->blockSignals( b );
1383 mMaxSymbolSizeSpinBox->blockSignals( b );
1384 mMinSymbolSizeSpinBox->blockSignals( b );
1385 mGroupSpaceSpinBox->blockSignals( b );
1386 mGroupIndentSpinBox->blockSignals( b );
1387 mSubgroupIndentSpinBox->blockSignals( b );
1388 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1389 mGroupSideSpinBox->blockSignals( b );
1390 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1391 mSubgroupSideSpinBox->blockSignals( b );
1392 mLayerSpaceSpinBox->blockSignals( b );
1393 mSymbolSpaceSpinBox->blockSignals( b );
1394 mSymbolSideSpaceSpinBox->blockSignals( b );
1395 mIconLabelSpaceSpinBox->blockSignals( b );
1396 mBoxSpaceSpinBox->blockSignals( b );
1397 mColumnSpaceSpinBox->blockSignals( b );
1398 mRasterStrokeGroupBox->blockSignals( b );
1399 mRasterStrokeColorButton->blockSignals( b );
1400 mRasterStrokeWidthSpinBox->blockSignals( b );
1401 mWmsLegendWidthSpinBox->blockSignals( b );
1402 mWmsLegendHeightSpinBox->blockSignals( b );
1403 mCheckboxResizeContents->blockSignals( b );
1404 mTitleSpaceBottomSpinBox->blockSignals( b );
1405 mFilterLegendByAtlasCheckBox->blockSignals( b );
1406 mTitleFontButton->blockSignals( b );
1407 mGroupFontButton->blockSignals( b );
1408 mLayerFontButton->blockSignals( b );
1409 mItemFontButton->blockSignals( b );
1410 mWrapCharLineEdit->blockSignals( b );
1411 mMaxWidthSpinBox->blockSignals( b );
1414void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1417 Q_UNUSED( previous )
1419 mLayerExpressionButton->setEnabled(
false );
1432 mLayerExpressionButton->setEnabled(
true );
1436 mCountToolButton->setChecked(
false );
1437 mCountToolButton->setEnabled(
false );
1440 mExpressionFilterButton->blockSignals(
true );
1441 mExpressionFilterButton->setChecked(
false );
1442 mExpressionFilterButton->setEnabled(
false );
1443 mExpressionFilterButton->blockSignals(
false );
1454 mCountToolButton->setChecked( currentNode->
customProperty( u
"showFeatureCount"_s, 0 ).toInt() );
1455 mCountToolButton->setEnabled(
true );
1456 mLayerExpressionButton->setEnabled(
true );
1460 mExpressionFilterButton->blockSignals(
true );
1461 mExpressionFilterButton->setExpressionText( expr );
1462 mExpressionFilterButton->setVectorLayer( vl );
1463 mExpressionFilterButton->setEnabled(
true );
1464 mExpressionFilterButton->setChecked( exprEnabled );
1465 mExpressionFilterButton->blockSignals(
false );
1468void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1470 QAction *a = qobject_cast<QAction *>( sender() );
1471 if ( !a || !mItemTreeView->currentNode() )
1478void QgsLayoutLegendWidget::setLegendMapViewData()
1480 if ( mLegend->linkedMap() )
1484 measurementConverter.
setDpi( dpi );
1487 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1488 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1489 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1493void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1497 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
Qgis::GeometryType::Polygon );
1501void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1503 if ( !mLegend || !idx.isValid() )
1514 int originalIndex = -1;
1517 originalIndex = _originalLegendNodeIndex( legendNode );
1521 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode, legendNode, originalIndex );
1522 openPanel( widget );
1530QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1535QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1537 if ( !mView->currentNode() )
1543 QMenu *menu =
new QMenu();
1547 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1548 menu->addSeparator();
1553 QActionGroup *styleGroup =
new QActionGroup { mWidget };
1554 styleGroup->setExclusive(
true );
1556 QList<Qgis::LegendComponent> lst;
1560 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1561 action->setActionGroup( styleGroup );
1562 action->setCheckable(
true );
1563 action->setChecked( currentStyle == style );
1564 action->setData(
static_cast<int>( style ) );
1579 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1582 setPanelTitle( tr(
"Legend Item Properties" ) );
1591 QString currentLabel;
1594 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1595 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1599 currentLabel = mLayer->name();
1600 QVariant v = mLayer->customProperty( u
"legend/title-label"_s );
1602 currentLabel = v.toString();
1603 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( u
"legend/column-break"_s ).toInt() );
1605 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1610 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( u
"legend/column-break"_s ).toInt() );
1613 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1614 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1615 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1616 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1617 mPatchGroup->setVisible( mLegendNode || mLayer );
1618 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1619 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1620 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1621 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1622 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1625 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1626 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1630 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1631 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1634 mCustomSymbolCheckBox->setChecked(
false );
1639 patchShape = symbolLegendNode->patchShape();
1641 std::unique_ptr<QgsSymbol> customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() :
nullptr );
1642 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1645 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1646 mCustomSymbolButton->setSymbolType( customSymbol->type() );
1647 mCustomSymbolButton->setSymbol( customSymbol.release() );
1649 else if ( symbolLegendNode->symbol() )
1651 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1652 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1653 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1656 else if ( !mLegendNode && mLayer )
1658 patchShape = mLayer->patchShape();
1661 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1663 mCustomSymbolCheckBox->setChecked(
true );
1664 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1665 mCustomSymbolButton->setSymbolType( customSymbol->type() );
1666 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1670 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1671 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1672 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1679 switch ( qobject_cast<QgsVectorLayer *>( mLayer->layer() )->geometryType() )
1694 mPatchShapeLabel->hide();
1695 mPatchShapeButton->hide();
1698 if ( !patchShape.
isNull() )
1699 mPatchShapeButton->setShape( patchShape );
1703 if ( symbolLegendNode->symbol() )
1705 mPatchShapeButton->setSymbolType( symbolLegendNode->symbol()->type() );
1709 mPatchShapeLabel->hide();
1710 mPatchShapeButton->hide();
1715 mPatchShapeLabel->hide();
1716 mPatchShapeButton->hide();
1721 mLabelGroup->hide();
1722 mColorRampLegendWidget->setSettings( colorRampNode->settings() );
1726 mColorRampLegendWidget->hide();
1739 mCustomSymbolCheckBox->hide();
1748 mLabelEdit->setPlainText( currentLabel );
1749 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1751 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1753 connect( mWidthSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1754 connect( mHeightSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1756 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1759 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1761 connect( mColumnSplitBehaviorComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1765 connectChildPanel( mColorRampLegendWidget );
1768void QgsLayoutLegendNodeWidget::setDockMode(
bool dockMode )
1770 mColorRampLegendWidget->setDockMode( dockMode );
1774void QgsLayoutLegendNodeWidget::labelChanged()
1778 const QString label = mLabelEdit->toPlainText();
1783 else if ( mLegendNode )
1786 mLegend->model()->refreshLayerLegend( mLayer );
1790 mLayer->setCustomProperty( u
"legend/title-label"_s, label );
1794 embeddedNode->setUserLabel( QString() );
1797 mLegend->adjustBoxSize();
1798 mLegend->invalidateCache();
1800 mLegend->endCommand();
1803void QgsLayoutLegendNodeWidget::patchChanged()
1805 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1811 mLegend->model()->refreshLayerLegend( mLayer );
1815 mLayer->setPatchShape( shape );
1816 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1821 mLegend->model()->refreshLayerLegend( mLayer );
1824 mLegend->adjustBoxSize();
1826 mLegend->endCommand();
1829void QgsLayoutLegendNodeWidget::insertExpression()
1837 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1841 if ( mLayer && mLayer->layer() )
1846 context.
setHighlightedVariables( 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 );
1850 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1851 if ( exprDlg.exec() == QDialog::Accepted )
1853 expression = exprDlg.expressionText();
1854 if ( !expression.isEmpty() )
1856 mLegend->beginCommand( tr(
"Insert expression" ) );
1857 mLabelEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
1858 mLegend->endCommand();
1863void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1865 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1866 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1871 mLegend->model()->refreshLayerLegend( mLayer );
1875 mLayer->setPatchSize( size );
1876 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1881 mLegend->model()->refreshLayerLegend( mLayer );
1884 mLegend->adjustBoxSize();
1886 mLegend->endCommand();
1889void QgsLayoutLegendNodeWidget::customSymbolChanged()
1891 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1893 if ( mCustomSymbolCheckBox->isChecked() )
1898 mLegend->model()->refreshLayerLegend( mLayer );
1902 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1907 mLegend->model()->refreshLayerLegend( mLayer );
1915 mLegend->model()->refreshLayerLegend( mLayer );
1919 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1924 mLegend->model()->refreshLayerLegend( mLayer );
1928 mLegend->adjustBoxSize();
1930 mLegend->endCommand();
1933void QgsLayoutLegendNodeWidget::colorRampLegendChanged()
1935 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1939 mLegend->model()->refreshLayerLegend( mLayer );
1941 mLegend->adjustBoxSize();
1943 mLegend->endCommand();
1946void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1948 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1953 mLegend->model()->refreshLayerLegend( mLayer );
1957 mLayer->setCustomProperty( u
"legend/column-break"_s, QString( checked ?
'1' :
'0' ) );
1961 mNode->setCustomProperty( u
"legend/column-break"_s, QString( checked ?
'1' :
'0' ) );
1964 mLegend->adjustBoxSize();
1966 mLegend->endCommand();
1969void QgsLayoutLegendNodeWidget::columnSplitChanged()
1971 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1973 if ( mLayer && !mLegendNode )
1978 mLegend->adjustBoxSize();
1980 mLegend->endCommand();
1987QgsLayoutLegendMapFilteringWidget::QgsLayoutLegendMapFilteringWidget(
QgsLayoutItemLegend *legend )
1989 , mLegendItem( legend )
1992 setPanelTitle( tr(
"Legend Filtering" ) );
1994 setNewItem( legend );
1997bool QgsLayoutLegendMapFilteringWidget::setNewItem(
QgsLayoutItem *item )
2007 mLegendItem = qobject_cast<QgsLayoutItemLegend *>( item );
2014 updateGuiElements();
2019void QgsLayoutLegendMapFilteringWidget::updateGuiElements()
2021 if ( mBlockUpdates )
2024 mBlockUpdates =
true;
2026 if ( mFilterMapItemsListView->model() )
2028 QAbstractItemModel *oldModel = mFilterMapItemsListView->model();
2029 mFilterMapItemsListView->setModel(
nullptr );
2030 oldModel->deleteLater();
2033 QgsLayoutLegendMapFilteringModel *model =
new QgsLayoutLegendMapFilteringModel( mLegendItem, mLegendItem->layout()->itemsModel(), mFilterMapItemsListView );
2034 mFilterMapItemsListView->setModel( model );
2036 mBlockUpdates =
false;
2044 : QSortFilterProxyModel( parent )
2045 , mLayoutModel( layoutModel )
2046 , mLegendItem( legend )
2048 setSourceModel( layoutModel );
2051int QgsLayoutLegendMapFilteringModel::columnCount(
const QModelIndex & )
const
2056QVariant QgsLayoutLegendMapFilteringModel::data(
const QModelIndex &i,
int role )
const
2061 if ( i.column() != 0 )
2066 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( i ) ) );
2074 case Qt::CheckStateRole:
2075 switch ( i.column() )
2080 return Qt::Unchecked;
2082 return mLegendItem->filterByMapItems().contains( mapItem ) ? Qt::Checked : Qt::Unchecked;
2090 return mLayoutModel->data( sourceIndex, role );
2094bool QgsLayoutLegendMapFilteringModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
2098 if ( !index.isValid() )
2101 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2102 if ( !mapItem || !mLegendItem )
2107 mLegendItem->layout()->undoStack()->beginCommand( mLegendItem, tr(
"Change Legend Linked Maps" ) );
2109 QList<QgsLayoutItemMap *> linkedMaps = mLegendItem->filterByMapItems();
2110 if ( value.toBool() )
2112 if ( !linkedMaps.contains( mapItem ) )
2114 linkedMaps.append( mapItem );
2115 mLegendItem->setFilterByMapItems( linkedMaps );
2120 linkedMaps.removeAll( mapItem );
2121 mLegendItem->setFilterByMapItems( linkedMaps );
2123 emit dataChanged( index, index, QVector<int>() << role );
2125 mLegendItem->layout()->undoStack()->endCommand();
2126 mLegendItem->invalidateCache();
2131Qt::ItemFlags QgsLayoutLegendMapFilteringModel::flags(
const QModelIndex &index )
const
2133 Qt::ItemFlags flags = QSortFilterProxyModel::flags( index );
2135 if ( !index.isValid() )
2140 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2141 const bool isMainLinkedMapItem = mLegendItem ? ( mLegendItem->linkedMap() == mapItem ) : false;
2147 if ( !isMainLinkedMapItem )
2149 flags |= Qt::ItemIsEnabled;
2153 flags &= ~Qt::ItemIsEnabled;
2156 switch ( index.column() )
2159 if ( !isMainLinkedMapItem )
2160 return flags | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
2162 return flags | Qt::ItemIsSelectable;
2165 return flags | Qt::ItemIsSelectable;
2169bool QgsLayoutLegendMapFilteringModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
2171 QgsLayoutItem *item = mLayoutModel->itemFromIndex( mLayoutModel->index( source_row, 0, source_parent ) );
2184QgsLegendLayerTreeProxyModel::QgsLegendLayerTreeProxyModel(
QgsLayoutItemLegend *legend, QObject *parent )
2200bool QgsLegendLayerTreeProxyModel::nodeShown(
QgsLayerTreeNode *node )
const
2211 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.