19#include "moc_qgslayoutlegendwidget.cpp"
51#include <QInputDialog>
52#include <QActionGroup>
69 int unfilteredNodeIndex = _unfilteredLegendNodeIndex( legendNode );
71 return ( unfilteredNodeIndex >= 0 && unfilteredNodeIndex < order.count() ? order[unfilteredNodeIndex] : -1 );
74 void _moveLegendNode(
QgsLayerTreeLayer *nodeLayer,
int legendNodeIndex,
int destLegendNodeIndex )
77 const int offset = destLegendNodeIndex - legendNodeIndex;
79 if ( legendNodeIndex < 0 || legendNodeIndex >= order.count() )
81 if ( legendNodeIndex + offset < 0 || legendNodeIndex + offset >= order.count() )
84 int id = order.takeAt( legendNodeIndex );
85 order.insert( legendNodeIndex + offset,
id );
94 , mMapCanvas( mapCanvas )
99 connect( mWrapCharLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
100 connect( mTitleLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
105 connect( mColumnCountSpinBox,
static_cast<void ( QSpinBox::* )(
int )
>( &QSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
106 connect( mSplitLayerCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
107 connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
108 connect( mSymbolWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged );
109 connect( mSymbolHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged );
110 connect( mMaxSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged );
111 connect( mMinSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged );
112 connect( mWmsLegendWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
113 connect( mWmsLegendHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
114 connect( mTitleSpaceBottomSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
115 connect( mGroupSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
116 connect( mGroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged );
117 connect( mSubgroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged );
118 connect( mSpaceBelowGroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
119 connect( mGroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
120 connect( mLayerSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
121 connect( mSpaceBelowSubgroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
122 connect( mSubgroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
123 connect( mSymbolSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
124 connect( mSymbolSideSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
125 connect( mIconLabelSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
126 connect( mBoxSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
127 connect( mColumnSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged );
128 connect( mCheckBoxAutoUpdate, &QCheckBox::stateChanged,
this, [=](
int state ) { mCheckBoxAutoUpdate_stateChanged( state ); } );
129 connect( mCheckboxResizeContents, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mCheckboxResizeContents_toggled );
130 connect( mRasterStrokeGroupBox, &QgsCollapsibleGroupBoxBasic::toggled,
this, &QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled );
131 connect( mRasterStrokeWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged );
132 connect( mRasterStrokeColorButton, &
QgsColorButton::colorChanged,
this, &QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged );
133 connect( mExpandAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::expandLegendTree );
134 connect( mCollapseAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::collapseLegendTree );
135 connect( mMoveDownToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveDownToolButton_clicked );
136 connect( mMoveUpToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveUpToolButton_clicked );
137 connect( mRemoveToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mRemoveToolButton_clicked );
138 connect( mAddToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddToolButton_clicked );
139 connect( mEditPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mEditPushButton_clicked );
140 connect( mCountToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mCountToolButton_clicked );
141 connect( mExpressionFilterButton, &QgsLegendFilterButton::toggled,
this, &QgsLayoutLegendWidget::mExpressionFilterButton_toggled );
142 connect( mLayerExpressionButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mLayerExpressionButton_clicked );
143 connect( mFilterByMapCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled );
144 connect( mUpdateAllPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mUpdateAllPushButton_clicked );
145 connect( mAddGroupToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddGroupToolButton_clicked );
146 connect( mFilterLegendByAtlasCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled );
147 connect( mItemTreeView, &QgsLayerTreeView::doubleClicked,
this, &QgsLayoutLegendWidget::mItemTreeView_doubleClicked );
149 connect( mFilterByMapCheckBox, &QCheckBox::toggled, mButtonLinkedMaps, &QWidget::setEnabled );
150 mButtonLinkedMaps->setEnabled(
false );
151 connect( mButtonLinkedMaps, &QToolButton::clicked,
this, [=] {
152 mMapFilteringWidget =
new QgsLayoutLegendMapFilteringWidget( mLegend );
153 openPanel( mMapFilteringWidget );
156 setPanelTitle( tr(
"Legend Properties" ) );
163 mTitleAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
164 mGroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
165 mSubgroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
166 mItemAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
168 mArrangementCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignRight );
170 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignLeft, tr(
"Symbols on Left" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsLeft.svg" ) ) );
171 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignRight, tr(
"Symbols on Right" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsRight.svg" ) ) );
173 mSpaceBelowGroupHeadingSpinBox->setClearValue( 0 );
174 mGroupSideSpinBox->setClearValue( 0 );
175 mSpaceBelowSubgroupHeadingSpinBox->setClearValue( 0 );
176 mSubgroupSideSpinBox->setClearValue( 0 );
177 mSymbolSideSpaceSpinBox->setClearValue( 0 );
202 mRasterStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
203 mRasterStrokeColorButton->setAllowOpacity(
true );
204 mRasterStrokeColorButton->setContext( QStringLiteral(
"composer " ) );
206 mMapComboBox->setCurrentLayout( legend->
layout() );
212 mainLayout->addWidget( mItemPropertiesWidget );
214 mItemTreeView->setHeaderHidden(
true );
216 mItemTreeView->setModel( legend->
model() );
217 mItemTreeView->setMenuProvider(
new QgsLayoutLegendMenuProvider( mItemTreeView,
this ) );
218 setLegendMapViewData();
224 connect( layoutAtlas(), &
QgsLayoutAtlas::toggled,
this, &QgsLayoutLegendWidget::updateFilterLegendByAtlasButton );
228 mTitleFontButton->registerExpressionContextGenerator(
this );
229 mGroupFontButton->registerExpressionContextGenerator(
this );
230 mLayerFontButton->registerExpressionContextGenerator(
this );
231 mItemFontButton->registerExpressionContextGenerator(
this );
232 mExpressionFilterButton->registerExpressionContextGenerator(
this );
234 mTitleFontButton->setLayer( coverageLayer() );
235 mGroupFontButton->setLayer( coverageLayer() );
236 mLayerFontButton->setLayer( coverageLayer() );
237 mItemFontButton->setLayer( coverageLayer() );
238 if ( mLegend->layout() )
251 connect( mItemTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsLayoutLegendWidget::selectedChanged );
260 if ( mItemPropertiesWidget )
261 mItemPropertiesWidget->setMasterLayout( masterLayout );
267 mTitleFontButton->setMessageBar( iface->
messageBar() );
268 mGroupFontButton->setMessageBar( iface->
messageBar() );
269 mLayerFontButton->setMessageBar( iface->
messageBar() );
270 mItemFontButton->setMessageBar( iface->
messageBar() );
273void QgsLayoutLegendWidget::setGuiElements()
280 blockAllSignals(
true );
281 mTitleLineEdit->setText( mLegend->title() );
282 whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
286 whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
287 mFilterByMapCheckBox->setChecked( mLegend->legendFilterByMapEnabled() );
288 mButtonLinkedMaps->setEnabled( mLegend->legendFilterByMapEnabled() );
289 mColumnCountSpinBox->setValue( mLegend->columnCount() );
290 mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
291 mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
292 mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
293 mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
294 mMaxSymbolSizeSpinBox->setValue( mLegend->maximumSymbolSize() );
295 mMinSymbolSizeSpinBox->setValue( mLegend->minimumSymbolSize() );
296 mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
297 mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
311 mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
312 mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
314 mRasterStrokeGroupBox->setChecked( mLegend->drawRasterStroke() );
315 mRasterStrokeWidthSpinBox->setValue( mLegend->rasterStrokeWidth() );
316 mRasterStrokeColorButton->setColor( mLegend->rasterStrokeColor() );
318 mCheckBoxAutoUpdate->setChecked( mLegend->autoUpdateModel() );
320 mCheckboxResizeContents->setChecked( mLegend->resizeToContents() );
321 mFilterLegendByAtlasCheckBox->setChecked( mLegend->legendFilterOutAtlas() );
322 mWrapCharLineEdit->setText( mLegend->wrapString() );
325 mMapComboBox->setItem( map );
331 blockAllSignals(
false );
333 mCheckBoxAutoUpdate_stateChanged( mLegend->autoUpdateModel() ? Qt::Checked : Qt::Unchecked, false );
334 updateDataDefinedButton( mLegendTitleDDBtn );
335 updateDataDefinedButton( mColumnsDDBtn );
338void QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged(
const QString &text )
342 mLegend->beginCommand( tr(
"Change Legend Wrap" ) );
343 mLegend->setWrapString( text );
344 mLegend->adjustBoxSize();
346 mLegend->endCommand();
350void QgsLayoutLegendWidget::mTitleLineEdit_textChanged(
const QString &text )
355 mLegend->setTitle( text );
356 mLegend->adjustBoxSize();
358 mLegend->endCommand();
362void QgsLayoutLegendWidget::titleAlignmentChanged()
366 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
367 mLegend->beginCommand( tr(
"Change Title Alignment" ) );
368 mLegend->setTitleAlignment( alignment );
370 mLegend->endCommand();
374void QgsLayoutLegendWidget::groupAlignmentChanged()
378 mLegend->beginCommand( tr(
"Change Group Alignment" ) );
381 mLegend->endCommand();
385void QgsLayoutLegendWidget::subgroupAlignmentChanged()
389 mLegend->beginCommand( tr(
"Change Subgroup Alignment" ) );
392 mLegend->endCommand();
396void QgsLayoutLegendWidget::itemAlignmentChanged()
400 mLegend->beginCommand( tr(
"Change Item Alignment" ) );
403 mLegend->endCommand();
407void QgsLayoutLegendWidget::arrangementChanged()
411 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
412 mLegend->beginCommand( tr(
"Change Legend Arrangement" ) );
413 mLegend->setSymbolAlignment( alignment );
415 mLegend->endCommand();
419void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged(
int c )
424 mLegend->setColumnCount(
c );
425 mLegend->adjustBoxSize();
427 mLegend->endCommand();
429 mSplitLayerCheckBox->setEnabled(
c > 1 );
430 mEqualColumnWidthCheckBox->setEnabled(
c > 1 );
433void QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled(
bool checked )
437 mLegend->beginCommand( tr(
"Split Legend Layers" ) );
438 mLegend->setSplitLayer( checked );
439 mLegend->adjustBoxSize();
441 mLegend->endCommand();
445void QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled(
bool checked )
449 mLegend->beginCommand( tr(
"Legend Column Width" ) );
450 mLegend->setEqualColumnWidth( checked );
451 mLegend->adjustBoxSize();
453 mLegend->endCommand();
457void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged(
double d )
462 mLegend->setSymbolWidth( d );
463 mLegend->adjustBoxSize();
465 mLegend->endCommand();
469void QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged(
double d )
474 mLegend->setMaximumSymbolSize( d );
475 mLegend->adjustBoxSize();
477 mLegend->endCommand();
481void QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged(
double d )
486 mLegend->setMinimumSymbolSize( d );
487 mLegend->adjustBoxSize();
489 mLegend->endCommand();
493void QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged(
double d )
498 mLegend->setSymbolHeight( d );
499 mLegend->adjustBoxSize();
501 mLegend->endCommand();
505void QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged(
double d )
510 mLegend->setWmsLegendWidth( d );
511 mLegend->adjustBoxSize();
513 mLegend->endCommand();
517void QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged(
double d )
522 mLegend->setWmsLegendHeight( d );
523 mLegend->adjustBoxSize();
525 mLegend->endCommand();
529void QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged(
double d )
535 mLegend->adjustBoxSize();
537 mLegend->endCommand();
541void QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged(
double d )
547 mLegend->adjustBoxSize();
549 mLegend->endCommand();
553void QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged(
double d )
559 mLegend->adjustBoxSize();
561 mLegend->endCommand();
565void QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged(
double d )
571 mLegend->adjustBoxSize();
573 mLegend->endCommand();
577void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged(
double space )
583 mLegend->adjustBoxSize();
585 mLegend->endCommand();
589void QgsLayoutLegendWidget::spaceGroupSideChanged(
double space )
595 mLegend->adjustBoxSize();
597 mLegend->endCommand();
601void QgsLayoutLegendWidget::spaceSubGroupSideChanged(
double space )
607 mLegend->adjustBoxSize();
609 mLegend->endCommand();
613void QgsLayoutLegendWidget::spaceSymbolSideChanged(
double space )
619 mLegend->adjustBoxSize();
621 mLegend->endCommand();
625void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged(
double d )
631 mLegend->adjustBoxSize();
633 mLegend->endCommand();
637void QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged(
double d )
645 mLegend->adjustBoxSize();
647 mLegend->endCommand();
651void QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged(
double d )
657 mLegend->adjustBoxSize();
659 mLegend->endCommand();
663void QgsLayoutLegendWidget::titleFontChanged()
669 mLegend->adjustBoxSize();
671 mLegend->endCommand();
675void QgsLayoutLegendWidget::groupFontChanged()
681 mLegend->adjustBoxSize();
683 mLegend->endCommand();
687void QgsLayoutLegendWidget::layerFontChanged()
693 mLegend->adjustBoxSize();
695 mLegend->endCommand();
699void QgsLayoutLegendWidget::itemFontChanged()
705 mLegend->adjustBoxSize();
707 mLegend->endCommand();
711void QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged(
double space )
717 mLegend->adjustBoxSize();
719 mLegend->endCommand();
723void QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged(
double d )
728 mLegend->setBoxSpace( d );
729 mLegend->adjustBoxSize();
731 mLegend->endCommand();
735void QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged(
double d )
740 mLegend->setColumnSpace( d );
741 mLegend->adjustBoxSize();
743 mLegend->endCommand();
747void QgsLayoutLegendWidget::mMoveDownToolButton_clicked()
754 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
755 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
756 const QModelIndex parentIndex = sourceIndex.parent();
757 if ( !sourceIndex.isValid() || sourceIndex.row() == mItemTreeView->layerTreeModel()->rowCount( parentIndex ) - 1 )
762 if ( !node && !legendNode )
765 mLegend->beginCommand( tr(
"Moved Legend Item Down" ) );
776 const QModelIndex nextIndex = index.siblingAtRow( index.row() + 1 );
778 if ( nextLegendNode )
780 _moveLegendNode(
legendNode->
layerNode(), _unfilteredLegendNodeIndex( legendNode ), _unfilteredLegendNodeIndex( nextLegendNode ) );
785 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() + 1, 0, parentIndex ) ) );
788 mLegend->endCommand();
791void QgsLayoutLegendWidget::mMoveUpToolButton_clicked()
798 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
799 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
800 const QModelIndex parentIndex = sourceIndex.parent();
801 if ( !sourceIndex.isValid() || sourceIndex.row() == 0 )
806 if ( !node && !legendNode )
809 mLegend->beginCommand( tr(
"Move Legend Item Up" ) );
820 const QModelIndex prevIndex = index.siblingAtRow( index.row() - 1 );
822 if ( prevLegendNode )
824 _moveLegendNode(
legendNode->
layerNode(), _unfilteredLegendNodeIndex( legendNode ), _unfilteredLegendNodeIndex( prevLegendNode ) );
829 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() - 1, 0, parentIndex ) ) );
832 mLegend->endCommand();
835void QgsLayoutLegendWidget::expandLegendTree()
837 mItemTreeView->expandAll();
840void QgsLayoutLegendWidget::collapseLegendTree()
842 mItemTreeView->collapseAll();
845void QgsLayoutLegendWidget::mCheckBoxAutoUpdate_stateChanged(
int state,
bool userTriggered )
849 mLegend->beginCommand( tr(
"Change Auto Update" ) );
851 mLegend->setAutoUpdateModel( state == Qt::Checked );
853 mLegend->endCommand();
857 QList<QWidget *> widgets;
858 widgets << mMoveDownToolButton << mMoveUpToolButton << mRemoveToolButton << mAddToolButton
859 << mEditPushButton << mCountToolButton << mUpdateAllPushButton << mAddGroupToolButton
860 << mExpressionFilterButton << mCollapseAllToolButton << mExpandAllToolButton;
861 for ( QWidget *w : std::as_const( widgets ) )
862 w->setEnabled( state != Qt::Checked );
864 if ( state == Qt::Unchecked )
867 selectedChanged( QModelIndex(), QModelIndex() );
868 mItemTreeView->proxyModel()->setShowPrivateLayers(
true );
872 mItemTreeView->proxyModel()->setShowPrivateLayers(
false );
876void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
892 mLegend->beginCommand( tr(
"Change Legend Map" ) );
893 mLegend->setLinkedMap( map );
895 mLegend->endCommand();
897 setLegendMapViewData();
901void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
908 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
909 mLegend->setResizeToContents( checked );
911 mLegend->adjustBoxSize();
913 mLegend->endCommand();
916void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
923 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
924 mLegend->setDrawRasterStroke( state );
925 mLegend->adjustBoxSize();
927 mLegend->endCommand();
930void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
938 mLegend->setRasterStrokeWidth( d );
939 mLegend->adjustBoxSize();
941 mLegend->endCommand();
944void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
952 mLegend->setRasterStrokeColor( newColor );
954 mLegend->endCommand();
957void QgsLayoutLegendWidget::mAddToolButton_clicked()
964 QList<QgsMapLayer *> visibleLayers;
965 if ( mLegend->linkedMap() )
967 visibleLayers = mLegend->linkedMap()->layersToRender();
969 if ( visibleLayers.isEmpty() )
972 visibleLayers = mMapCanvas->layers(
true );
976 addDialog.setVisibleLayers( visibleLayers );
977 if ( addDialog.exec() == QDialog::Accepted )
979 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
980 if ( !layers.empty() )
982 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
985 mLegend->model()->rootGroup()->addLayer( layer );
987 mLegend->updateLegend();
989 mLegend->endCommand();
994void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
1001 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
1002 if ( !selectionModel )
1007 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
1009 QList<QPersistentModelIndex> proxyIndexes;
1010 const QModelIndexList viewSelection = selectionModel->selectedIndexes();
1011 for (
const QModelIndex &index : viewSelection )
1012 proxyIndexes << index;
1015 QHash<QgsLayerTreeLayer *, QList<int>> nodesWithRemoval;
1016 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1021 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex( legendNode ) );
1024 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
1026 QList<int> toDelete = it.value();
1027 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
1030 for (
int i : std::as_const( toDelete ) )
1032 if ( i >= 0 && i < order.count() )
1033 order.removeAt( i );
1037 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
1041 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1043 if ( proxyIndex.isValid() && mItemTreeView->index2node( proxyIndex ) )
1045 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( proxyIndex );
1046 mLegend->model()->removeRow( sourceIndex.row(), sourceIndex.parent() );
1050 mLegend->updateLegend();
1052 mLegend->endCommand();
1055void QgsLayoutLegendWidget::mEditPushButton_clicked()
1062 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
1063 mItemTreeView_doubleClicked( idx );
1066void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
1074 QModelIndex currentIndex = mItemTreeView->currentIndex();
1075 if ( !currentIndex.isValid() )
1094 mLegend->beginCommand( tr(
"Update Legend" ) );
1097 for (
const QString &key : constCustomProperties )
1099 if ( key.startsWith( QLatin1String(
"legend/" ) ) )
1106 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1108 mLegend->updateLegend();
1110 mLegend->endCommand();
1113void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1120 const QList<QModelIndex> selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1121 if ( selectedIndexes.empty() )
1124 mLegend->beginCommand( tr(
"Update Legend" ) );
1125 for (
const QModelIndex &index : selectedIndexes )
1131 currentNode->
setCustomProperty( QStringLiteral(
"showFeatureCount" ), checked ? 1 : 0 );
1133 mLegend->updateFilterByMap();
1134 mLegend->adjustBoxSize();
1135 mLegend->endCommand();
1138void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1140 mLegend->beginCommand( tr(
"Update Legend" ) );
1141 mLegend->setLegendFilterByMapEnabled( checked );
1142 mLegend->adjustBoxSize();
1144 mLegend->endCommand();
1147void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1155 QModelIndex currentIndex = mItemTreeView->currentIndex();
1156 if ( !currentIndex.isValid() )
1167 mLegend->beginCommand( tr(
"Update Legend" ) );
1168 mLegend->updateFilterByMap();
1169 mLegend->adjustBoxSize();
1170 mLegend->endCommand();
1173void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1180 QModelIndex currentIndex = mItemTreeView->currentIndex();
1181 if ( !currentIndex.isValid() )
1188 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1194 QString currentExpression;
1196 currentExpression = QStringLiteral(
"@symbol_label" );
1202 QStringList highlighted;
1205 const QList<QgsLayerTreeModelLegendNode *> legendNodes = model->layerLegendNodes( layerNode,
false );
1206 if ( !legendNodes.isEmpty() )
1208 if (
QgsSymbolLegendNode *symbolNode = qobject_cast<QgsSymbolLegendNode *>( legendNodes.first() ) )
1210 legendContext.
appendScope( symbolNode->createSymbolScope() );
1211 highlighted << QStringLiteral(
"symbol_label" ) << QStringLiteral(
"symbol_id" ) << QStringLiteral(
"symbol_count" );
1224 QgsExpressionBuilderDialog expressiondialog(
nullptr, currentExpression,
nullptr, QStringLiteral(
"generic" ), legendContext );
1225 if ( expressiondialog.exec() )
1228 mItemTreeView->layerTreeModel()->refreshLayerLegend( layerNode );
1231 mLegend->beginCommand( tr(
"Update Legend" ) );
1233 mLegend->adjustBoxSize();
1234 mLegend->endCommand();
1237void QgsLayoutLegendWidget::mUpdateAllPushButton_clicked()
1242void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1246 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1247 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1248 mLegend->updateLegend();
1250 mLegend->endCommand();
1254void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1259 mLegend->setLegendFilterOutAtlas( toggled );
1265void QgsLayoutLegendWidget::updateLegend()
1269 mLegend->beginCommand( tr(
"Update Legend" ) );
1272 mLegend->setAutoUpdateModel(
true );
1273 mLegend->setAutoUpdateModel(
false );
1275 mLegend->endCommand();
1279void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1281 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1282 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1291bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1301 mLegend = qobject_cast<QgsLayoutItemLegend *>( item );
1302 mItemPropertiesWidget->setItem( mLegend );
1304 if ( mMapFilteringWidget )
1305 mMapFilteringWidget->setItem( mLegend );
1309 mItemTreeView->setModel( mLegend->model() );
1318void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1320 mTitleLineEdit->blockSignals( b );
1321 mTitleAlignCombo->blockSignals( b );
1322 mItemTreeView->blockSignals( b );
1323 mCheckBoxAutoUpdate->blockSignals( b );
1324 mMapComboBox->blockSignals( b );
1325 mFilterByMapCheckBox->blockSignals( b );
1326 mColumnCountSpinBox->blockSignals( b );
1327 mSplitLayerCheckBox->blockSignals( b );
1328 mEqualColumnWidthCheckBox->blockSignals( b );
1329 mSymbolWidthSpinBox->blockSignals( b );
1330 mSymbolHeightSpinBox->blockSignals( b );
1331 mMaxSymbolSizeSpinBox->blockSignals( b );
1332 mMinSymbolSizeSpinBox->blockSignals( b );
1333 mGroupSpaceSpinBox->blockSignals( b );
1334 mGroupIndentSpinBox->blockSignals( b );
1335 mSubgroupIndentSpinBox->blockSignals( b );
1336 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1337 mGroupSideSpinBox->blockSignals( b );
1338 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1339 mSubgroupSideSpinBox->blockSignals( b );
1340 mLayerSpaceSpinBox->blockSignals( b );
1341 mSymbolSpaceSpinBox->blockSignals( b );
1342 mSymbolSideSpaceSpinBox->blockSignals( b );
1343 mIconLabelSpaceSpinBox->blockSignals( b );
1344 mBoxSpaceSpinBox->blockSignals( b );
1345 mColumnSpaceSpinBox->blockSignals( b );
1346 mRasterStrokeGroupBox->blockSignals( b );
1347 mRasterStrokeColorButton->blockSignals( b );
1348 mRasterStrokeWidthSpinBox->blockSignals( b );
1349 mWmsLegendWidthSpinBox->blockSignals( b );
1350 mWmsLegendHeightSpinBox->blockSignals( b );
1351 mCheckboxResizeContents->blockSignals( b );
1352 mTitleSpaceBottomSpinBox->blockSignals( b );
1353 mFilterLegendByAtlasCheckBox->blockSignals( b );
1354 mTitleFontButton->blockSignals( b );
1355 mGroupFontButton->blockSignals( b );
1356 mLayerFontButton->blockSignals( b );
1357 mItemFontButton->blockSignals( b );
1358 mWrapCharLineEdit->blockSignals( b );
1361void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1364 Q_UNUSED( previous )
1366 mLayerExpressionButton->setEnabled(
false );
1368 if ( mLegend && mLegend->autoUpdateModel() )
1379 mLayerExpressionButton->setEnabled(
true );
1383 mCountToolButton->setChecked(
false );
1384 mCountToolButton->setEnabled(
false );
1387 mExpressionFilterButton->blockSignals(
true );
1388 mExpressionFilterButton->setChecked(
false );
1389 mExpressionFilterButton->setEnabled(
false );
1390 mExpressionFilterButton->blockSignals(
false );
1401 mCountToolButton->setChecked( currentNode->
customProperty( QStringLiteral(
"showFeatureCount" ), 0 ).toInt() );
1402 mCountToolButton->setEnabled(
true );
1403 mLayerExpressionButton->setEnabled(
true );
1407 mExpressionFilterButton->blockSignals(
true );
1408 mExpressionFilterButton->setExpressionText( expr );
1409 mExpressionFilterButton->setVectorLayer( vl );
1410 mExpressionFilterButton->setEnabled(
true );
1411 mExpressionFilterButton->setChecked( exprEnabled );
1412 mExpressionFilterButton->blockSignals(
false );
1415void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1417 QAction *a = qobject_cast<QAction *>( sender() );
1418 if ( !a || !mItemTreeView->currentNode() )
1425void QgsLayoutLegendWidget::setLegendMapViewData()
1427 if ( mLegend->linkedMap() )
1431 measurementConverter.
setDpi( dpi );
1434 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1435 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1436 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1440void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1444 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
Qgis::GeometryType::Polygon );
1448void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1450 if ( !mLegend || !idx.isValid() )
1455 if ( mLegend->autoUpdateModel() )
1461 int originalIndex = -1;
1464 originalIndex = _originalLegendNodeIndex( legendNode );
1468 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode, legendNode, originalIndex );
1469 openPanel( widget );
1477QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1482QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1484 if ( !mView->currentNode() )
1487 if ( mWidget->legend()->autoUpdateModel() )
1490 QMenu *menu =
new QMenu();
1494 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1495 menu->addSeparator();
1500 QActionGroup *styleGroup =
new QActionGroup { mWidget };
1501 styleGroup->setExclusive(
true );
1503 QList<Qgis::LegendComponent> lst;
1507 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1508 action->setActionGroup( styleGroup );
1509 action->setCheckable(
true );
1510 action->setChecked( currentStyle == style );
1511 action->setData(
static_cast<int>( style ) );
1526 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1529 setPanelTitle( tr(
"Legend Item Properties" ) );
1538 QString currentLabel;
1541 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1542 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1546 currentLabel = mLayer->name();
1547 QVariant v = mLayer->customProperty( QStringLiteral(
"legend/title-label" ) );
1549 currentLabel = v.toString();
1550 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1552 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1557 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1560 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1561 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1562 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1563 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1564 mPatchGroup->setVisible( mLegendNode || mLayer );
1565 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1566 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1567 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1568 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1569 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1572 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1573 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1577 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1578 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1581 mCustomSymbolCheckBox->setChecked(
false );
1586 patchShape = symbolLegendNode->patchShape();
1588 std::unique_ptr<QgsSymbol> customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() : nullptr );
1589 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1592 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1594 mCustomSymbolButton->setSymbol( customSymbol.release() );
1596 else if ( symbolLegendNode->symbol() )
1598 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1599 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1600 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1603 else if ( !mLegendNode && mLayer )
1605 patchShape = mLayer->patchShape();
1608 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1610 mCustomSymbolCheckBox->setChecked(
true );
1611 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1613 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1617 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1618 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1619 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1626 switch ( qobject_cast<QgsVectorLayer *>( mLayer->layer() )->geometryType() )
1641 mPatchShapeLabel->hide();
1642 mPatchShapeButton->hide();
1645 if ( !patchShape.
isNull() )
1646 mPatchShapeButton->setShape( patchShape );
1650 if ( symbolLegendNode->symbol() )
1652 mPatchShapeButton->setSymbolType( symbolLegendNode->symbol()->type() );
1656 mPatchShapeLabel->hide();
1657 mPatchShapeButton->hide();
1662 mPatchShapeLabel->hide();
1663 mPatchShapeButton->hide();
1668 mLabelGroup->hide();
1669 mColorRampLegendWidget->setSettings( colorRampNode->settings() );
1673 mColorRampLegendWidget->hide();
1686 mCustomSymbolCheckBox->hide();
1695 mLabelEdit->setPlainText( currentLabel );
1696 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1698 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1700 connect( mWidthSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1701 connect( mHeightSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1703 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1706 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1708 connect( mColumnSplitBehaviorComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1712 connectChildPanel( mColorRampLegendWidget );
1715void QgsLayoutLegendNodeWidget::setDockMode(
bool dockMode )
1717 mColorRampLegendWidget->setDockMode( dockMode );
1721void QgsLayoutLegendNodeWidget::labelChanged()
1725 const QString label = mLabelEdit->toPlainText();
1730 else if ( mLegendNode )
1733 mLegend->model()->refreshLayerLegend( mLayer );
1737 mLayer->setCustomProperty( QStringLiteral(
"legend/title-label" ), label );
1741 embeddedNode->setUserLabel( QString() );
1744 mLegend->adjustBoxSize();
1745 mLegend->invalidateCache();
1747 mLegend->endCommand();
1750void QgsLayoutLegendNodeWidget::patchChanged()
1752 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1758 mLegend->model()->refreshLayerLegend( mLayer );
1762 mLayer->setPatchShape( shape );
1763 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1768 mLegend->model()->refreshLayerLegend( mLayer );
1771 mLegend->adjustBoxSize();
1773 mLegend->endCommand();
1776void QgsLayoutLegendNodeWidget::insertExpression()
1784 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1788 if ( mLayer && mLayer->layer() )
1793 context.
setHighlightedVariables( QStringList() << QStringLiteral(
"legend_title" ) << QStringLiteral(
"legend_column_count" ) << QStringLiteral(
"legend_split_layers" ) << QStringLiteral(
"legend_wrap_string" ) << QStringLiteral(
"legend_filter_by_map" ) << QStringLiteral(
"legend_filter_out_atlas" ) );
1797 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1798 if ( exprDlg.exec() == QDialog::Accepted )
1800 expression = exprDlg.expressionText();
1801 if ( !expression.isEmpty() )
1803 mLegend->beginCommand( tr(
"Insert expression" ) );
1804 mLabelEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
1805 mLegend->endCommand();
1810void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1812 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1813 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1818 mLegend->model()->refreshLayerLegend( mLayer );
1822 mLayer->setPatchSize( size );
1823 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1828 mLegend->model()->refreshLayerLegend( mLayer );
1831 mLegend->adjustBoxSize();
1833 mLegend->endCommand();
1836void QgsLayoutLegendNodeWidget::customSymbolChanged()
1838 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1840 if ( mCustomSymbolCheckBox->isChecked() )
1845 mLegend->model()->refreshLayerLegend( mLayer );
1849 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1854 mLegend->model()->refreshLayerLegend( mLayer );
1862 mLegend->model()->refreshLayerLegend( mLayer );
1866 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1871 mLegend->model()->refreshLayerLegend( mLayer );
1875 mLegend->adjustBoxSize();
1877 mLegend->endCommand();
1880void QgsLayoutLegendNodeWidget::colorRampLegendChanged()
1882 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1886 mLegend->model()->refreshLayerLegend( mLayer );
1888 mLegend->adjustBoxSize();
1890 mLegend->endCommand();
1893void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1895 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1900 mLegend->model()->refreshLayerLegend( mLayer );
1904 mLayer->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1908 mNode->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1911 mLegend->adjustBoxSize();
1913 mLegend->endCommand();
1916void QgsLayoutLegendNodeWidget::columnSplitChanged()
1918 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1920 if ( mLayer && !mLegendNode )
1925 mLegend->adjustBoxSize();
1927 mLegend->endCommand();
1934QgsLayoutLegendMapFilteringWidget::QgsLayoutLegendMapFilteringWidget(
QgsLayoutItemLegend *legend )
1936 , mLegendItem( legend )
1939 setPanelTitle( tr(
"Legend Filtering" ) );
1941 setNewItem( legend );
1944bool QgsLayoutLegendMapFilteringWidget::setNewItem(
QgsLayoutItem *item )
1954 mLegendItem = qobject_cast<QgsLayoutItemLegend *>( item );
1961 updateGuiElements();
1966void QgsLayoutLegendMapFilteringWidget::updateGuiElements()
1968 if ( mBlockUpdates )
1971 mBlockUpdates =
true;
1973 if ( mFilterMapItemsListView->model() )
1975 QAbstractItemModel *oldModel = mFilterMapItemsListView->model();
1976 mFilterMapItemsListView->setModel(
nullptr );
1977 oldModel->deleteLater();
1980 QgsLayoutLegendMapFilteringModel *model =
new QgsLayoutLegendMapFilteringModel( mLegendItem, mLegendItem->layout()->itemsModel(), mFilterMapItemsListView );
1981 mFilterMapItemsListView->setModel( model );
1983 mBlockUpdates =
false;
1991 : QSortFilterProxyModel( parent )
1992 , mLayoutModel( layoutModel )
1993 , mLegendItem( legend )
1995 setSourceModel( layoutModel );
1998int QgsLayoutLegendMapFilteringModel::columnCount(
const QModelIndex & )
const
2003QVariant QgsLayoutLegendMapFilteringModel::data(
const QModelIndex &i,
int role )
const
2008 if ( i.column() != 0 )
2013 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( i ) ) );
2021 case Qt::CheckStateRole:
2022 switch ( i.column() )
2027 return Qt::Unchecked;
2029 return mLegendItem->filterByMapItems().contains( mapItem ) ? Qt::Checked : Qt::Unchecked;
2037 return mLayoutModel->data( sourceIndex, role );
2041bool QgsLayoutLegendMapFilteringModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
2045 if ( !index.isValid() )
2048 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2049 if ( !mapItem || !mLegendItem )
2054 mLegendItem->layout()->undoStack()->beginCommand( mLegendItem, tr(
"Change Legend Linked Maps" ) );
2056 QList<QgsLayoutItemMap *> linkedMaps = mLegendItem->filterByMapItems();
2057 if ( value.toBool() )
2059 if ( !linkedMaps.contains( mapItem ) )
2061 linkedMaps.append( mapItem );
2062 mLegendItem->setFilterByMapItems( linkedMaps );
2067 linkedMaps.removeAll( mapItem );
2068 mLegendItem->setFilterByMapItems( linkedMaps );
2070 emit dataChanged( index, index, QVector<int>() << role );
2072 mLegendItem->layout()->undoStack()->endCommand();
2073 mLegendItem->invalidateCache();
2078Qt::ItemFlags QgsLayoutLegendMapFilteringModel::flags(
const QModelIndex &index )
const
2080 Qt::ItemFlags flags = QSortFilterProxyModel::flags( index );
2082 if ( !index.isValid() )
2087 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2088 const bool isMainLinkedMapItem = mLegendItem ? ( mLegendItem->linkedMap() == mapItem ) : false;
2094 if ( !isMainLinkedMapItem )
2096 flags |= Qt::ItemIsEnabled;
2100 flags &= ~Qt::ItemIsEnabled;
2103 switch ( index.column() )
2106 if ( !isMainLinkedMapItem )
2107 return flags | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
2109 return flags | Qt::ItemIsSelectable;
2112 return flags | Qt::ItemIsSelectable;
2116bool QgsLayoutLegendMapFilteringModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
2118 QgsLayoutItem *item = mLayoutModel->itemFromIndex( mLayoutModel->index( source_row, 0, source_parent ) );
LegendComponent
Component of legends which can be styled.
@ Symbol
Symbol icon (excluding label)
@ Group
Legend group title.
@ Hidden
Special style, item is hidden including margins around.
@ Subgroup
Legend subgroup title.
@ SymbolLabel
Symbol label (excluding icon)
void changed()
Emitted when the alignment is changed.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
Settings for a color ramp legend node.
A legend node which renders a color ramp.
A generic dialog for building expression strings.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
static QString findAndSelectActiveExpression(QgsCodeEditor *editor, const QString &pattern=QString())
Find the expression under the cursor in the given editor and select it.
Container of fields for a vector layer.
Layer tree group node serves as a container for layers and further groups.
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position.
void setName(const QString &n) override
Sets the group's name.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group.
QString name() const override
Returns the group's name.
Layer tree node points to a map layer.
void setPatchSize(QSizeF size)
Sets the user (overridden) size for the legend node.
QString labelExpression() const
Returns the expression member of the LayerTreeNode.
LegendNodesSplitBehavior
Legend node column split behavior.
@ AllowSplittingLegendNodesOverMultipleColumns
Allow splitting node's legend nodes across multiple columns.
@ PreventSplittingLegendNodesOverMultipleColumns
Prevent splitting node's legend nodes across multiple columns.
@ UseDefaultLegendSetting
Inherit default legend column splitting setting.
void setLabelExpression(const QString &expression)
set the expression to evaluate
void setPatchShape(const QgsLegendPatchShape &shape)
Sets the symbol patch shape to use when rendering the legend node symbol.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
The QgsLegendRendererItem class is abstract interface for legend items returned from QgsMapLayerLegen...
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.
This class is a base class for nodes in a layer tree.
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
QStringList customProperties() const
Returns list of keys stored in custom properties.
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance.
static void setLegendFilterByExpression(QgsLayerTreeLayer &layer, const QString &expr, bool enabled=true)
Sets the expression filter of a legend layer.
static QString legendFilterByExpression(const QgsLayerTreeLayer &layer, bool *enabled=nullptr)
Returns the expression filter of a legend layer.
The QgsLayerTreeView class extends QTreeView and provides some additional functionality when working ...
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.
Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector ...
void toggled(bool enabled)
Emitted when atlas is enabled or disabled.
A common interface for layout designer dialogs and widgets.
virtual QgsMessageBar * messageBar()=0
Returns the designer's message bar.
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
A layout item subclass for map legends.
QgsLegendModel * model()
Returns the legend model.
Layout graphical items for displaying a map.
@ LayoutLegend
Legend item.
Base class for graphical items within a QgsLayout.
@ UndoLegendMinSymbolSize
Legend minimum symbol size.
@ UndoLegendTitleSpaceBottom
Legend title space.
@ UndoLegendIconSymbolSpace
Legend icon symbol space.
@ UndoLegendLayerFont
Legend layer font.
@ UndoLegendBoxSpace
Legend box space.
@ UndoLegendRasterStrokeColor
Legend raster stroke color.
@ UndoLegendTitleFont
Legend title font.
@ UndoLegendItemFont
Legend item font.
@ UndoLegendWmsLegendWidth
Legend WMS width.
@ UndoLegendLayerSpace
Legend layer spacing.
@ UndoLegendColumnSpace
Legend column space.
@ UndoLegendMaxSymbolSize
Legend maximum symbol size.
@ 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.
This class 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.
@ LegendTitle
Legend title.
@ LegendColumnCount
Legend column count.
void layerChanged(QgsVectorLayer *layer)
Emitted when the context's layer is changed.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
QgsLayoutReportContext & reportContext()
Returns a reference to the layout's report context, which stores information relating to the current ...
Item model implementation based on layer tree model for layout legend.
Represents a patch shape for use in map legends.
void setSymbolType(Qgis::SymbolType type)
Sets the symbol type associated with this patch.
bool isNull() const
Returns true if the patch shape is a null QgsLegendPatchShape, which indicates that the default legen...
static void setNodeLegendStyle(QgsLayerTreeNode *node, Qgis::LegendComponent style)
Sets the style of a node.
static Qgis::LegendComponent nodeLegendStyle(QgsLayerTreeNode *node, QgsLayerTreeModel *model)
Returns the style for the given node, within the specified model.
static QString styleLabel(Qgis::LegendComponent s)
Returns a translated string representing a style component, for use in UI.
Map canvas is a class for displaying all GIS data types on a canvas.
static void setLegendNodeOrder(QgsLayerTreeLayer *nodeLayer, const QList< int > &order)
static void setLegendNodeColorRampSettings(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsColorRampLegendNodeSettings *settings)
Sets a custom legend color ramp settings for the legend node belonging to nodeLayer at the specified ...
static void setLegendNodeCustomSymbol(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsSymbol *symbol)
Sets a custom legend symbol for the legend node belonging to nodeLayer at the specified originalIndex...
static void setLegendNodeUserLabel(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QString &newLabel)
static void setLegendNodeSymbolSize(QgsLayerTreeLayer *nodeLayer, int originalIndex, QSizeF size)
Sets the legend symbol size for the legend node belonging to nodeLayer at the specified originalIndex...
static void setLegendNodeColumnBreak(QgsLayerTreeLayer *nodeLayer, int originalIndex, bool columnBreakBeforeNode)
Sets whether a forced column break should occur before the node.
static void setLegendNodePatchShape(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsLegendPatchShape &shape)
Sets the legend patch shape for the legend node belonging to nodeLayer at the specified originalIndex...
static QList< int > legendNodeOrder(QgsLayerTreeLayer *nodeLayer)
Base class for all map layer types.
Interface for master layout type objects, such as print layouts and reports.
static int qtDefaultDpiX()
Returns the default Qt horizontal DPI.
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
Abstract base class for all rendered symbols.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
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.