47#include <QActionGroup>
48#include <QInputDialog>
52#include "moc_qgslayoutlegendwidget.cpp"
69 int unfilteredNodeIndex = _unfilteredLegendNodeIndex( legendNode );
71 return ( unfilteredNodeIndex >= 0 && unfilteredNodeIndex < order.count() ? order[unfilteredNodeIndex] : -1 );
74 void _moveLegendNode(
QgsLayerTreeLayer *nodeLayer,
int legendNodeIndex,
int destLegendNodeIndex )
77 const int offset = destLegendNodeIndex - legendNodeIndex;
79 if ( legendNodeIndex < 0 || legendNodeIndex >= order.count() )
81 if ( legendNodeIndex + offset < 0 || legendNodeIndex + offset >= order.count() )
84 int id = order.takeAt( legendNodeIndex );
85 order.insert( legendNodeIndex + offset,
id );
94 , mMapCanvas( mapCanvas )
99 connect( mWrapCharLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
100 connect( mTitleLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
105 connect( mColumnCountSpinBox,
static_cast<void ( QSpinBox::* )(
int )
>( &QSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
106 connect( mSplitLayerCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
107 connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
108 connect( mSymbolWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged );
109 connect( mSymbolHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged );
110 connect( mMaxSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged );
111 connect( mMinSymbolSizeSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged );
112 connect( mWmsLegendWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
113 connect( mWmsLegendHeightSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
114 connect( mTitleSpaceBottomSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
115 connect( mGroupSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
116 connect( mGroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged );
117 connect( mSubgroupIndentSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged );
118 connect( mSpaceBelowGroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
119 connect( mGroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
120 connect( mLayerSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
121 connect( mSpaceBelowSubgroupHeadingSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
122 connect( mSubgroupSideSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
123 connect( mSymbolSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
124 connect( mSymbolSideSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
125 connect( mIconLabelSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
126 connect( mBoxSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
127 connect( mColumnSpaceSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged );
128 connect( mMaxWidthSpinBox, qOverload< double >( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::maxWidthChanged );
129 connect( mCheckBoxAutoUpdate, &QCheckBox::stateChanged,
this, [
this](
int state ) { mCheckBoxAutoUpdate_stateChanged( state ); } );
130 connect( mCheckboxResizeContents, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mCheckboxResizeContents_toggled );
131 connect( mRasterStrokeGroupBox, &QgsCollapsibleGroupBoxBasic::toggled,
this, &QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled );
132 connect( mRasterStrokeWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged );
133 connect( mRasterStrokeColorButton, &
QgsColorButton::colorChanged,
this, &QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged );
134 connect( mExpandAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::expandLegendTree );
135 connect( mCollapseAllToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::collapseLegendTree );
136 connect( mMoveDownToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveDownToolButton_clicked );
137 connect( mMoveUpToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveUpToolButton_clicked );
138 connect( mRemoveToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mRemoveToolButton_clicked );
139 connect( mAddToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddToolButton_clicked );
140 connect( mEditPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mEditPushButton_clicked );
141 connect( mCountToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mCountToolButton_clicked );
142 connect( mExpressionFilterButton, &QgsLegendFilterButton::toggled,
this, &QgsLayoutLegendWidget::mExpressionFilterButton_toggled );
143 connect( mLayerExpressionButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mLayerExpressionButton_clicked );
144 connect( mFilterByMapCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled );
145 connect( mUpdateAllPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mUpdateAllPushButton_clicked );
146 connect( mAddGroupToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddGroupToolButton_clicked );
147 connect( mFilterLegendByAtlasCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled );
148 connect( mItemTreeView, &QgsLayerTreeView::doubleClicked,
this, &QgsLayoutLegendWidget::mItemTreeView_doubleClicked );
150 connect( mFilterByMapCheckBox, &QCheckBox::toggled, mButtonLinkedMaps, &QWidget::setEnabled );
151 mButtonLinkedMaps->setEnabled(
false );
152 connect( mButtonLinkedMaps, &QToolButton::clicked,
this, [
this] {
155 mMapFilteringWidget =
new QgsLayoutLegendMapFilteringWidget( mLegend );
156 openPanel( mMapFilteringWidget );
160 setPanelTitle( tr(
"Legend Properties" ) );
167 mTitleAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
168 mGroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
169 mSubgroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
170 mItemAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
172 mArrangementCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignRight );
174 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignLeft, tr(
"Symbols on Left" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsLeft.svg" ) ) );
175 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignRight, tr(
"Symbols on Right" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsRight.svg" ) ) );
177 mSpaceBelowGroupHeadingSpinBox->setClearValue( 0 );
178 mGroupSideSpinBox->setClearValue( 0 );
179 mSpaceBelowSubgroupHeadingSpinBox->setClearValue( 0 );
180 mSubgroupSideSpinBox->setClearValue( 0 );
181 mSymbolSideSpaceSpinBox->setClearValue( 0 );
183 mMaxWidthSpinBox->setShowClearButton(
true );
184 mMaxWidthSpinBox->setClearValue( 0, tr(
"Disabled" ) );
209 mRasterStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
210 mRasterStrokeColorButton->setAllowOpacity(
true );
211 mRasterStrokeColorButton->setContext( QStringLiteral(
"composer " ) );
213 mMapComboBox->setCurrentLayout( legend->
layout() );
219 mainLayout->addWidget( mItemPropertiesWidget );
221 mItemTreeView->setHeaderHidden(
true );
223 mLegendProxyModel =
new QgsLegendLayerTreeProxyModel( legend,
this );
225 mItemTreeView->setModel( legend->
model(), mLegendProxyModel );
226 mItemTreeView->setMenuProvider(
new QgsLayoutLegendMenuProvider( mItemTreeView,
this ) );
227 setLegendMapViewData();
233 connect( layoutAtlas(), &
QgsLayoutAtlas::toggled,
this, &QgsLayoutLegendWidget::updateFilterLegendByAtlasButton );
237 mTitleFontButton->registerExpressionContextGenerator(
this );
238 mGroupFontButton->registerExpressionContextGenerator(
this );
239 mLayerFontButton->registerExpressionContextGenerator(
this );
240 mItemFontButton->registerExpressionContextGenerator(
this );
241 mExpressionFilterButton->registerExpressionContextGenerator(
this );
243 mTitleFontButton->setLayer( coverageLayer() );
244 mGroupFontButton->setLayer( coverageLayer() );
245 mLayerFontButton->setLayer( coverageLayer() );
246 mItemFontButton->setLayer( coverageLayer() );
247 if ( mLegend->layout() )
261 connect( mItemTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsLayoutLegendWidget::selectedChanged );
270 if ( mItemPropertiesWidget )
271 mItemPropertiesWidget->setMasterLayout( masterLayout );
277 mTitleFontButton->setMessageBar( iface->
messageBar() );
278 mGroupFontButton->setMessageBar( iface->
messageBar() );
279 mLayerFontButton->setMessageBar( iface->
messageBar() );
280 mItemFontButton->setMessageBar( iface->
messageBar() );
283void QgsLayoutLegendWidget::setGuiElements()
290 blockAllSignals(
true );
291 mTitleLineEdit->setText( mLegend->title() );
292 whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
296 whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
297 mFilterByMapCheckBox->setChecked( mLegend->legendFilterByMapEnabled() );
298 mButtonLinkedMaps->setEnabled( mLegend->legendFilterByMapEnabled() );
299 mColumnCountSpinBox->setValue( mLegend->columnCount() );
300 mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
301 mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
302 mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
303 mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
304 mMaxSymbolSizeSpinBox->setValue( mLegend->maximumSymbolSize() );
305 mMinSymbolSizeSpinBox->setValue( mLegend->minimumSymbolSize() );
306 mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
307 mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
321 mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
322 mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
324 mMaxWidthSpinBox->setValue( mLegend->autoWrapLinesAfter() );
326 mRasterStrokeGroupBox->setChecked( mLegend->drawRasterStroke() );
327 mRasterStrokeWidthSpinBox->setValue( mLegend->rasterStrokeWidth() );
328 mRasterStrokeColorButton->setColor( mLegend->rasterStrokeColor() );
330 mCheckBoxAutoUpdate->setChecked( mLegend->autoUpdateModel() );
332 mCheckboxResizeContents->setChecked( mLegend->resizeToContents() );
333 mFilterLegendByAtlasCheckBox->setChecked( mLegend->legendFilterOutAtlas() );
334 mWrapCharLineEdit->setText( mLegend->wrapString() );
337 mMapComboBox->setItem( map );
343 blockAllSignals(
false );
345 mCheckBoxAutoUpdate_stateChanged( mLegend->autoUpdateModel() ? Qt::Checked : Qt::Unchecked,
false );
346 updateDataDefinedButton( mLegendTitleDDBtn );
347 updateDataDefinedButton( mColumnsDDBtn );
350void QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged(
const QString &text )
354 mLegend->beginCommand( tr(
"Change Legend Wrap" ) );
355 mLegend->setWrapString( text );
356 mLegend->adjustBoxSize();
358 mLegend->endCommand();
362void QgsLayoutLegendWidget::mTitleLineEdit_textChanged(
const QString &text )
367 mLegend->setTitle( text );
368 mLegend->adjustBoxSize();
370 mLegend->endCommand();
374void QgsLayoutLegendWidget::titleAlignmentChanged()
378 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
379 mLegend->beginCommand( tr(
"Change Title Alignment" ) );
380 mLegend->setTitleAlignment( alignment );
382 mLegend->endCommand();
386void QgsLayoutLegendWidget::groupAlignmentChanged()
390 mLegend->beginCommand( tr(
"Change Group Alignment" ) );
393 mLegend->endCommand();
397void QgsLayoutLegendWidget::subgroupAlignmentChanged()
401 mLegend->beginCommand( tr(
"Change Subgroup Alignment" ) );
404 mLegend->endCommand();
408void QgsLayoutLegendWidget::itemAlignmentChanged()
412 mLegend->beginCommand( tr(
"Change Item Alignment" ) );
415 mLegend->endCommand();
419void QgsLayoutLegendWidget::arrangementChanged()
423 Qt::AlignmentFlag alignment =
static_cast<Qt::AlignmentFlag
>(
static_cast<int>( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
424 mLegend->beginCommand( tr(
"Change Legend Arrangement" ) );
425 mLegend->setSymbolAlignment( alignment );
427 mLegend->endCommand();
431void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged(
int c )
436 mLegend->setColumnCount(
c );
437 mLegend->adjustBoxSize();
439 mLegend->endCommand();
441 mSplitLayerCheckBox->setEnabled(
c > 1 );
442 mEqualColumnWidthCheckBox->setEnabled(
c > 1 );
445void QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled(
bool checked )
449 mLegend->beginCommand( tr(
"Split Legend Layers" ) );
450 mLegend->setSplitLayer( checked );
451 mLegend->adjustBoxSize();
453 mLegend->endCommand();
457void QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled(
bool checked )
461 mLegend->beginCommand( tr(
"Legend Column Width" ) );
462 mLegend->setEqualColumnWidth( checked );
463 mLegend->adjustBoxSize();
465 mLegend->endCommand();
469void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged(
double d )
474 mLegend->setSymbolWidth( d );
475 mLegend->adjustBoxSize();
477 mLegend->endCommand();
481void QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged(
double d )
486 mLegend->setMaximumSymbolSize( d );
487 mLegend->adjustBoxSize();
489 mLegend->endCommand();
493void QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged(
double d )
498 mLegend->setMinimumSymbolSize( d );
499 mLegend->adjustBoxSize();
501 mLegend->endCommand();
505void QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged(
double d )
510 mLegend->setSymbolHeight( d );
511 mLegend->adjustBoxSize();
513 mLegend->endCommand();
517void QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged(
double d )
522 mLegend->setWmsLegendWidth( d );
523 mLegend->adjustBoxSize();
525 mLegend->endCommand();
529void QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged(
double d )
534 mLegend->setWmsLegendHeight( d );
535 mLegend->adjustBoxSize();
537 mLegend->endCommand();
541void QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged(
double d )
547 mLegend->adjustBoxSize();
549 mLegend->endCommand();
553void QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged(
double d )
559 mLegend->adjustBoxSize();
561 mLegend->endCommand();
565void QgsLayoutLegendWidget::mGroupIndentSpinBox_valueChanged(
double d )
571 mLegend->adjustBoxSize();
573 mLegend->endCommand();
577void QgsLayoutLegendWidget::mSubgroupIndentSpinBox_valueChanged(
double d )
583 mLegend->adjustBoxSize();
585 mLegend->endCommand();
589void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged(
double space )
595 mLegend->adjustBoxSize();
597 mLegend->endCommand();
601void QgsLayoutLegendWidget::spaceGroupSideChanged(
double space )
607 mLegend->adjustBoxSize();
609 mLegend->endCommand();
613void QgsLayoutLegendWidget::spaceSubGroupSideChanged(
double space )
619 mLegend->adjustBoxSize();
621 mLegend->endCommand();
625void QgsLayoutLegendWidget::spaceSymbolSideChanged(
double space )
631 mLegend->adjustBoxSize();
633 mLegend->endCommand();
637void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged(
double d )
643 mLegend->adjustBoxSize();
645 mLegend->endCommand();
649void QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged(
double d )
657 mLegend->adjustBoxSize();
659 mLegend->endCommand();
663void QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged(
double d )
669 mLegend->adjustBoxSize();
671 mLegend->endCommand();
675void QgsLayoutLegendWidget::titleFontChanged()
681 mLegend->adjustBoxSize();
683 mLegend->endCommand();
687void QgsLayoutLegendWidget::groupFontChanged()
693 mLegend->adjustBoxSize();
695 mLegend->endCommand();
699void QgsLayoutLegendWidget::layerFontChanged()
705 mLegend->adjustBoxSize();
707 mLegend->endCommand();
711void QgsLayoutLegendWidget::itemFontChanged()
717 mLegend->adjustBoxSize();
719 mLegend->endCommand();
723void QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged(
double space )
729 mLegend->adjustBoxSize();
731 mLegend->endCommand();
735void QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged(
double d )
740 mLegend->setBoxSpace( d );
741 mLegend->adjustBoxSize();
743 mLegend->endCommand();
747void QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged(
double d )
752 mLegend->setColumnSpace( d );
753 mLegend->adjustBoxSize();
755 mLegend->endCommand();
759void QgsLayoutLegendWidget::maxWidthChanged(
double width )
764 mLegend->setAutoWrapLinesAfter( width );
765 mLegend->adjustBoxSize();
767 mLegend->endCommand();
771void QgsLayoutLegendWidget::mMoveDownToolButton_clicked()
778 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
779 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
780 const QModelIndex parentIndex = sourceIndex.parent();
781 if ( !sourceIndex.isValid() || sourceIndex.row() == mItemTreeView->layerTreeModel()->rowCount( parentIndex ) - 1 )
786 if ( !node && !legendNode )
789 mLegend->beginCommand( tr(
"Moved Legend Item Down" ) );
800 const QModelIndex nextIndex = index.siblingAtRow( index.row() + 1 );
802 if ( nextLegendNode )
804 _moveLegendNode(
legendNode->
layerNode(), _unfilteredLegendNodeIndex( legendNode ), _unfilteredLegendNodeIndex( nextLegendNode ) );
809 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() + 1, 0, parentIndex ) ) );
812 mLegend->endCommand();
815void QgsLayoutLegendWidget::mMoveUpToolButton_clicked()
822 const QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
823 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( index );
824 const QModelIndex parentIndex = sourceIndex.parent();
825 if ( !sourceIndex.isValid() || sourceIndex.row() == 0 )
830 if ( !node && !legendNode )
833 mLegend->beginCommand( tr(
"Move Legend Item Up" ) );
844 const QModelIndex prevIndex = index.siblingAtRow( index.row() - 1 );
846 if ( prevLegendNode )
848 _moveLegendNode(
legendNode->
layerNode(), _unfilteredLegendNodeIndex( legendNode ), _unfilteredLegendNodeIndex( prevLegendNode ) );
853 mItemTreeView->setCurrentIndex( mItemTreeView->proxyModel()->mapFromSource( mItemTreeView->layerTreeModel()->index( sourceIndex.row() - 1, 0, parentIndex ) ) );
856 mLegend->endCommand();
859void QgsLayoutLegendWidget::expandLegendTree()
861 mItemTreeView->expandAll();
864void QgsLayoutLegendWidget::collapseLegendTree()
866 mItemTreeView->collapseAll();
869void QgsLayoutLegendWidget::mCheckBoxAutoUpdate_stateChanged(
int state,
bool userTriggered )
873 mLegend->beginCommand( tr(
"Change Auto Update" ) );
875 mLegend->setAutoUpdateModel( state == Qt::Checked );
877 mLegend->endCommand();
880 mLegendProxyModel->setIsDefaultLegend( state == Qt::Checked );
883 QList<QWidget *> widgets;
884 widgets << mMoveDownToolButton << mMoveUpToolButton << mRemoveToolButton << mAddToolButton
885 << mEditPushButton << mCountToolButton << mUpdateAllPushButton << mAddGroupToolButton
886 << mExpressionFilterButton << mCollapseAllToolButton << mExpandAllToolButton;
887 for ( QWidget *w : std::as_const( widgets ) )
888 w->setEnabled( state != Qt::Checked );
890 if ( state == Qt::Unchecked )
893 selectedChanged( QModelIndex(), QModelIndex() );
894 mItemTreeView->proxyModel()->setShowPrivateLayers(
true );
898 mItemTreeView->proxyModel()->setShowPrivateLayers(
false );
902void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
918 mLegend->beginCommand( tr(
"Change Legend Map" ) );
919 mLegend->setLinkedMap( map );
921 mLegend->endCommand();
923 setLegendMapViewData();
927void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
934 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
935 mLegend->setResizeToContents( checked );
937 mLegend->adjustBoxSize();
939 mLegend->endCommand();
942void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
949 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
950 mLegend->setDrawRasterStroke( state );
951 mLegend->adjustBoxSize();
953 mLegend->endCommand();
956void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
964 mLegend->setRasterStrokeWidth( d );
965 mLegend->adjustBoxSize();
967 mLegend->endCommand();
970void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
978 mLegend->setRasterStrokeColor( newColor );
980 mLegend->endCommand();
983void QgsLayoutLegendWidget::mAddToolButton_clicked()
990 QList<QgsMapLayer *> visibleLayers;
991 if ( mLegend->linkedMap() )
993 visibleLayers = mLegend->linkedMap()->layersToRender();
995 if ( visibleLayers.isEmpty() )
998 visibleLayers = mMapCanvas->layers(
true );
1002 addDialog.setVisibleLayers( visibleLayers );
1003 if ( addDialog.exec() == QDialog::Accepted )
1005 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
1006 if ( !layers.empty() )
1008 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
1011 mLegend->model()->rootGroup()->addLayer( layer );
1013 mLegend->updateLegend();
1015 mLegend->endCommand();
1020void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
1027 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
1028 if ( !selectionModel )
1033 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
1035 QList<QPersistentModelIndex> proxyIndexes;
1036 const QModelIndexList viewSelection = selectionModel->selectedIndexes();
1037 for (
const QModelIndex &index : viewSelection )
1038 proxyIndexes << index;
1041 QHash<QgsLayerTreeLayer *, QList<int>> nodesWithRemoval;
1042 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1047 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex( legendNode ) );
1050 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
1052 QList<int> toDelete = it.value();
1053 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
1056 for (
int i : std::as_const( toDelete ) )
1058 if ( i >= 0 && i < order.count() )
1059 order.removeAt( i );
1063 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
1067 for (
const QPersistentModelIndex &proxyIndex : std::as_const( proxyIndexes ) )
1069 if ( proxyIndex.isValid() && mItemTreeView->index2node( proxyIndex ) )
1071 const QModelIndex sourceIndex = mItemTreeView->proxyModel()->mapToSource( proxyIndex );
1072 mLegend->model()->removeRow( sourceIndex.row(), sourceIndex.parent() );
1076 mLegend->updateLegend();
1078 mLegend->endCommand();
1081void QgsLayoutLegendWidget::mEditPushButton_clicked()
1088 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
1089 mItemTreeView_doubleClicked( idx );
1092void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
1100 QModelIndex currentIndex = mItemTreeView->currentIndex();
1101 if ( !currentIndex.isValid() )
1120 mLegend->beginCommand( tr(
"Update Legend" ) );
1123 for (
const QString &key : constCustomProperties )
1125 if ( key.startsWith( QLatin1String(
"legend/" ) ) )
1132 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1134 mLegend->updateLegend();
1136 mLegend->endCommand();
1139void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1146 const QList<QModelIndex> selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1147 if ( selectedIndexes.empty() )
1150 mLegend->beginCommand( tr(
"Update Legend" ) );
1151 for (
const QModelIndex &index : selectedIndexes )
1157 currentNode->
setCustomProperty( QStringLiteral(
"showFeatureCount" ), checked ? 1 : 0 );
1159 mLegend->updateFilterByMap();
1160 mLegend->adjustBoxSize();
1161 mLegend->endCommand();
1164void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1166 mLegend->beginCommand( tr(
"Update Legend" ) );
1167 mLegend->setLegendFilterByMapEnabled( checked );
1168 mLegend->adjustBoxSize();
1170 mLegend->endCommand();
1173void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1181 QModelIndex currentIndex = mItemTreeView->currentIndex();
1182 if ( !currentIndex.isValid() )
1193 mLegend->beginCommand( tr(
"Update Legend" ) );
1194 mLegend->updateFilterByMap();
1195 mLegend->adjustBoxSize();
1196 mLegend->endCommand();
1199void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1206 QModelIndex currentIndex = mItemTreeView->currentIndex();
1207 if ( !currentIndex.isValid() )
1214 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1220 QString currentExpression;
1222 currentExpression = QStringLiteral(
"@symbol_label" );
1228 QStringList highlighted;
1231 const QList<QgsLayerTreeModelLegendNode *> legendNodes = model->layerLegendNodes( layerNode,
false );
1232 if ( !legendNodes.isEmpty() )
1234 if (
QgsSymbolLegendNode *symbolNode = qobject_cast<QgsSymbolLegendNode *>( legendNodes.first() ) )
1236 legendContext.
appendScope( symbolNode->createSymbolScope() );
1237 highlighted << QStringLiteral(
"symbol_label" ) << QStringLiteral(
"symbol_id" ) << QStringLiteral(
"symbol_count" );
1250 QgsExpressionBuilderDialog expressiondialog(
nullptr, currentExpression,
nullptr, QStringLiteral(
"generic" ), legendContext );
1251 if ( expressiondialog.exec() )
1254 mItemTreeView->layerTreeModel()->refreshLayerLegend( layerNode );
1257 mLegend->beginCommand( tr(
"Update Legend" ) );
1259 mLegend->adjustBoxSize();
1260 mLegend->endCommand();
1263void QgsLayoutLegendWidget::mUpdateAllPushButton_clicked()
1268void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1272 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1273 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1274 mLegend->updateLegend();
1276 mLegend->endCommand();
1280void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1285 mLegend->setLegendFilterOutAtlas( toggled );
1291void QgsLayoutLegendWidget::updateLegend()
1295 mLegend->beginCommand( tr(
"Update Legend" ) );
1298 mLegend->setAutoUpdateModel(
true );
1299 mLegend->setAutoUpdateModel(
false );
1301 mLegend->endCommand();
1305void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1307 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1308 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1317bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1327 mLegend = qobject_cast<QgsLayoutItemLegend *>( item );
1328 mItemPropertiesWidget->setItem( mLegend );
1330 if ( mMapFilteringWidget )
1331 mMapFilteringWidget->setItem( mLegend );
1335 mLegendProxyModel =
new QgsLegendLayerTreeProxyModel( mLegend,
this );
1337 mItemTreeView->setModel( mLegend->model(), mLegendProxyModel );
1347void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1349 mTitleLineEdit->blockSignals( b );
1350 mTitleAlignCombo->blockSignals( b );
1351 mItemTreeView->blockSignals( b );
1352 mCheckBoxAutoUpdate->blockSignals( b );
1353 mMapComboBox->blockSignals( b );
1354 mFilterByMapCheckBox->blockSignals( b );
1355 mColumnCountSpinBox->blockSignals( b );
1356 mSplitLayerCheckBox->blockSignals( b );
1357 mEqualColumnWidthCheckBox->blockSignals( b );
1358 mSymbolWidthSpinBox->blockSignals( b );
1359 mSymbolHeightSpinBox->blockSignals( b );
1360 mMaxSymbolSizeSpinBox->blockSignals( b );
1361 mMinSymbolSizeSpinBox->blockSignals( b );
1362 mGroupSpaceSpinBox->blockSignals( b );
1363 mGroupIndentSpinBox->blockSignals( b );
1364 mSubgroupIndentSpinBox->blockSignals( b );
1365 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1366 mGroupSideSpinBox->blockSignals( b );
1367 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1368 mSubgroupSideSpinBox->blockSignals( b );
1369 mLayerSpaceSpinBox->blockSignals( b );
1370 mSymbolSpaceSpinBox->blockSignals( b );
1371 mSymbolSideSpaceSpinBox->blockSignals( b );
1372 mIconLabelSpaceSpinBox->blockSignals( b );
1373 mBoxSpaceSpinBox->blockSignals( b );
1374 mColumnSpaceSpinBox->blockSignals( b );
1375 mRasterStrokeGroupBox->blockSignals( b );
1376 mRasterStrokeColorButton->blockSignals( b );
1377 mRasterStrokeWidthSpinBox->blockSignals( b );
1378 mWmsLegendWidthSpinBox->blockSignals( b );
1379 mWmsLegendHeightSpinBox->blockSignals( b );
1380 mCheckboxResizeContents->blockSignals( b );
1381 mTitleSpaceBottomSpinBox->blockSignals( b );
1382 mFilterLegendByAtlasCheckBox->blockSignals( b );
1383 mTitleFontButton->blockSignals( b );
1384 mGroupFontButton->blockSignals( b );
1385 mLayerFontButton->blockSignals( b );
1386 mItemFontButton->blockSignals( b );
1387 mWrapCharLineEdit->blockSignals( b );
1388 mMaxWidthSpinBox->blockSignals( b );
1391void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1394 Q_UNUSED( previous )
1396 mLayerExpressionButton->setEnabled(
false );
1398 if ( mLegend && mLegend->autoUpdateModel() )
1409 mLayerExpressionButton->setEnabled(
true );
1413 mCountToolButton->setChecked(
false );
1414 mCountToolButton->setEnabled(
false );
1417 mExpressionFilterButton->blockSignals(
true );
1418 mExpressionFilterButton->setChecked(
false );
1419 mExpressionFilterButton->setEnabled(
false );
1420 mExpressionFilterButton->blockSignals(
false );
1431 mCountToolButton->setChecked( currentNode->
customProperty( QStringLiteral(
"showFeatureCount" ), 0 ).toInt() );
1432 mCountToolButton->setEnabled(
true );
1433 mLayerExpressionButton->setEnabled(
true );
1437 mExpressionFilterButton->blockSignals(
true );
1438 mExpressionFilterButton->setExpressionText( expr );
1439 mExpressionFilterButton->setVectorLayer( vl );
1440 mExpressionFilterButton->setEnabled(
true );
1441 mExpressionFilterButton->setChecked( exprEnabled );
1442 mExpressionFilterButton->blockSignals(
false );
1445void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1447 QAction *a = qobject_cast<QAction *>( sender() );
1448 if ( !a || !mItemTreeView->currentNode() )
1455void QgsLayoutLegendWidget::setLegendMapViewData()
1457 if ( mLegend->linkedMap() )
1461 measurementConverter.
setDpi( dpi );
1464 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1465 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1466 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1470void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1474 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
Qgis::GeometryType::Polygon );
1478void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1480 if ( !mLegend || !idx.isValid() )
1485 if ( mLegend->autoUpdateModel() )
1491 int originalIndex = -1;
1494 originalIndex = _originalLegendNodeIndex( legendNode );
1498 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode, legendNode, originalIndex );
1499 openPanel( widget );
1507QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1512QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1514 if ( !mView->currentNode() )
1517 if ( mWidget->legend()->autoUpdateModel() )
1520 QMenu *menu =
new QMenu();
1524 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1525 menu->addSeparator();
1530 QActionGroup *styleGroup =
new QActionGroup { mWidget };
1531 styleGroup->setExclusive(
true );
1533 QList<Qgis::LegendComponent> lst;
1537 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1538 action->setActionGroup( styleGroup );
1539 action->setCheckable(
true );
1540 action->setChecked( currentStyle == style );
1541 action->setData(
static_cast<int>( style ) );
1556 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1559 setPanelTitle( tr(
"Legend Item Properties" ) );
1568 QString currentLabel;
1571 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1572 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1576 currentLabel = mLayer->name();
1577 QVariant v = mLayer->customProperty( QStringLiteral(
"legend/title-label" ) );
1579 currentLabel = v.toString();
1580 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1582 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1587 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1590 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1591 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1592 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1593 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1594 mPatchGroup->setVisible( mLegendNode || mLayer );
1595 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1596 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1597 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1598 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1599 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1602 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1603 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1607 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1608 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1611 mCustomSymbolCheckBox->setChecked(
false );
1616 patchShape = symbolLegendNode->patchShape();
1618 std::unique_ptr<QgsSymbol> customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() :
nullptr );
1619 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1622 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1623 mCustomSymbolButton->setSymbolType( customSymbol->type() );
1624 mCustomSymbolButton->setSymbol( customSymbol.release() );
1626 else if ( symbolLegendNode->symbol() )
1628 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1629 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1630 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1633 else if ( !mLegendNode && mLayer )
1635 patchShape = mLayer->patchShape();
1638 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1640 mCustomSymbolCheckBox->setChecked(
true );
1641 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1642 mCustomSymbolButton->setSymbolType( customSymbol->type() );
1643 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1647 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1648 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1649 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1656 switch ( qobject_cast<QgsVectorLayer *>( mLayer->layer() )->geometryType() )
1671 mPatchShapeLabel->hide();
1672 mPatchShapeButton->hide();
1675 if ( !patchShape.
isNull() )
1676 mPatchShapeButton->setShape( patchShape );
1680 if ( symbolLegendNode->symbol() )
1682 mPatchShapeButton->setSymbolType( symbolLegendNode->symbol()->type() );
1686 mPatchShapeLabel->hide();
1687 mPatchShapeButton->hide();
1692 mPatchShapeLabel->hide();
1693 mPatchShapeButton->hide();
1698 mLabelGroup->hide();
1699 mColorRampLegendWidget->setSettings( colorRampNode->settings() );
1703 mColorRampLegendWidget->hide();
1716 mCustomSymbolCheckBox->hide();
1725 mLabelEdit->setPlainText( currentLabel );
1726 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1728 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1730 connect( mWidthSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1731 connect( mHeightSpinBox, qOverload<double>( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1733 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1736 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1738 connect( mColumnSplitBehaviorComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1742 connectChildPanel( mColorRampLegendWidget );
1745void QgsLayoutLegendNodeWidget::setDockMode(
bool dockMode )
1747 mColorRampLegendWidget->setDockMode( dockMode );
1751void QgsLayoutLegendNodeWidget::labelChanged()
1755 const QString label = mLabelEdit->toPlainText();
1760 else if ( mLegendNode )
1763 mLegend->model()->refreshLayerLegend( mLayer );
1767 mLayer->setCustomProperty( QStringLiteral(
"legend/title-label" ), label );
1771 embeddedNode->setUserLabel( QString() );
1774 mLegend->adjustBoxSize();
1775 mLegend->invalidateCache();
1777 mLegend->endCommand();
1780void QgsLayoutLegendNodeWidget::patchChanged()
1782 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1788 mLegend->model()->refreshLayerLegend( mLayer );
1792 mLayer->setPatchShape( shape );
1793 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1798 mLegend->model()->refreshLayerLegend( mLayer );
1801 mLegend->adjustBoxSize();
1803 mLegend->endCommand();
1806void QgsLayoutLegendNodeWidget::insertExpression()
1814 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1818 if ( mLayer && mLayer->layer() )
1823 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" ) );
1827 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1828 if ( exprDlg.exec() == QDialog::Accepted )
1830 expression = exprDlg.expressionText();
1831 if ( !expression.isEmpty() )
1833 mLegend->beginCommand( tr(
"Insert expression" ) );
1834 mLabelEdit->insertPlainText(
"[%" + expression.trimmed() +
"%]" );
1835 mLegend->endCommand();
1840void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1842 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1843 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1848 mLegend->model()->refreshLayerLegend( mLayer );
1852 mLayer->setPatchSize( size );
1853 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1858 mLegend->model()->refreshLayerLegend( mLayer );
1861 mLegend->adjustBoxSize();
1863 mLegend->endCommand();
1866void QgsLayoutLegendNodeWidget::customSymbolChanged()
1868 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1870 if ( mCustomSymbolCheckBox->isChecked() )
1875 mLegend->model()->refreshLayerLegend( mLayer );
1879 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1884 mLegend->model()->refreshLayerLegend( mLayer );
1892 mLegend->model()->refreshLayerLegend( mLayer );
1896 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1901 mLegend->model()->refreshLayerLegend( mLayer );
1905 mLegend->adjustBoxSize();
1907 mLegend->endCommand();
1910void QgsLayoutLegendNodeWidget::colorRampLegendChanged()
1912 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1916 mLegend->model()->refreshLayerLegend( mLayer );
1918 mLegend->adjustBoxSize();
1920 mLegend->endCommand();
1923void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1925 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1930 mLegend->model()->refreshLayerLegend( mLayer );
1934 mLayer->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1938 mNode->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1941 mLegend->adjustBoxSize();
1943 mLegend->endCommand();
1946void QgsLayoutLegendNodeWidget::columnSplitChanged()
1948 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1950 if ( mLayer && !mLegendNode )
1955 mLegend->adjustBoxSize();
1957 mLegend->endCommand();
1964QgsLayoutLegendMapFilteringWidget::QgsLayoutLegendMapFilteringWidget(
QgsLayoutItemLegend *legend )
1966 , mLegendItem( legend )
1969 setPanelTitle( tr(
"Legend Filtering" ) );
1971 setNewItem( legend );
1974bool QgsLayoutLegendMapFilteringWidget::setNewItem(
QgsLayoutItem *item )
1984 mLegendItem = qobject_cast<QgsLayoutItemLegend *>( item );
1991 updateGuiElements();
1996void QgsLayoutLegendMapFilteringWidget::updateGuiElements()
1998 if ( mBlockUpdates )
2001 mBlockUpdates =
true;
2003 if ( mFilterMapItemsListView->model() )
2005 QAbstractItemModel *oldModel = mFilterMapItemsListView->model();
2006 mFilterMapItemsListView->setModel(
nullptr );
2007 oldModel->deleteLater();
2010 QgsLayoutLegendMapFilteringModel *model =
new QgsLayoutLegendMapFilteringModel( mLegendItem, mLegendItem->layout()->itemsModel(), mFilterMapItemsListView );
2011 mFilterMapItemsListView->setModel( model );
2013 mBlockUpdates =
false;
2021 : QSortFilterProxyModel( parent )
2022 , mLayoutModel( layoutModel )
2023 , mLegendItem( legend )
2025 setSourceModel( layoutModel );
2028int QgsLayoutLegendMapFilteringModel::columnCount(
const QModelIndex & )
const
2033QVariant QgsLayoutLegendMapFilteringModel::data(
const QModelIndex &i,
int role )
const
2038 if ( i.column() != 0 )
2043 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( i ) ) );
2051 case Qt::CheckStateRole:
2052 switch ( i.column() )
2057 return Qt::Unchecked;
2059 return mLegendItem->filterByMapItems().contains( mapItem ) ? Qt::Checked : Qt::Unchecked;
2067 return mLayoutModel->data( sourceIndex, role );
2071bool QgsLayoutLegendMapFilteringModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
2075 if ( !index.isValid() )
2078 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2079 if ( !mapItem || !mLegendItem )
2084 mLegendItem->layout()->undoStack()->beginCommand( mLegendItem, tr(
"Change Legend Linked Maps" ) );
2086 QList<QgsLayoutItemMap *> linkedMaps = mLegendItem->filterByMapItems();
2087 if ( value.toBool() )
2089 if ( !linkedMaps.contains( mapItem ) )
2091 linkedMaps.append( mapItem );
2092 mLegendItem->setFilterByMapItems( linkedMaps );
2097 linkedMaps.removeAll( mapItem );
2098 mLegendItem->setFilterByMapItems( linkedMaps );
2100 emit dataChanged( index, index, QVector<int>() << role );
2102 mLegendItem->layout()->undoStack()->endCommand();
2103 mLegendItem->invalidateCache();
2108Qt::ItemFlags QgsLayoutLegendMapFilteringModel::flags(
const QModelIndex &index )
const
2110 Qt::ItemFlags flags = QSortFilterProxyModel::flags( index );
2112 if ( !index.isValid() )
2117 QgsLayoutItemMap *mapItem = qobject_cast<QgsLayoutItemMap *>( mLayoutModel->itemFromIndex( mapToSource( index ) ) );
2118 const bool isMainLinkedMapItem = mLegendItem ? ( mLegendItem->linkedMap() == mapItem ) : false;
2124 if ( !isMainLinkedMapItem )
2126 flags |= Qt::ItemIsEnabled;
2130 flags &= ~Qt::ItemIsEnabled;
2133 switch ( index.column() )
2136 if ( !isMainLinkedMapItem )
2137 return flags | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
2139 return flags | Qt::ItemIsSelectable;
2142 return flags | Qt::ItemIsSelectable;
2146bool QgsLayoutLegendMapFilteringModel::filterAcceptsRow(
int source_row,
const QModelIndex &source_parent )
const
2148 QgsLayoutItem *item = mLayoutModel->itemFromIndex( mLayoutModel->index( source_row, 0, source_parent ) );
2161QgsLegendLayerTreeProxyModel::QgsLegendLayerTreeProxyModel(
QgsLayoutItemLegend *legend, QObject *parent )
2167void QgsLegendLayerTreeProxyModel::setIsDefaultLegend(
bool isDefault )
2169 mIsDefaultLegend = isDefault;
2172 setShowPrivateLayers( !mIsDefaultLegend );
2177bool QgsLegendLayerTreeProxyModel::nodeShown(
QgsLayerTreeNode *node )
const
LegendComponent
Component of legends which can be styled.
@ Symbol
Symbol icon (excluding label).
@ Group
Legend group title.
@ Hidden
Special style, item is hidden including margins around.
@ Subgroup
Legend subgroup title.
@ SymbolLabel
Symbol label (excluding icon).
@ ExcludeByDefault
If set, the layer should not be included in legends by default, and must be manually added by a user.
void changed()
Emitted when the alignment is changed.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
Settings for a color ramp legend node.
A legend node which renders a color ramp.
A generic dialog for building expression strings.
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
static QString findAndSelectActiveExpression(QgsCodeEditor *editor, const QString &pattern=QString())
Find the expression under the cursor in the given editor and select it.
Container of fields for a vector layer.
Layer tree group node serves as a container for layers and further groups.
void insertChildNode(int index, QgsLayerTreeNode *node)
Insert existing node at specified position.
void setName(const QString &n) override
Sets the group's name.
void removeChildNode(QgsLayerTreeNode *node)
Remove a child node from this group.
QString name() const override
Returns the group's name.
Layer tree node points to a map layer.
void setPatchSize(QSizeF size)
Sets the user (overridden) size for the legend node.
QString labelExpression() const
Returns the expression member of the LayerTreeNode.
LegendNodesSplitBehavior
Legend node column split behavior.
@ AllowSplittingLegendNodesOverMultipleColumns
Allow splitting node's legend nodes across multiple columns.
@ PreventSplittingLegendNodesOverMultipleColumns
Prevent splitting node's legend nodes across multiple columns.
@ UseDefaultLegendSetting
Inherit default legend column splitting setting.
void setLabelExpression(const QString &expression)
set the expression to evaluate
void setPatchShape(const QgsLegendPatchShape &shape)
Sets the symbol patch shape to use when rendering the legend node symbol.
QgsMapLayer * layer() const
Returns the map layer associated with this node.
An abstract interface for legend items returned from QgsMapLayerLegend implementation.
NodeTypes
Types of legend nodes.
@ SimpleLegend
Simple label with icon legend node type.
@ RasterSymbolLegend
Raster symbol legend node type.
@ ImageLegend
Raster image legend node type.
@ DataDefinedSizeLegend
Marker symbol legend node type.
@ WmsLegend
WMS legend node type.
@ EmbeddedWidget
Embedded widget placeholder node type.
@ ColorRampLegend
Color ramp legend.
@ SymbolLegend
Vector symbol legend node type.
@ NodeType
Type of node. Added in 3.16.
QgsLayerTreeModel * model() const
Returns pointer to model owning this legend node.
QgsLayerTreeLayer * layerNode() const
Returns pointer to the parent layer node.
QgsLayerTreeModelLegendNode * legendNodeEmbeddedInParent(QgsLayerTreeLayer *nodeLayer) const
Returns legend node that may be embedded in parent (i.e.
QList< QgsLayerTreeModelLegendNode * > layerOriginalLegendNodes(QgsLayerTreeLayer *nodeLayer)
Returns original (unfiltered) list of legend nodes attached to a particular layer node.
Base class for nodes in a layer tree.
@ NodeLayer
Leaf node pointing to a layer.
void setCustomProperty(const QString &key, const QVariant &value)
Sets a custom property for the node. Properties are stored in a map and saved in project file.
void removeCustomProperty(const QString &key)
Remove a custom property from layer. Properties are stored in a map and saved in project file.
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer. Properties are stored in a map and saved in project file.
QgsLayerTreeNode * parent()
Gets pointer to the parent. If parent is nullptr, the node is a root node.
NodeType nodeType() const
Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree...
QStringList customProperties() const
Returns list of keys stored in custom properties.
virtual QgsLayerTreeNode * clone() const =0
Create a copy of the node. Returns new instance.
A proxy model for QgsLayerTreeModel, supporting private layers and text filtering.
virtual bool nodeShown(QgsLayerTreeNode *node) const
Returns true if the specified node should be shown.
static void setLegendFilterByExpression(QgsLayerTreeLayer &layer, const QString &expr, bool enabled=true)
Sets the expression filter of a legend layer.
static QString legendFilterByExpression(const QgsLayerTreeLayer &layer, bool *enabled=nullptr)
Returns the expression filter of a legend layer.
Extends QTreeView and provides additional functionality when working with a layer tree.
static QgsLayerTreeLayer * toLayer(QgsLayerTreeNode *node)
Cast node to a layer.
static bool isLayer(const QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
static bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
static QgsLayerTreeGroup * toGroup(QgsLayerTreeNode *node)
Cast node to a group.
Used to render QgsLayout as an atlas, by iterating over the features from an associated vector layer.
void toggled(bool enabled)
Emitted when atlas is enabled or disabled.
A common interface for layout designer dialogs and widgets.
virtual QgsMessageBar * messageBar()=0
Returns the designer's message bar.
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
A layout item subclass for map legends.
bool autoUpdateModel() const
Returns whether the legend content should auto update to reflect changes in the project's layer tree.
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.
@ UndoLegendAutoWrapAfter
Legend auto wrap lines after distance.
@ UndoLegendSymbolSpace
Legend symbol spacing.
@ UndoLegendSymbolWidth
Legend symbol width.
@ UndoLegendColumnCount
Legend column count.
@ UndoLegendSymbolHeight
Legend symbol height.
@ UndoLegendGroupSpace
Legend group spacing.
@ UndoLegendSubgroupIndent
Legend subgroup indent.
@ UndoLegendRasterStrokeWidth
Legend raster stroke width.
@ UndoLegendGroupIndent
Legend group indent.
@ UndoLegendText
Legend text.
@ UndoLegendWmsLegendHeight
Legend WMS height.
@ UndoLegendGroupFont
Legend group font.
int type() const override
Returns a unique graphics item type identifier.
A dialog to add new layers to the legend.
Provides a method of converting QgsLayoutMeasurements from one unit to another.
QgsLayoutMeasurement convert(QgsLayoutMeasurement measurement, Qgis::LayoutUnit targetUnits) const
Converts a measurement from one unit to another.
void setDpi(const double dpi)
Sets the dots per inch (dpi) for the measurement converter.
A model for items attached to a layout.
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
@ LegendAutoWrapWidth
Legend text automatic wrapping width.
@ LegendTitle
Legend title.
@ LegendColumnCount
Legend column count.
void layerChanged(QgsVectorLayer *layer)
Emitted when the context's layer is changed.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
QgsLayoutReportContext & reportContext()
Returns a reference to the layout's report context, which stores information relating to the current ...
Item model implementation based on layer tree model for layout legend.
Represents a patch shape for use in map legends.
bool isNull() const
Returns true if the patch shape is a null QgsLegendPatchShape, which indicates that the default legen...
static void setNodeLegendStyle(QgsLayerTreeNode *node, Qgis::LegendComponent style)
Sets the style of a node.
static Qgis::LegendComponent nodeLegendStyle(QgsLayerTreeNode *node, QgsLayerTreeModel *model)
Returns the style for the given node, within the specified model.
static QString styleLabel(Qgis::LegendComponent s)
Returns a translated string representing a style component, for use in UI.
Map canvas is a class for displaying all GIS data types on a canvas.
static void setLegendNodeOrder(QgsLayerTreeLayer *nodeLayer, const QList< int > &order)
static void setLegendNodeColorRampSettings(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsColorRampLegendNodeSettings *settings)
Sets a custom legend color ramp settings for the legend node belonging to nodeLayer at the specified ...
static void setLegendNodeCustomSymbol(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsSymbol *symbol)
Sets a custom legend symbol for the legend node belonging to nodeLayer at the specified originalIndex...
static void setLegendNodeUserLabel(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QString &newLabel)
static void setLegendNodeSymbolSize(QgsLayerTreeLayer *nodeLayer, int originalIndex, QSizeF size)
Sets the legend symbol size for the legend node belonging to nodeLayer at the specified originalIndex...
static void setLegendNodeColumnBreak(QgsLayerTreeLayer *nodeLayer, int originalIndex, bool columnBreakBeforeNode)
Sets whether a forced column break should occur before the node.
static void setLegendNodePatchShape(QgsLayerTreeLayer *nodeLayer, int originalIndex, const QgsLegendPatchShape &shape)
Sets the legend patch shape for the legend node belonging to nodeLayer at the specified originalIndex...
static QList< int > legendNodeOrder(QgsLayerTreeLayer *nodeLayer)
An abstract interface for implementations of legends for one map layer.
Qgis::MapLayerLegendFlags flags() const
Returns flags associated with the legend.
Base class for all map layer types.
QgsMapLayerLegend * legend() const
Can be nullptr.
Interface for master layout type objects, such as print layouts and reports.
static int qtDefaultDpiX()
Returns the default Qt horizontal DPI.
Implementation of legend node interface for displaying preview of vector symbols and their labels and...
Abstract base class for all rendered symbols.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based dataset.
QgsExpressionContextScope * createExpressionContextScope() const final
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
QgsLayerTreeModelLegendNode * legendNode(const QString &rule, QgsLayerTreeModel &model)
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.