50#include <QInputDialog>
51#include <QActionGroup>
66 int unfilteredNodeIndex = _unfilteredLegendNodeIndex( legendNode );
68 return ( unfilteredNodeIndex >= 0 && unfilteredNodeIndex < order.count() ? order[unfilteredNodeIndex] : -1 );
75 , mMapCanvas( mapCanvas )
80 connect( mWrapCharLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
81 connect( mTitleLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
86 connect( mColumnCountSpinBox,
static_cast < void ( QSpinBox::* )(
int )
> ( &QSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
87 connect( mSplitLayerCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
88 connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
89 connect( mSymbolWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged );
90 connect( mSymbolHeightSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged );
91 connect( mMaxSymbolSizeSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged );
92 connect( mMinSymbolSizeSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged );
93 connect( mWmsLegendWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
94 connect( mWmsLegendHeightSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
95 connect( mTitleSpaceBottomSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
96 connect( mGroupSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
97 connect( mGroupIndentSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged );
98 connect( mSubgroupIndentSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged );
99 connect( mSpaceBelowGroupHeadingSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
100 connect( mGroupSideSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
101 connect( mLayerSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
102 connect( mSpaceBelowSubgroupHeadingSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
103 connect( mSubgroupSideSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
104 connect( mSymbolSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
105 connect( mSymbolSideSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
106 connect( mIconLabelSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
107 connect( mBoxSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
108 connect( mColumnSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged );
109 connect( mCheckBoxAutoUpdate, &QCheckBox::stateChanged,
this, [ = ](
int state ) { mCheckBoxAutoUpdate_stateChanged( state ); } );
110 connect( mCheckboxResizeContents, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mCheckboxResizeContents_toggled );
111 connect( mRasterStrokeGroupBox, &QgsCollapsibleGroupBoxBasic::toggled,
this, &QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled );
112 connect( mRasterStrokeWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged );
113 connect( mRasterStrokeColorButton, &
QgsColorButton::colorChanged,
this, &QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged );
114 connect( mExpandAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::expandLegendTree );
115 connect( mCollapseAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::collapseLegendTree );
116 connect( mMoveDownToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveDownToolButton_clicked );
117 connect( mMoveUpToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveUpToolButton_clicked );
118 connect( mRemoveToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mRemoveToolButton_clicked );
119 connect( mAddToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddToolButton_clicked );
120 connect( mEditPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mEditPushButton_clicked );
121 connect( mCountToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mCountToolButton_clicked );
122 connect( mExpressionFilterButton, &QgsLegendFilterButton::toggled,
this, &QgsLayoutLegendWidget::mExpressionFilterButton_toggled );
123 connect( mLayerExpressionButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mLayerExpressionButton_clicked );
124 connect( mFilterByMapCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled );
125 connect( mUpdateAllPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mUpdateAllPushButton_clicked );
126 connect( mAddGroupToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddGroupToolButton_clicked );
127 connect( mFilterLegendByAtlasCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled );
128 connect( mItemTreeView, &QgsLayerTreeView::doubleClicked,
this, &QgsLayoutLegendWidget::mItemTreeView_doubleClicked );
130 connect( mFilterByMapCheckBox, &QCheckBox::toggled, mButtonLinkedMaps, &QWidget::setEnabled );
131 mButtonLinkedMaps->setEnabled(
false );
132 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,
234 this, &QgsLayoutLegendWidget::selectedChanged );
243 if ( mItemPropertiesWidget )
244 mItemPropertiesWidget->setMasterLayout( masterLayout );
250 mTitleFontButton->setMessageBar( iface->
messageBar() );
251 mGroupFontButton->setMessageBar( iface->
messageBar() );
252 mLayerFontButton->setMessageBar( iface->
messageBar() );
253 mItemFontButton->setMessageBar( iface->
messageBar() );
256void QgsLayoutLegendWidget::setGuiElements()
263 blockAllSignals(
true );
264 mTitleLineEdit->setText( mLegend->title() );
265 whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
269 whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
270 mFilterByMapCheckBox->setChecked( mLegend->legendFilterByMapEnabled() );
271 mButtonLinkedMaps->setEnabled( mLegend->legendFilterByMapEnabled() );
272 mColumnCountSpinBox->setValue( mLegend->columnCount() );
273 mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
274 mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
275 mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
276 mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
277 mMaxSymbolSizeSpinBox->setValue( mLegend->maximumSymbolSize() );
278 mMinSymbolSizeSpinBox->setValue( mLegend->minimumSymbolSize() );
279 mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
280 mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
294 mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
295 mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
297 mRasterStrokeGroupBox->setChecked( mLegend->drawRasterStroke() );
298 mRasterStrokeWidthSpinBox->setValue( mLegend->rasterStrokeWidth() );
299 mRasterStrokeColorButton->setColor( mLegend->rasterStrokeColor() );
301 mCheckBoxAutoUpdate->setChecked( mLegend->autoUpdateModel() );
303 mCheckboxResizeContents->setChecked( mLegend->resizeToContents() );
304 mFilterLegendByAtlasCheckBox->setChecked( mLegend->legendFilterOutAtlas() );
305 mWrapCharLineEdit->setText( mLegend->wrapString() );
308 mMapComboBox->setItem( map );
314 blockAllSignals(
false );
316 mCheckBoxAutoUpdate_stateChanged( mLegend->autoUpdateModel() ? Qt::Checked : Qt::Unchecked, false );
317 updateDataDefinedButton( mLegendTitleDDBtn );
318 updateDataDefinedButton( mColumnsDDBtn );
321void QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged(
const QString &text )
325 mLegend->beginCommand( tr(
"Change Legend Wrap" ) );
326 mLegend->setWrapString( text );
327 mLegend->adjustBoxSize();
329 mLegend->endCommand();
333void QgsLayoutLegendWidget::mTitleLineEdit_textChanged(
const QString &text )
338 mLegend->setTitle( text );
339 mLegend->adjustBoxSize();
341 mLegend->endCommand();
345void QgsLayoutLegendWidget::titleAlignmentChanged()
349 Qt::AlignmentFlag alignment =
static_cast< Qt::AlignmentFlag
>(
static_cast< int >( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
350 mLegend->beginCommand( tr(
"Change Title Alignment" ) );
351 mLegend->setTitleAlignment( alignment );
353 mLegend->endCommand();
357void QgsLayoutLegendWidget::groupAlignmentChanged()
361 mLegend->beginCommand( tr(
"Change Group Alignment" ) );
364 mLegend->endCommand();
368void QgsLayoutLegendWidget::subgroupAlignmentChanged()
372 mLegend->beginCommand( tr(
"Change Subgroup Alignment" ) );
375 mLegend->endCommand();
379void QgsLayoutLegendWidget::itemAlignmentChanged()
383 mLegend->beginCommand( tr(
"Change Item Alignment" ) );
386 mLegend->endCommand();
390void QgsLayoutLegendWidget::arrangementChanged()
394 Qt::AlignmentFlag alignment =
static_cast< Qt::AlignmentFlag
>(
static_cast< int >( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
395 mLegend->beginCommand( tr(
"Change Legend Arrangement" ) );
396 mLegend->setSymbolAlignment( alignment );
398 mLegend->endCommand();
402void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged(
int c )
407 mLegend->setColumnCount(
c );
408 mLegend->adjustBoxSize();
410 mLegend->endCommand();
412 mSplitLayerCheckBox->setEnabled(
c > 1 );
413 mEqualColumnWidthCheckBox->setEnabled(
c > 1 );
416void QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled(
bool checked )
420 mLegend->beginCommand( tr(
"Split Legend Layers" ) );
421 mLegend->setSplitLayer( checked );
422 mLegend->adjustBoxSize();
424 mLegend->endCommand();
428void QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled(
bool checked )
432 mLegend->beginCommand( tr(
"Legend Column Width" ) );
433 mLegend->setEqualColumnWidth( checked );
434 mLegend->adjustBoxSize();
436 mLegend->endCommand();
440void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged(
double d )
445 mLegend->setSymbolWidth( d );
446 mLegend->adjustBoxSize();
448 mLegend->endCommand();
452void QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged(
double d )
457 mLegend->setMaximumSymbolSize( d );
458 mLegend->adjustBoxSize();
460 mLegend->endCommand();
464void QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged(
double d )
469 mLegend->setMinimumSymbolSize( d );
470 mLegend->adjustBoxSize();
472 mLegend->endCommand();
476void QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged(
double d )
481 mLegend->setSymbolHeight( d );
482 mLegend->adjustBoxSize();
484 mLegend->endCommand();
488void QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged(
double d )
493 mLegend->setWmsLegendWidth( d );
494 mLegend->adjustBoxSize();
496 mLegend->endCommand();
500void QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged(
double d )
505 mLegend->setWmsLegendHeight( d );
506 mLegend->adjustBoxSize();
508 mLegend->endCommand();
512void QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged(
double d )
518 mLegend->adjustBoxSize();
520 mLegend->endCommand();
524void QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged(
double d )
530 mLegend->adjustBoxSize();
532 mLegend->endCommand();
536void QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged(
double d )
542 mLegend->adjustBoxSize();
544 mLegend->endCommand();
548void QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged(
double d )
554 mLegend->adjustBoxSize();
556 mLegend->endCommand();
560void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged(
double space )
566 mLegend->adjustBoxSize();
568 mLegend->endCommand();
572void QgsLayoutLegendWidget::spaceGroupSideChanged(
double space )
578 mLegend->adjustBoxSize();
580 mLegend->endCommand();
584void QgsLayoutLegendWidget::spaceSubGroupSideChanged(
double space )
590 mLegend->adjustBoxSize();
592 mLegend->endCommand();
596void QgsLayoutLegendWidget::spaceSymbolSideChanged(
double space )
602 mLegend->adjustBoxSize();
604 mLegend->endCommand();
608void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged(
double d )
614 mLegend->adjustBoxSize();
616 mLegend->endCommand();
620void QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged(
double d )
628 mLegend->adjustBoxSize();
630 mLegend->endCommand();
634void QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged(
double d )
640 mLegend->adjustBoxSize();
642 mLegend->endCommand();
646void QgsLayoutLegendWidget::titleFontChanged()
652 mLegend->adjustBoxSize();
654 mLegend->endCommand();
658void QgsLayoutLegendWidget::groupFontChanged()
664 mLegend->adjustBoxSize();
666 mLegend->endCommand();
670void QgsLayoutLegendWidget::layerFontChanged()
676 mLegend->adjustBoxSize();
678 mLegend->endCommand();
682void QgsLayoutLegendWidget::itemFontChanged()
688 mLegend->adjustBoxSize();
690 mLegend->endCommand();
694void QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged(
double space )
700 mLegend->adjustBoxSize();
702 mLegend->endCommand();
706void QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged(
double d )
711 mLegend->setBoxSpace( d );
712 mLegend->adjustBoxSize();
714 mLegend->endCommand();
718void QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged(
double d )
723 mLegend->setColumnSpace( d );
724 mLegend->adjustBoxSize();
726 mLegend->endCommand();
730static void _moveLegendNode(
QgsLayerTreeLayer *nodeLayer,
int legendNodeIndex,
int offset )
734 if ( legendNodeIndex < 0 || legendNodeIndex >= order.count() )
736 if ( legendNodeIndex + offset < 0 || legendNodeIndex + offset >= order.count() )
739 int id = order.takeAt( legendNodeIndex );
740 order.insert( legendNodeIndex + offset,
id );
746void QgsLayoutLegendWidget::mMoveDownToolButton_clicked()
753 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
754 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
755 const QModelIndex parentIndex = sourceIndex.parent();
756 if ( !sourceIndex.isValid() || sourceIndex.row() == mItemTreeView->layerTreeModel()->rowCount( parentIndex ) - 1 )
761 if ( !node && !legendNode )
764 mLegend->beginCommand( tr(
"Moved Legend Item Down" ) );
778 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() + 1, 0, parentIndex ) ) );
781 mLegend->endCommand();
784void QgsLayoutLegendWidget::mMoveUpToolButton_clicked()
791 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
792 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
793 const QModelIndex parentIndex = sourceIndex.parent();
794 if ( !sourceIndex.isValid() || sourceIndex.row() == 0 )
799 if ( !node && !legendNode )
802 mLegend->beginCommand( tr(
"Move Legend Item Up" ) );
816 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() - 1, 0, parentIndex ) ) );
819 mLegend->endCommand();
822void QgsLayoutLegendWidget::expandLegendTree()
824 mItemTreeView -> expandAll();
827void QgsLayoutLegendWidget::collapseLegendTree()
829 mItemTreeView -> collapseAll();
832void QgsLayoutLegendWidget::mCheckBoxAutoUpdate_stateChanged(
int state,
bool userTriggered )
836 mLegend->beginCommand( tr(
"Change Auto Update" ) );
838 mLegend->setAutoUpdateModel( state == Qt::Checked );
840 mLegend->endCommand();
844 QList<QWidget *> widgets;
845 widgets << mMoveDownToolButton << mMoveUpToolButton << mRemoveToolButton << mAddToolButton
846 << mEditPushButton << mCountToolButton << mUpdateAllPushButton << mAddGroupToolButton
847 << mExpressionFilterButton << mCollapseAllToolButton << mExpandAllToolButton;
848 for ( QWidget *w : std::as_const( widgets ) )
849 w->setEnabled( state != Qt::Checked );
851 if ( state == Qt::Unchecked )
854 selectedChanged( QModelIndex(), QModelIndex() );
858void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
874 mLegend->beginCommand( tr(
"Change Legend Map" ) );
875 mLegend->setLinkedMap( map );
877 mLegend->endCommand();
879 setLegendMapViewData();
883void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
890 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
891 mLegend->setResizeToContents( checked );
893 mLegend->adjustBoxSize();
895 mLegend->endCommand();
898void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
905 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
906 mLegend->setDrawRasterStroke( state );
907 mLegend->adjustBoxSize();
909 mLegend->endCommand();
912void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
920 mLegend->setRasterStrokeWidth( d );
921 mLegend->adjustBoxSize();
923 mLegend->endCommand();
926void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
934 mLegend->setRasterStrokeColor( newColor );
936 mLegend->endCommand();
939void QgsLayoutLegendWidget::mAddToolButton_clicked()
946 QList< QgsMapLayer * > visibleLayers;
947 if ( mLegend->linkedMap() )
949 visibleLayers = mLegend->linkedMap()->layersToRender();
951 if ( visibleLayers.isEmpty() )
954 visibleLayers = mMapCanvas->layers(
true );
958 addDialog.setVisibleLayers( visibleLayers );
959 if ( addDialog.exec() == QDialog::Accepted )
961 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
962 if ( !layers.empty() )
964 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
967 mLegend->model()->rootGroup()->addLayer( layer );
969 mLegend->updateLegend();
971 mLegend->endCommand();
976void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
983 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
984 if ( !selectionModel )
989 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
991 QList<QPersistentModelIndex> proxyIndexes;
992 const QModelIndexList viewSelection = selectionModel->selectedIndexes();
993 for (
const QModelIndex &index : viewSelection )
994 proxyIndexes << index;
997 QHash<QgsLayerTreeLayer *, QList<int> > nodesWithRemoval;
998 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1003 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex( legendNode ) );
1006 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
1008 QList<int> toDelete = it.value();
1009 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
1012 for (
int i : std::as_const( toDelete ) )
1014 if ( i >= 0 && i < order.count() )
1015 order.removeAt( i );
1019 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
1023 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1025 if ( proxyIndex.isValid() && mItemTreeView->index2node( proxyIndex ) )
1027 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( proxyIndex );
1028 mLegend->model()->removeRow( sourceIndex.row(), sourceIndex.parent() );
1032 mLegend->updateLegend();
1034 mLegend->endCommand();
1037void QgsLayoutLegendWidget::mEditPushButton_clicked()
1044 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
1045 mItemTreeView_doubleClicked( idx );
1048void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
1056 QModelIndex currentIndex = mItemTreeView->currentIndex();
1057 if ( !currentIndex.isValid() )
1076 mLegend->beginCommand( tr(
"Update Legend" ) );
1079 for (
const QString &key : constCustomProperties )
1081 if ( key.startsWith( QLatin1String(
"legend/" ) ) )
1088 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1090 mLegend->updateLegend();
1092 mLegend->endCommand();
1095void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1102 const QList< QModelIndex > selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1103 if ( selectedIndexes.empty() )
1106 mLegend->beginCommand( tr(
"Update Legend" ) );
1107 for (
const QModelIndex &index : selectedIndexes )
1113 currentNode->
setCustomProperty( QStringLiteral(
"showFeatureCount" ), checked ? 1 : 0 );
1115 mLegend->updateFilterByMap();
1116 mLegend->adjustBoxSize();
1117 mLegend->endCommand();
1120void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1122 mLegend->beginCommand( tr(
"Update Legend" ) );
1123 mLegend->setLegendFilterByMapEnabled( checked );
1124 mLegend->adjustBoxSize();
1126 mLegend->endCommand();
1129void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1137 QModelIndex currentIndex = mItemTreeView->currentIndex();
1138 if ( !currentIndex.isValid() )
1148 mExpressionFilterButton->expressionText(),
1151 mLegend->beginCommand( tr(
"Update Legend" ) );
1152 mLegend->updateFilterByMap();
1153 mLegend->adjustBoxSize();
1154 mLegend->endCommand();
1157void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1164 QModelIndex currentIndex = mItemTreeView->currentIndex();
1165 if ( !currentIndex.isValid() )
1172 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1178 QString currentExpression;
1180 currentExpression = QStringLiteral(
"@symbol_label" );
1186 QStringList highlighted;
1189 const QList<QgsLayerTreeModelLegendNode *> legendNodes = model->layerLegendNodes( layerNode,
false );
1190 if ( !legendNodes.isEmpty() )
1192 if (
QgsSymbolLegendNode *symbolNode = qobject_cast<QgsSymbolLegendNode *>( legendNodes.first() ) )
1194 legendContext.
appendScope( symbolNode->createSymbolScope() );
1195 highlighted << QStringLiteral(
"symbol_label" ) << QStringLiteral(
"symbol_id" ) << QStringLiteral(
"symbol_count" );
1208 QgsExpressionBuilderDialog expressiondialog(
nullptr, currentExpression,
nullptr, QStringLiteral(
"generic" ), legendContext );
1209 if ( expressiondialog.exec() )
1212 mItemTreeView->layerTreeModel()->refreshLayerLegend( layerNode );
1215 mLegend->beginCommand( tr(
"Update Legend" ) );
1217 mLegend->adjustBoxSize();
1218 mLegend->endCommand();
1221void QgsLayoutLegendWidget::mUpdateAllPushButton_clicked()
1226void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1230 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1231 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1232 mLegend->updateLegend();
1234 mLegend->endCommand();
1238void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1243 mLegend->setLegendFilterOutAtlas( toggled );
1249void QgsLayoutLegendWidget::updateLegend()
1253 mLegend->beginCommand( tr(
"Update Legend" ) );
1256 mLegend->setAutoUpdateModel(
true );
1257 mLegend->setAutoUpdateModel(
false );
1259 mLegend->endCommand();
1263void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1265 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1266 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1275bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1285 mLegend = qobject_cast< QgsLayoutItemLegend * >( item );
1286 mItemPropertiesWidget->setItem( mLegend );
1288 if ( mMapFilteringWidget )
1289 mMapFilteringWidget->setItem( mLegend );
1293 mItemTreeView->setModel( mLegend->model() );
1302void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1304 mTitleLineEdit->blockSignals( b );
1305 mTitleAlignCombo->blockSignals( b );
1306 mItemTreeView->blockSignals( b );
1307 mCheckBoxAutoUpdate->blockSignals( b );
1308 mMapComboBox->blockSignals( b );
1309 mFilterByMapCheckBox->blockSignals( b );
1310 mColumnCountSpinBox->blockSignals( b );
1311 mSplitLayerCheckBox->blockSignals( b );
1312 mEqualColumnWidthCheckBox->blockSignals( b );
1313 mSymbolWidthSpinBox->blockSignals( b );
1314 mSymbolHeightSpinBox->blockSignals( b );
1315 mMaxSymbolSizeSpinBox->blockSignals( b );
1316 mMinSymbolSizeSpinBox->blockSignals( b );
1317 mGroupSpaceSpinBox->blockSignals( b );
1318 mGroupIndentSpinBox->blockSignals( b );
1319 mSubgroupIndentSpinBox->blockSignals( b );
1320 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1321 mGroupSideSpinBox->blockSignals( b );
1322 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1323 mSubgroupSideSpinBox->blockSignals( b );
1324 mLayerSpaceSpinBox->blockSignals( b );
1325 mSymbolSpaceSpinBox->blockSignals( b );
1326 mSymbolSideSpaceSpinBox->blockSignals( b );
1327 mIconLabelSpaceSpinBox->blockSignals( b );
1328 mBoxSpaceSpinBox->blockSignals( b );
1329 mColumnSpaceSpinBox->blockSignals( b );
1330 mRasterStrokeGroupBox->blockSignals( b );
1331 mRasterStrokeColorButton->blockSignals( b );
1332 mRasterStrokeWidthSpinBox->blockSignals( b );
1333 mWmsLegendWidthSpinBox->blockSignals( b );
1334 mWmsLegendHeightSpinBox->blockSignals( b );
1335 mCheckboxResizeContents->blockSignals( b );
1336 mTitleSpaceBottomSpinBox->blockSignals( b );
1337 mFilterLegendByAtlasCheckBox->blockSignals( b );
1338 mTitleFontButton->blockSignals( b );
1339 mGroupFontButton->blockSignals( b );
1340 mLayerFontButton->blockSignals( b );
1341 mItemFontButton->blockSignals( b );
1342 mWrapCharLineEdit->blockSignals( b );
1345void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1348 Q_UNUSED( previous )
1350 mLayerExpressionButton->setEnabled(
false );
1352 if ( mLegend && mLegend->autoUpdateModel() )
1363 mLayerExpressionButton->setEnabled(
true );
1367 mCountToolButton->setChecked(
false );
1368 mCountToolButton->setEnabled(
false );
1371 mExpressionFilterButton->blockSignals(
true );
1372 mExpressionFilterButton->setChecked(
false );
1373 mExpressionFilterButton->setEnabled(
false );
1374 mExpressionFilterButton->blockSignals(
false );
1385 mCountToolButton->setChecked( currentNode->
customProperty( QStringLiteral(
"showFeatureCount" ), 0 ).toInt() );
1386 mCountToolButton->setEnabled(
true );
1387 mLayerExpressionButton->setEnabled(
true );
1391 mExpressionFilterButton->blockSignals(
true );
1392 mExpressionFilterButton->setExpressionText( expr );
1393 mExpressionFilterButton->setVectorLayer( vl );
1394 mExpressionFilterButton->setEnabled(
true );
1395 mExpressionFilterButton->setChecked( exprEnabled );
1396 mExpressionFilterButton->blockSignals(
false );
1399void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1401 QAction *a = qobject_cast<QAction *>( sender() );
1402 if ( !a || !mItemTreeView->currentNode() )
1409void QgsLayoutLegendWidget::setLegendMapViewData()
1411 if ( mLegend->linkedMap() )
1415 measurementConverter.
setDpi( dpi );
1418 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1419 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1420 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1424void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1428 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
Qgis::GeometryType::Polygon );
1432void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1434 if ( !mLegend || !idx.isValid() )
1439 if ( mLegend->autoUpdateModel() )
1445 int originalIndex = -1;
1448 originalIndex = _originalLegendNodeIndex( legendNode );
1452 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode, legendNode, originalIndex );
1453 openPanel( widget );
1461QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1466QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1468 if ( !mView->currentNode() )
1471 if ( mWidget->legend()->autoUpdateModel() )
1474 QMenu *menu =
new QMenu();
1478 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1479 menu->addSeparator();
1484 QActionGroup *styleGroup =
new QActionGroup{ mWidget };
1485 styleGroup->setExclusive(
true );
1487 QList<QgsLegendStyle::Style> lst;
1491 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1492 action->setActionGroup( styleGroup );
1493 action->setCheckable(
true );
1494 action->setChecked( currentStyle == style );
1495 action->setData(
static_cast< int >( style ) );
1510 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1513 setPanelTitle( tr(
"Legend Item Properties" ) );
1522 QString currentLabel;
1525 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1526 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1530 currentLabel = mLayer->name();
1531 QVariant v = mLayer->customProperty( QStringLiteral(
"legend/title-label" ) );
1533 currentLabel = v.toString();
1534 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1536 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1541 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1544 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1545 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1546 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1547 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1548 mPatchGroup->setVisible( mLegendNode || mLayer );
1549 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1550 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1551 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1552 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1553 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1556 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1557 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1561 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1562 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1565 mCustomSymbolCheckBox->setChecked(
false );
1570 patchShape = symbolLegendNode->patchShape();
1572 std::unique_ptr< QgsSymbol > customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() : nullptr );
1573 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1576 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1578 mCustomSymbolButton->setSymbol( customSymbol.release() );
1580 else if ( symbolLegendNode->symbol() )
1582 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1583 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1584 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1587 else if ( !mLegendNode && mLayer )
1589 patchShape = mLayer->patchShape();
1592 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1594 mCustomSymbolCheckBox->setChecked(
true );
1595 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1597 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1601 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1602 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1603 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1610 switch ( qobject_cast< QgsVectorLayer * >( mLayer->layer() )->geometryType() )
1625 mPatchShapeLabel->hide();
1626 mPatchShapeButton->hide();
1629 if ( !patchShape.
isNull() )
1630 mPatchShapeButton->setShape( patchShape );
1635 if ( symbolLegendNode->symbol() )
1637 mPatchShapeButton->setSymbolType( symbolLegendNode->symbol()->type() );
1641 mPatchShapeLabel->hide();
1642 mPatchShapeButton->hide();
1647 mPatchShapeLabel->hide();
1648 mPatchShapeButton->hide();
1653 mLabelGroup->hide();
1654 mColorRampLegendWidget->setSettings( colorRampNode->settings() );
1658 mColorRampLegendWidget->hide();
1671 mCustomSymbolCheckBox->hide();
1680 mLabelEdit->setPlainText( currentLabel );
1681 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1683 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1685 connect( mWidthSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1686 connect( mHeightSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1688 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1691 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1693 connect( mColumnSplitBehaviorComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1697 connectChildPanel( mColorRampLegendWidget );
1700void QgsLayoutLegendNodeWidget::setDockMode(
bool dockMode )
1702 mColorRampLegendWidget->setDockMode( dockMode );
1706void QgsLayoutLegendNodeWidget::labelChanged()
1710 const QString label = mLabelEdit->toPlainText();
1715 else if ( mLegendNode )
1718 mLegend->model()->refreshLayerLegend( mLayer );
1722 mLayer->setCustomProperty( QStringLiteral(
"legend/title-label" ), label );
1726 embeddedNode->setUserLabel( QString() );
1729 mLegend->adjustBoxSize();
1730 mLegend->invalidateCache();
1732 mLegend->endCommand();
1735void QgsLayoutLegendNodeWidget::patchChanged()
1737 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1743 mLegend->model()->refreshLayerLegend( mLayer );
1747 mLayer->setPatchShape( shape );
1748 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1753 mLegend->model()->refreshLayerLegend( mLayer );
1756 mLegend->adjustBoxSize();
1758 mLegend->endCommand();
1761void QgsLayoutLegendNodeWidget::insertExpression()
1769 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1773 if ( mLayer && mLayer->layer() )
1779 << QStringLiteral(
"legend_column_count" )
1780 << QStringLiteral(
"legend_split_layers" )
1781 << QStringLiteral(
"legend_wrap_string" )
1782 << QStringLiteral(
"legend_filter_by_map" )
1783 << QStringLiteral(
"legend_filter_out_atlas" ) );
1787 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1788 if ( exprDlg.exec() == QDialog::Accepted )
1790 expression = exprDlg.expressionText();
1791 if ( !expression.isEmpty() )
1793 mLegend->beginCommand( tr(
"Insert expression" ) );
1794 mLabelEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
1795 mLegend->endCommand();
1800void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1802 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1803 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1808 mLegend->model()->refreshLayerLegend( mLayer );
1812 mLayer->setPatchSize( size );
1813 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1818 mLegend->model()->refreshLayerLegend( mLayer );
1821 mLegend->adjustBoxSize();
1823 mLegend->endCommand();
1826void QgsLayoutLegendNodeWidget::customSymbolChanged()
1828 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1830 if ( mCustomSymbolCheckBox->isChecked() )
1835 mLegend->model()->refreshLayerLegend( mLayer );
1839 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1844 mLegend->model()->refreshLayerLegend( mLayer );
1852 mLegend->model()->refreshLayerLegend( mLayer );
1856 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1861 mLegend->model()->refreshLayerLegend( mLayer );
1865 mLegend->adjustBoxSize();
1867 mLegend->endCommand();
1870void QgsLayoutLegendNodeWidget::colorRampLegendChanged()
1872 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1876 mLegend->model()->refreshLayerLegend( mLayer );
1878 mLegend->adjustBoxSize();
1880 mLegend->endCommand();
1883void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1885 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1890 mLegend->model()->refreshLayerLegend( mLayer );
1894 mLayer->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1898 mNode->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1901 mLegend->adjustBoxSize();
1903 mLegend->endCommand();
1906void QgsLayoutLegendNodeWidget::columnSplitChanged()
1908 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1910 if ( mLayer && !mLegendNode )
1915 mLegend->adjustBoxSize();
1917 mLegend->endCommand();
1924QgsLayoutLegendMapFilteringWidget::QgsLayoutLegendMapFilteringWidget(
QgsLayoutItemLegend *legend )
1926 , mLegendItem( legend )
1929 setPanelTitle( tr(
"Legend Filtering" ) );
1931 setNewItem( legend );
1934bool QgsLayoutLegendMapFilteringWidget::setNewItem(
QgsLayoutItem *item )
1944 mLegendItem = qobject_cast< QgsLayoutItemLegend * >( item );
1951 updateGuiElements();
1956void QgsLayoutLegendMapFilteringWidget::updateGuiElements()
1958 if ( mBlockUpdates )
1961 mBlockUpdates =
true;
1963 if ( mFilterMapItemsListView->model() )
1965 QAbstractItemModel *oldModel = mFilterMapItemsListView->model();
1966 mFilterMapItemsListView->setModel(
nullptr );
1967 oldModel->deleteLater();
1970 QgsLayoutLegendMapFilteringModel *model =
new QgsLayoutLegendMapFilteringModel( mLegendItem, mLegendItem->layout()->itemsModel(), mFilterMapItemsListView );
1971 mFilterMapItemsListView->setModel( model );
1973 mBlockUpdates =
false;
1981 : QSortFilterProxyModel( parent )
1982 , mLayoutModel( layoutModel )
1983 , mLegendItem( legend )
1985 setSourceModel( layoutModel );
1988int QgsLayoutLegendMapFilteringModel::columnCount(
const QModelIndex & )
const
1993QVariant QgsLayoutLegendMapFilteringModel::data(
const QModelIndex &i,
int role )
const
1998 if ( i.column() != 0 )
2003 QgsLayoutItemMap *mapItem = qobject_cast< QgsLayoutItemMap * >( mLayoutModel->itemFromIndex( mapToSource( i ) ) );
2011 case Qt::CheckStateRole:
2012 switch ( i.column() )
2017 return Qt::Unchecked;
2019 return mLegendItem->filterByMapItems().contains( mapItem ) ? Qt::Checked : Qt::Unchecked;
2027 return mLayoutModel->data( sourceIndex, role );
2031bool QgsLayoutLegendMapFilteringModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
2035 if ( !index.isValid() )
2038 QgsLayoutItemMap *mapItem = qobject_cast< QgsLayoutItemMap * >( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2039 if ( !mapItem || !mLegendItem )
2044 mLegendItem->layout()->undoStack()->beginCommand( mLegendItem, tr(
"Change Legend Linked Maps" ) );
2046 QList< QgsLayoutItemMap * > linkedMaps = mLegendItem->filterByMapItems();
2047 if ( value.toBool() )
2049 if ( !linkedMaps.contains( mapItem ) )
2051 linkedMaps.append( mapItem );
2052 mLegendItem->setFilterByMapItems( linkedMaps );
2057 linkedMaps.removeAll( mapItem );
2058 mLegendItem->setFilterByMapItems( linkedMaps );
2060 emit dataChanged( index, index, QVector<int>() << role );
2062 mLegendItem->layout()->undoStack()->endCommand();
2063 mLegendItem->invalidateCache();
2068Qt::ItemFlags QgsLayoutLegendMapFilteringModel::flags(
const QModelIndex &index )
const
2070 Qt::ItemFlags flags = QSortFilterProxyModel::flags( index );
2072 if ( ! index.isValid() )
2077 QgsLayoutItemMap *mapItem = qobject_cast< QgsLayoutItemMap * >( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2078 const bool isMainLinkedMapItem = mLegendItem ? ( mLegendItem->linkedMap() == mapItem ) : false;
2084 if ( !isMainLinkedMapItem )
2086 flags |= Qt::ItemIsEnabled;
2090 flags &= ~Qt::ItemIsEnabled;
2093 switch ( index.column() )
2096 if ( !isMainLinkedMapItem )
2097 return flags | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
2099 return flags | Qt::ItemIsSelectable;
2102 return flags | Qt::ItemIsSelectable;
2106bool QgsLayoutLegendMapFilteringModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
2108 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 (since QGIS 3.18)
@ 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)
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.