19#include "moc_qgslayoutlegendwidget.cpp"
51#include <QInputDialog>
52#include <QActionGroup>
67 int unfilteredNodeIndex = _unfilteredLegendNodeIndex( legendNode );
69 return ( unfilteredNodeIndex >= 0 && unfilteredNodeIndex < order.count() ? order[unfilteredNodeIndex] : -1 );
76 , mMapCanvas( mapCanvas )
81 connect( mWrapCharLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
82 connect( mTitleLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
87 connect( mColumnCountSpinBox,
static_cast<void ( QSpinBox::* )(
int )
>( &QSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
88 connect( mSplitLayerCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
89 connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
90 connect( mSymbolWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged );
91 connect( mSymbolHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged );
92 connect( mMaxSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged );
93 connect( mMinSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged );
94 connect( mWmsLegendWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
95 connect( mWmsLegendHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
96 connect( mTitleSpaceBottomSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
97 connect( mGroupSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
98 connect( mGroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged );
99 connect( mSubgroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged );
100 connect( mSpaceBelowGroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
101 connect( mGroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
102 connect( mLayerSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
103 connect( mSpaceBelowSubgroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
104 connect( mSubgroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
105 connect( mSymbolSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
106 connect( mSymbolSideSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
107 connect( mIconLabelSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
108 connect( mBoxSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
109 connect( mColumnSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged );
110 connect( mCheckBoxAutoUpdate, &QCheckBox::stateChanged,
this, [=](
int state ) { mCheckBoxAutoUpdate_stateChanged( state ); } );
111 connect( mCheckboxResizeContents, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mCheckboxResizeContents_toggled );
112 connect( mRasterStrokeGroupBox, &QgsCollapsibleGroupBoxBasic::toggled,
this, &QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled );
113 connect( mRasterStrokeWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged );
114 connect( mRasterStrokeColorButton, &
QgsColorButton::colorChanged,
this, &QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged );
115 connect( mExpandAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::expandLegendTree );
116 connect( mCollapseAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::collapseLegendTree );
117 connect( mMoveDownToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveDownToolButton_clicked );
118 connect( mMoveUpToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveUpToolButton_clicked );
119 connect( mRemoveToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mRemoveToolButton_clicked );
120 connect( mAddToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddToolButton_clicked );
121 connect( mEditPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mEditPushButton_clicked );
122 connect( mCountToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mCountToolButton_clicked );
123 connect( mExpressionFilterButton, &QgsLegendFilterButton::toggled,
this, &QgsLayoutLegendWidget::mExpressionFilterButton_toggled );
124 connect( mLayerExpressionButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mLayerExpressionButton_clicked );
125 connect( mFilterByMapCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled );
126 connect( mUpdateAllPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mUpdateAllPushButton_clicked );
127 connect( mAddGroupToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddGroupToolButton_clicked );
128 connect( mFilterLegendByAtlasCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled );
129 connect( mItemTreeView, &QgsLayerTreeView::doubleClicked,
this, &QgsLayoutLegendWidget::mItemTreeView_doubleClicked );
131 connect( mFilterByMapCheckBox, &QCheckBox::toggled, mButtonLinkedMaps, &QWidget::setEnabled );
132 mButtonLinkedMaps->setEnabled(
false );
133 connect( mButtonLinkedMaps, &QToolButton::clicked,
this, [=] {
134 mMapFilteringWidget =
new QgsLayoutLegendMapFilteringWidget( mLegend );
135 openPanel( mMapFilteringWidget );
138 setPanelTitle( tr(
"Legend Properties" ) );
145 mTitleAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
146 mGroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
147 mSubgroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
148 mItemAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
150 mArrangementCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignRight );
152 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignLeft, tr(
"Symbols on Left" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsLeft.svg" ) ) );
153 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignRight, tr(
"Symbols on Right" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsRight.svg" ) ) );
155 mSpaceBelowGroupHeadingSpinBox->setClearValue( 0 );
156 mGroupSideSpinBox->setClearValue( 0 );
157 mSpaceBelowSubgroupHeadingSpinBox->setClearValue( 0 );
158 mSubgroupSideSpinBox->setClearValue( 0 );
159 mSymbolSideSpaceSpinBox->setClearValue( 0 );
184 mRasterStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
185 mRasterStrokeColorButton->setAllowOpacity(
true );
186 mRasterStrokeColorButton->setContext( QStringLiteral(
"composer " ) );
188 mMapComboBox->setCurrentLayout( legend->
layout() );
194 mainLayout->addWidget( mItemPropertiesWidget );
196 mItemTreeView->setHeaderHidden(
true );
198 mItemTreeView->setModel( legend->
model() );
199 mItemTreeView->setMenuProvider(
new QgsLayoutLegendMenuProvider( mItemTreeView,
this ) );
200 setLegendMapViewData();
206 connect( layoutAtlas(), &
QgsLayoutAtlas::toggled,
this, &QgsLayoutLegendWidget::updateFilterLegendByAtlasButton );
210 mTitleFontButton->registerExpressionContextGenerator(
this );
211 mGroupFontButton->registerExpressionContextGenerator(
this );
212 mLayerFontButton->registerExpressionContextGenerator(
this );
213 mItemFontButton->registerExpressionContextGenerator(
this );
214 mExpressionFilterButton->registerExpressionContextGenerator(
this );
216 mTitleFontButton->setLayer( coverageLayer() );
217 mGroupFontButton->setLayer( coverageLayer() );
218 mLayerFontButton->setLayer( coverageLayer() );
219 mItemFontButton->setLayer( coverageLayer() );
220 if ( mLegend->layout() )
233 connect( mItemTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsLayoutLegendWidget::selectedChanged );
242 if ( mItemPropertiesWidget )
243 mItemPropertiesWidget->setMasterLayout( masterLayout );
249 mTitleFontButton->setMessageBar( iface->
messageBar() );
250 mGroupFontButton->setMessageBar( iface->
messageBar() );
251 mLayerFontButton->setMessageBar( iface->
messageBar() );
252 mItemFontButton->setMessageBar( iface->
messageBar() );
255void QgsLayoutLegendWidget::setGuiElements()
262 blockAllSignals(
true );
263 mTitleLineEdit->setText( mLegend->title() );
264 whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
268 whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
269 mFilterByMapCheckBox->setChecked( mLegend->legendFilterByMapEnabled() );
270 mButtonLinkedMaps->setEnabled( mLegend->legendFilterByMapEnabled() );
271 mColumnCountSpinBox->setValue( mLegend->columnCount() );
272 mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
273 mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
274 mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
275 mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
276 mMaxSymbolSizeSpinBox->setValue( mLegend->maximumSymbolSize() );
277 mMinSymbolSizeSpinBox->setValue( mLegend->minimumSymbolSize() );
278 mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
279 mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
293 mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
294 mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
296 mRasterStrokeGroupBox->setChecked( mLegend->drawRasterStroke() );
297 mRasterStrokeWidthSpinBox->setValue( mLegend->rasterStrokeWidth() );
298 mRasterStrokeColorButton->setColor( mLegend->rasterStrokeColor() );
300 mCheckBoxAutoUpdate->setChecked( mLegend->autoUpdateModel() );
302 mCheckboxResizeContents->setChecked( mLegend->resizeToContents() );
303 mFilterLegendByAtlasCheckBox->setChecked( mLegend->legendFilterOutAtlas() );
304 mWrapCharLineEdit->setText( mLegend->wrapString() );
307 mMapComboBox->setItem( map );
313 blockAllSignals(
false );
315 mCheckBoxAutoUpdate_stateChanged( mLegend->autoUpdateModel() ? Qt::Checked : Qt::Unchecked, false );
316 updateDataDefinedButton( mLegendTitleDDBtn );
317 updateDataDefinedButton( mColumnsDDBtn );
320void QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged(
const QString &text )
324 mLegend->beginCommand( tr(
"Change Legend Wrap" ) );
325 mLegend->setWrapString( text );
326 mLegend->adjustBoxSize();
328 mLegend->endCommand();
332void QgsLayoutLegendWidget::mTitleLineEdit_textChanged(
const QString &text )
337 mLegend->setTitle( text );
338 mLegend->adjustBoxSize();
340 mLegend->endCommand();
344void QgsLayoutLegendWidget::titleAlignmentChanged()
348 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
349 mLegend->beginCommand( tr(
"Change Title Alignment" ) );
350 mLegend->setTitleAlignment( alignment );
352 mLegend->endCommand();
356void QgsLayoutLegendWidget::groupAlignmentChanged()
360 mLegend->beginCommand( tr(
"Change Group Alignment" ) );
363 mLegend->endCommand();
367void QgsLayoutLegendWidget::subgroupAlignmentChanged()
371 mLegend->beginCommand( tr(
"Change Subgroup Alignment" ) );
374 mLegend->endCommand();
378void QgsLayoutLegendWidget::itemAlignmentChanged()
382 mLegend->beginCommand( tr(
"Change Item Alignment" ) );
385 mLegend->endCommand();
389void QgsLayoutLegendWidget::arrangementChanged()
393 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
394 mLegend->beginCommand( tr(
"Change Legend Arrangement" ) );
395 mLegend->setSymbolAlignment( alignment );
397 mLegend->endCommand();
401void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged(
int c )
406 mLegend->setColumnCount(
c );
407 mLegend->adjustBoxSize();
409 mLegend->endCommand();
411 mSplitLayerCheckBox->setEnabled(
c > 1 );
412 mEqualColumnWidthCheckBox->setEnabled(
c > 1 );
415void QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled(
bool checked )
419 mLegend->beginCommand( tr(
"Split Legend Layers" ) );
420 mLegend->setSplitLayer( checked );
421 mLegend->adjustBoxSize();
423 mLegend->endCommand();
427void QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled(
bool checked )
431 mLegend->beginCommand( tr(
"Legend Column Width" ) );
432 mLegend->setEqualColumnWidth( checked );
433 mLegend->adjustBoxSize();
435 mLegend->endCommand();
439void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged(
double d )
444 mLegend->setSymbolWidth( d );
445 mLegend->adjustBoxSize();
447 mLegend->endCommand();
451void QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged(
double d )
456 mLegend->setMaximumSymbolSize( d );
457 mLegend->adjustBoxSize();
459 mLegend->endCommand();
463void QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged(
double d )
468 mLegend->setMinimumSymbolSize( d );
469 mLegend->adjustBoxSize();
471 mLegend->endCommand();
475void QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged(
double d )
480 mLegend->setSymbolHeight( d );
481 mLegend->adjustBoxSize();
483 mLegend->endCommand();
487void QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged(
double d )
492 mLegend->setWmsLegendWidth( d );
493 mLegend->adjustBoxSize();
495 mLegend->endCommand();
499void QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged(
double d )
504 mLegend->setWmsLegendHeight( d );
505 mLegend->adjustBoxSize();
507 mLegend->endCommand();
511void QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged(
double d )
517 mLegend->adjustBoxSize();
519 mLegend->endCommand();
523void QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged(
double d )
529 mLegend->adjustBoxSize();
531 mLegend->endCommand();
535void QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged(
double d )
541 mLegend->adjustBoxSize();
543 mLegend->endCommand();
547void QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged(
double d )
553 mLegend->adjustBoxSize();
555 mLegend->endCommand();
559void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged(
double space )
565 mLegend->adjustBoxSize();
567 mLegend->endCommand();
571void QgsLayoutLegendWidget::spaceGroupSideChanged(
double space )
577 mLegend->adjustBoxSize();
579 mLegend->endCommand();
583void QgsLayoutLegendWidget::spaceSubGroupSideChanged(
double space )
589 mLegend->adjustBoxSize();
591 mLegend->endCommand();
595void QgsLayoutLegendWidget::spaceSymbolSideChanged(
double space )
601 mLegend->adjustBoxSize();
603 mLegend->endCommand();
607void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged(
double d )
613 mLegend->adjustBoxSize();
615 mLegend->endCommand();
619void QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged(
double d )
627 mLegend->adjustBoxSize();
629 mLegend->endCommand();
633void QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged(
double d )
639 mLegend->adjustBoxSize();
641 mLegend->endCommand();
645void QgsLayoutLegendWidget::titleFontChanged()
651 mLegend->adjustBoxSize();
653 mLegend->endCommand();
657void QgsLayoutLegendWidget::groupFontChanged()
663 mLegend->adjustBoxSize();
665 mLegend->endCommand();
669void QgsLayoutLegendWidget::layerFontChanged()
675 mLegend->adjustBoxSize();
677 mLegend->endCommand();
681void QgsLayoutLegendWidget::itemFontChanged()
687 mLegend->adjustBoxSize();
689 mLegend->endCommand();
693void QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged(
double space )
699 mLegend->adjustBoxSize();
701 mLegend->endCommand();
705void QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged(
double d )
710 mLegend->setBoxSpace( d );
711 mLegend->adjustBoxSize();
713 mLegend->endCommand();
717void QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged(
double d )
722 mLegend->setColumnSpace( d );
723 mLegend->adjustBoxSize();
725 mLegend->endCommand();
729static void _moveLegendNode(
QgsLayerTreeLayer *nodeLayer,
int legendNodeIndex,
int offset )
733 if ( legendNodeIndex < 0 || legendNodeIndex >= order.count() )
735 if ( legendNodeIndex + offset < 0 || legendNodeIndex + offset >= order.count() )
738 int id = order.takeAt( legendNodeIndex );
739 order.insert( legendNodeIndex + offset,
id );
745void QgsLayoutLegendWidget::mMoveDownToolButton_clicked()
752 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
753 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
754 const QModelIndex parentIndex = sourceIndex.parent();
755 if ( !sourceIndex.isValid() || sourceIndex.row() == mItemTreeView->layerTreeModel()->rowCount( parentIndex ) - 1 )
760 if ( !node && !legendNode )
763 mLegend->beginCommand( tr(
"Moved Legend Item Down" ) );
777 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() + 1, 0, parentIndex ) ) );
780 mLegend->endCommand();
783void QgsLayoutLegendWidget::mMoveUpToolButton_clicked()
790 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
791 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
792 const QModelIndex parentIndex = sourceIndex.parent();
793 if ( !sourceIndex.isValid() || sourceIndex.row() == 0 )
798 if ( !node && !legendNode )
801 mLegend->beginCommand( tr(
"Move Legend Item Up" ) );
815 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() - 1, 0, parentIndex ) ) );
818 mLegend->endCommand();
821void QgsLayoutLegendWidget::expandLegendTree()
823 mItemTreeView->expandAll();
826void QgsLayoutLegendWidget::collapseLegendTree()
828 mItemTreeView->collapseAll();
831void QgsLayoutLegendWidget::mCheckBoxAutoUpdate_stateChanged(
int state,
bool userTriggered )
835 mLegend->beginCommand( tr(
"Change Auto Update" ) );
837 mLegend->setAutoUpdateModel( state == Qt::Checked );
839 mLegend->endCommand();
843 QList<QWidget *> widgets;
844 widgets << mMoveDownToolButton << mMoveUpToolButton << mRemoveToolButton << mAddToolButton
845 << mEditPushButton << mCountToolButton << mUpdateAllPushButton << mAddGroupToolButton
846 << mExpressionFilterButton << mCollapseAllToolButton << mExpandAllToolButton;
847 for ( QWidget *w : std::as_const( widgets ) )
848 w->setEnabled( state != Qt::Checked );
850 if ( state == Qt::Unchecked )
853 selectedChanged( QModelIndex(), QModelIndex() );
854 mItemTreeView->proxyModel()->setShowPrivateLayers(
true );
858 mItemTreeView->proxyModel()->setShowPrivateLayers(
false );
862void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
878 mLegend->beginCommand( tr(
"Change Legend Map" ) );
879 mLegend->setLinkedMap( map );
881 mLegend->endCommand();
883 setLegendMapViewData();
887void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
894 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
895 mLegend->setResizeToContents( checked );
897 mLegend->adjustBoxSize();
899 mLegend->endCommand();
902void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
909 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
910 mLegend->setDrawRasterStroke( state );
911 mLegend->adjustBoxSize();
913 mLegend->endCommand();
916void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
924 mLegend->setRasterStrokeWidth( d );
925 mLegend->adjustBoxSize();
927 mLegend->endCommand();
930void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
938 mLegend->setRasterStrokeColor( newColor );
940 mLegend->endCommand();
943void QgsLayoutLegendWidget::mAddToolButton_clicked()
950 QList<QgsMapLayer *> visibleLayers;
951 if ( mLegend->linkedMap() )
953 visibleLayers = mLegend->linkedMap()->layersToRender();
955 if ( visibleLayers.isEmpty() )
958 visibleLayers = mMapCanvas->layers(
true );
962 addDialog.setVisibleLayers( visibleLayers );
963 if ( addDialog.exec() == QDialog::Accepted )
965 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
966 if ( !layers.empty() )
968 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
971 mLegend->model()->rootGroup()->addLayer( layer );
973 mLegend->updateLegend();
975 mLegend->endCommand();
980void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
987 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
988 if ( !selectionModel )
993 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
995 QList<QPersistentModelIndex> proxyIndexes;
996 const QModelIndexList viewSelection = selectionModel->selectedIndexes();
997 for (
const QModelIndex &index : viewSelection )
998 proxyIndexes << index;
1001 QHash<QgsLayerTreeLayer *, QList<int>> nodesWithRemoval;
1002 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1007 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex( legendNode ) );
1010 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
1012 QList<int> toDelete = it.value();
1013 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
1016 for (
int i : std::as_const( toDelete ) )
1018 if ( i >= 0 && i < order.count() )
1019 order.removeAt( i );
1023 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
1027 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1029 if ( proxyIndex.isValid() && mItemTreeView->index2node( proxyIndex ) )
1031 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( proxyIndex );
1032 mLegend->model()->removeRow( sourceIndex.row(), sourceIndex.parent() );
1036 mLegend->updateLegend();
1038 mLegend->endCommand();
1041void QgsLayoutLegendWidget::mEditPushButton_clicked()
1048 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
1049 mItemTreeView_doubleClicked( idx );
1052void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
1060 QModelIndex currentIndex = mItemTreeView->currentIndex();
1061 if ( !currentIndex.isValid() )
1080 mLegend->beginCommand( tr(
"Update Legend" ) );
1083 for (
const QString &key : constCustomProperties )
1085 if ( key.startsWith( QLatin1String(
"legend/" ) ) )
1092 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1094 mLegend->updateLegend();
1096 mLegend->endCommand();
1099void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1106 const QList<QModelIndex> selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1107 if ( selectedIndexes.empty() )
1110 mLegend->beginCommand( tr(
"Update Legend" ) );
1111 for (
const QModelIndex &index : selectedIndexes )
1117 currentNode->
setCustomProperty( QStringLiteral(
"showFeatureCount" ), checked ? 1 : 0 );
1119 mLegend->updateFilterByMap();
1120 mLegend->adjustBoxSize();
1121 mLegend->endCommand();
1124void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1126 mLegend->beginCommand( tr(
"Update Legend" ) );
1127 mLegend->setLegendFilterByMapEnabled( checked );
1128 mLegend->adjustBoxSize();
1130 mLegend->endCommand();
1133void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1141 QModelIndex currentIndex = mItemTreeView->currentIndex();
1142 if ( !currentIndex.isValid() )
1153 mLegend->beginCommand( tr(
"Update Legend" ) );
1154 mLegend->updateFilterByMap();
1155 mLegend->adjustBoxSize();
1156 mLegend->endCommand();
1159void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1166 QModelIndex currentIndex = mItemTreeView->currentIndex();
1167 if ( !currentIndex.isValid() )
1174 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1180 QString currentExpression;
1182 currentExpression = QStringLiteral(
"@symbol_label" );
1188 QStringList highlighted;
1191 const QList<QgsLayerTreeModelLegendNode *> legendNodes = model->layerLegendNodes( layerNode,
false );
1192 if ( !legendNodes.isEmpty() )
1194 if (
QgsSymbolLegendNode *symbolNode = qobject_cast<QgsSymbolLegendNode *>( legendNodes.first() ) )
1196 legendContext.
appendScope( symbolNode->createSymbolScope() );
1197 highlighted << QStringLiteral(
"symbol_label" ) << QStringLiteral(
"symbol_id" ) << QStringLiteral(
"symbol_count" );
1210 QgsExpressionBuilderDialog expressiondialog(
nullptr, currentExpression,
nullptr, QStringLiteral(
"generic" ), legendContext );
1211 if ( expressiondialog.exec() )
1214 mItemTreeView->layerTreeModel()->refreshLayerLegend( layerNode );
1217 mLegend->beginCommand( tr(
"Update Legend" ) );
1219 mLegend->adjustBoxSize();
1220 mLegend->endCommand();
1223void QgsLayoutLegendWidget::mUpdateAllPushButton_clicked()
1228void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1232 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1233 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1234 mLegend->updateLegend();
1236 mLegend->endCommand();
1240void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1245 mLegend->setLegendFilterOutAtlas( toggled );
1251void QgsLayoutLegendWidget::updateLegend()
1255 mLegend->beginCommand( tr(
"Update Legend" ) );
1258 mLegend->setAutoUpdateModel(
true );
1259 mLegend->setAutoUpdateModel(
false );
1261 mLegend->endCommand();
1265void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1267 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1268 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1277bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1287 mLegend = qobject_cast<QgsLayoutItemLegend *>( item );
1288 mItemPropertiesWidget->setItem( mLegend );
1290 if ( mMapFilteringWidget )
1291 mMapFilteringWidget->setItem( mLegend );
1295 mItemTreeView->setModel( mLegend->model() );
1304void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1306 mTitleLineEdit->blockSignals( b );
1307 mTitleAlignCombo->blockSignals( b );
1308 mItemTreeView->blockSignals( b );
1309 mCheckBoxAutoUpdate->blockSignals( b );
1310 mMapComboBox->blockSignals( b );
1311 mFilterByMapCheckBox->blockSignals( b );
1312 mColumnCountSpinBox->blockSignals( b );
1313 mSplitLayerCheckBox->blockSignals( b );
1314 mEqualColumnWidthCheckBox->blockSignals( b );
1315 mSymbolWidthSpinBox->blockSignals( b );
1316 mSymbolHeightSpinBox->blockSignals( b );
1317 mMaxSymbolSizeSpinBox->blockSignals( b );
1318 mMinSymbolSizeSpinBox->blockSignals( b );
1319 mGroupSpaceSpinBox->blockSignals( b );
1320 mGroupIndentSpinBox->blockSignals( b );
1321 mSubgroupIndentSpinBox->blockSignals( b );
1322 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1323 mGroupSideSpinBox->blockSignals( b );
1324 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1325 mSubgroupSideSpinBox->blockSignals( b );
1326 mLayerSpaceSpinBox->blockSignals( b );
1327 mSymbolSpaceSpinBox->blockSignals( b );
1328 mSymbolSideSpaceSpinBox->blockSignals( b );
1329 mIconLabelSpaceSpinBox->blockSignals( b );
1330 mBoxSpaceSpinBox->blockSignals( b );
1331 mColumnSpaceSpinBox->blockSignals( b );
1332 mRasterStrokeGroupBox->blockSignals( b );
1333 mRasterStrokeColorButton->blockSignals( b );
1334 mRasterStrokeWidthSpinBox->blockSignals( b );
1335 mWmsLegendWidthSpinBox->blockSignals( b );
1336 mWmsLegendHeightSpinBox->blockSignals( b );
1337 mCheckboxResizeContents->blockSignals( b );
1338 mTitleSpaceBottomSpinBox->blockSignals( b );
1339 mFilterLegendByAtlasCheckBox->blockSignals( b );
1340 mTitleFontButton->blockSignals( b );
1341 mGroupFontButton->blockSignals( b );
1342 mLayerFontButton->blockSignals( b );
1343 mItemFontButton->blockSignals( b );
1344 mWrapCharLineEdit->blockSignals( b );
1347void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1350 Q_UNUSED( previous )
1352 mLayerExpressionButton->setEnabled(
false );
1354 if ( mLegend && mLegend->autoUpdateModel() )
1365 mLayerExpressionButton->setEnabled(
true );
1369 mCountToolButton->setChecked(
false );
1370 mCountToolButton->setEnabled(
false );
1373 mExpressionFilterButton->blockSignals(
true );
1374 mExpressionFilterButton->setChecked(
false );
1375 mExpressionFilterButton->setEnabled(
false );
1376 mExpressionFilterButton->blockSignals(
false );
1387 mCountToolButton->setChecked( currentNode->
customProperty( QStringLiteral(
"showFeatureCount" ), 0 ).toInt() );
1388 mCountToolButton->setEnabled(
true );
1389 mLayerExpressionButton->setEnabled(
true );
1393 mExpressionFilterButton->blockSignals(
true );
1394 mExpressionFilterButton->setExpressionText( expr );
1395 mExpressionFilterButton->setVectorLayer( vl );
1396 mExpressionFilterButton->setEnabled(
true );
1397 mExpressionFilterButton->setChecked( exprEnabled );
1398 mExpressionFilterButton->blockSignals(
false );
1401void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1403 QAction *a = qobject_cast<QAction *>( sender() );
1404 if ( !a || !mItemTreeView->currentNode() )
1411void QgsLayoutLegendWidget::setLegendMapViewData()
1413 if ( mLegend->linkedMap() )
1417 measurementConverter.
setDpi( dpi );
1420 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1421 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1422 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1426void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1430 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
Qgis::GeometryType::Polygon );
1434void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1436 if ( !mLegend || !idx.isValid() )
1441 if ( mLegend->autoUpdateModel() )
1447 int originalIndex = -1;
1450 originalIndex = _originalLegendNodeIndex( legendNode );
1454 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode, legendNode, originalIndex );
1455 openPanel( widget );
1463QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1468QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1470 if ( !mView->currentNode() )
1473 if ( mWidget->legend()->autoUpdateModel() )
1476 QMenu *menu =
new QMenu();
1480 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1481 menu->addSeparator();
1486 QActionGroup *styleGroup =
new QActionGroup { mWidget };
1487 styleGroup->setExclusive(
true );
1489 QList<QgsLegendStyle::Style> lst;
1493 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1494 action->setActionGroup( styleGroup );
1495 action->setCheckable(
true );
1496 action->setChecked( currentStyle == style );
1497 action->setData(
static_cast<int>( style ) );
1512 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1515 setPanelTitle( tr(
"Legend Item Properties" ) );
1524 QString currentLabel;
1527 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1528 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1532 currentLabel = mLayer->name();
1533 QVariant v = mLayer->customProperty( QStringLiteral(
"legend/title-label" ) );
1535 currentLabel = v.toString();
1536 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1538 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1543 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1546 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1547 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1548 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1549 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1550 mPatchGroup->setVisible( mLegendNode || mLayer );
1551 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1552 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1553 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1554 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1555 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1558 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1559 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1563 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1564 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1567 mCustomSymbolCheckBox->setChecked(
false );
1572 patchShape = symbolLegendNode->patchShape();
1574 std::unique_ptr<QgsSymbol> customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() : nullptr );
1575 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1578 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1580 mCustomSymbolButton->setSymbol( customSymbol.release() );
1582 else if ( symbolLegendNode->symbol() )
1584 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1585 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1586 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1589 else if ( !mLegendNode && mLayer )
1591 patchShape = mLayer->patchShape();
1594 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1596 mCustomSymbolCheckBox->setChecked(
true );
1597 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1599 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1603 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1604 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1605 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1612 switch ( qobject_cast<QgsVectorLayer *>( mLayer->layer() )->geometryType() )
1627 mPatchShapeLabel->hide();
1628 mPatchShapeButton->hide();
1631 if ( !patchShape.
isNull() )
1632 mPatchShapeButton->setShape( patchShape );
1636 if ( symbolLegendNode->symbol() )
1638 mPatchShapeButton->setSymbolType( symbolLegendNode->symbol()->type() );
1642 mPatchShapeLabel->hide();
1643 mPatchShapeButton->hide();
1648 mPatchShapeLabel->hide();
1649 mPatchShapeButton->hide();
1654 mLabelGroup->hide();
1655 mColorRampLegendWidget->setSettings( colorRampNode->settings() );
1659 mColorRampLegendWidget->hide();
1672 mCustomSymbolCheckBox->hide();
1681 mLabelEdit->setPlainText( currentLabel );
1682 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1684 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1686 connect( mWidthSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1687 connect( mHeightSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1689 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1692 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1694 connect( mColumnSplitBehaviorComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1698 connectChildPanel( mColorRampLegendWidget );
1701void QgsLayoutLegendNodeWidget::setDockMode(
bool dockMode )
1703 mColorRampLegendWidget->setDockMode( dockMode );
1707void QgsLayoutLegendNodeWidget::labelChanged()
1711 const QString label = mLabelEdit->toPlainText();
1716 else if ( mLegendNode )
1719 mLegend->model()->refreshLayerLegend( mLayer );
1723 mLayer->setCustomProperty( QStringLiteral(
"legend/title-label" ), label );
1727 embeddedNode->setUserLabel( QString() );
1730 mLegend->adjustBoxSize();
1731 mLegend->invalidateCache();
1733 mLegend->endCommand();
1736void QgsLayoutLegendNodeWidget::patchChanged()
1738 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1744 mLegend->model()->refreshLayerLegend( mLayer );
1748 mLayer->setPatchShape( shape );
1749 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1754 mLegend->model()->refreshLayerLegend( mLayer );
1757 mLegend->adjustBoxSize();
1759 mLegend->endCommand();
1762void QgsLayoutLegendNodeWidget::insertExpression()
1770 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1774 if ( mLayer && mLayer->layer() )
1779 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" ) );
1783 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1784 if ( exprDlg.exec() == QDialog::Accepted )
1786 expression = exprDlg.expressionText();
1787 if ( !expression.isEmpty() )
1789 mLegend->beginCommand( tr(
"Insert expression" ) );
1790 mLabelEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
1791 mLegend->endCommand();
1796void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1798 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1799 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1804 mLegend->model()->refreshLayerLegend( mLayer );
1808 mLayer->setPatchSize( size );
1809 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1814 mLegend->model()->refreshLayerLegend( mLayer );
1817 mLegend->adjustBoxSize();
1819 mLegend->endCommand();
1822void QgsLayoutLegendNodeWidget::customSymbolChanged()
1824 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1826 if ( mCustomSymbolCheckBox->isChecked() )
1831 mLegend->model()->refreshLayerLegend( mLayer );
1835 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1840 mLegend->model()->refreshLayerLegend( mLayer );
1848 mLegend->model()->refreshLayerLegend( mLayer );
1852 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1857 mLegend->model()->refreshLayerLegend( mLayer );
1861 mLegend->adjustBoxSize();
1863 mLegend->endCommand();
1866void QgsLayoutLegendNodeWidget::colorRampLegendChanged()
1868 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1872 mLegend->model()->refreshLayerLegend( mLayer );
1874 mLegend->adjustBoxSize();
1876 mLegend->endCommand();
1879void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1881 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1886 mLegend->model()->refreshLayerLegend( mLayer );
1890 mLayer->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1894 mNode->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1897 mLegend->adjustBoxSize();
1899 mLegend->endCommand();
1902void QgsLayoutLegendNodeWidget::columnSplitChanged()
1904 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1906 if ( mLayer && !mLegendNode )
1911 mLegend->adjustBoxSize();
1913 mLegend->endCommand();
1920QgsLayoutLegendMapFilteringWidget::QgsLayoutLegendMapFilteringWidget(
QgsLayoutItemLegend *legend )
1922 , mLegendItem( legend )
1925 setPanelTitle( tr(
"Legend Filtering" ) );
1927 setNewItem( legend );
1930bool QgsLayoutLegendMapFilteringWidget::setNewItem(
QgsLayoutItem *item )
1940 mLegendItem = qobject_cast<QgsLayoutItemLegend *>( item );
1947 updateGuiElements();
1952void QgsLayoutLegendMapFilteringWidget::updateGuiElements()
1954 if ( mBlockUpdates )
1957 mBlockUpdates =
true;
1959 if ( mFilterMapItemsListView->model() )
1961 QAbstractItemModel *oldModel = mFilterMapItemsListView->model();
1962 mFilterMapItemsListView->setModel(
nullptr );
1963 oldModel->deleteLater();
1966 QgsLayoutLegendMapFilteringModel *model =
new QgsLayoutLegendMapFilteringModel( mLegendItem, mLegendItem->layout()->itemsModel(), mFilterMapItemsListView );
1967 mFilterMapItemsListView->setModel( model );
1969 mBlockUpdates =
false;
1977 : QSortFilterProxyModel( parent )
1978 , mLayoutModel( layoutModel )
1979 , mLegendItem( legend )
1981 setSourceModel( layoutModel );
1984int QgsLayoutLegendMapFilteringModel::columnCount(
const QModelIndex & )
const
1989QVariant QgsLayoutLegendMapFilteringModel::data(
const QModelIndex &i,
int role )
const
1994 if ( i.column() != 0 )
1999 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( i ) ) );
2007 case Qt::CheckStateRole:
2008 switch ( i.column() )
2013 return Qt::Unchecked;
2015 return mLegendItem->filterByMapItems().contains( mapItem ) ? Qt::Checked : Qt::Unchecked;
2023 return mLayoutModel->data( sourceIndex, role );
2027bool QgsLayoutLegendMapFilteringModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
2031 if ( !index.isValid() )
2034 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2035 if ( !mapItem || !mLegendItem )
2040 mLegendItem->layout()->undoStack()->beginCommand( mLegendItem, tr(
"Change Legend Linked Maps" ) );
2042 QList<QgsLayoutItemMap *> linkedMaps = mLegendItem->filterByMapItems();
2043 if ( value.toBool() )
2045 if ( !linkedMaps.contains( mapItem ) )
2047 linkedMaps.append( mapItem );
2048 mLegendItem->setFilterByMapItems( linkedMaps );
2053 linkedMaps.removeAll( mapItem );
2054 mLegendItem->setFilterByMapItems( linkedMaps );
2056 emit dataChanged( index, index, QVector<int>() << role );
2058 mLegendItem->layout()->undoStack()->endCommand();
2059 mLegendItem->invalidateCache();
2064Qt::ItemFlags QgsLayoutLegendMapFilteringModel::flags(
const QModelIndex &index )
const
2066 Qt::ItemFlags flags = QSortFilterProxyModel::flags( index );
2068 if ( !index.isValid() )
2073 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2074 const bool isMainLinkedMapItem = mLegendItem ? ( mLegendItem->linkedMap() == mapItem ) : false;
2080 if ( !isMainLinkedMapItem )
2082 flags |= Qt::ItemIsEnabled;
2086 flags &= ~Qt::ItemIsEnabled;
2089 switch ( index.column() )
2092 if ( !isMainLinkedMapItem )
2093 return flags | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
2095 return flags | Qt::ItemIsSelectable;
2098 return flags | Qt::ItemIsSelectable;
2102bool QgsLayoutLegendMapFilteringModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
2104 QgsLayoutItem *item = mLayoutModel->itemFromIndex( mLayoutModel->index( source_row, 0, source_parent ) );
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, QgsLegendStyle::Style style)
Sets the style of a node.
static QgsLegendStyle::Style nodeLegendStyle(QgsLayerTreeNode *node, QgsLayerTreeModel *model)
Returns the style for the given node, within the specified model.
static QString styleLabel(Style s)
Returns a translated string representing a style component, for use in UI.
Style
Component of legends which can be styled.
@ Group
Legend group title.
@ Symbol
Symbol icon (excluding label)
@ Subgroup
Legend subgroup title.
@ Hidden
Special style, item is hidden including margins around.
@ SymbolLabel
Symbol label (excluding icon)
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.