46 #include <QMessageBox>
47 #include <QInputDialog>
64 int unfilteredNodeIndex = _unfilteredLegendNodeIndex(
legendNode );
66 return ( unfilteredNodeIndex >= 0 && unfilteredNodeIndex < order.count() ? order[unfilteredNodeIndex] : -1 );
73 , mMapCanvas( mapCanvas )
78 connect( mWrapCharLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged );
79 connect( mTitleLineEdit, &QLineEdit::textChanged,
this, &QgsLayoutLegendWidget::mTitleLineEdit_textChanged );
84 connect( mColumnCountSpinBox,
static_cast < void ( QSpinBox::* )(
int )
> ( &QSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged );
85 connect( mSplitLayerCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled );
86 connect( mEqualColumnWidthCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled );
87 connect( mSymbolWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged );
88 connect( mSymbolHeightSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged );
89 connect( mWmsLegendWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
90 connect( mWmsLegendHeightSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
91 connect( mTitleSpaceBottomSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
92 connect( mGroupSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
93 connect( mSpaceBelowGroupHeadingSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
94 connect( mGroupSideSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
95 connect( mLayerSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
96 connect( mSpaceBelowSubgroupHeadingSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
97 connect( mSubgroupSideSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
98 connect( mSymbolSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
99 connect( mSymbolSideSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
100 connect( mIconLabelSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
102 connect( mBoxSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
103 connect( mColumnSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged );
104 connect( mLineSpacingSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLineSpacingSpinBox_valueChanged );
105 connect( mCheckBoxAutoUpdate, &QCheckBox::stateChanged,
this, [ = ](
int state ) { mCheckBoxAutoUpdate_stateChanged( state ); } );
106 connect( mCheckboxResizeContents, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mCheckboxResizeContents_toggled );
107 connect( mRasterStrokeGroupBox, &QgsCollapsibleGroupBoxBasic::toggled,
this, &QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled );
108 connect( mRasterStrokeWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged );
109 connect( mRasterStrokeColorButton, &
QgsColorButton::colorChanged,
this, &QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged );
110 connect( mMoveDownToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveDownToolButton_clicked );
111 connect( mMoveUpToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveUpToolButton_clicked );
112 connect( mRemoveToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mRemoveToolButton_clicked );
113 connect( mAddToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddToolButton_clicked );
114 connect( mEditPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mEditPushButton_clicked );
115 connect( mCountToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mCountToolButton_clicked );
116 connect( mExpressionFilterButton, &QgsLegendFilterButton::toggled,
this, &QgsLayoutLegendWidget::mExpressionFilterButton_toggled );
117 connect( mLayerExpressionButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mLayerExpressionButton_clicked );
118 connect( mFilterByMapCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled );
119 connect( mUpdateAllPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mUpdateAllPushButton_clicked );
120 connect( mAddGroupToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddGroupToolButton_clicked );
121 connect( mFilterLegendByAtlasCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled );
122 connect( mItemTreeView, &QgsLayerTreeView::doubleClicked,
this, &QgsLayoutLegendWidget::mItemTreeView_doubleClicked );
123 setPanelTitle( tr(
"Legend Properties" ) );
130 mTitleAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
131 mGroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
132 mSubgroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
133 mItemAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
135 mArrangementCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignRight );
137 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignLeft, tr(
"Symbols on Left" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsLeft.svg" ) ) );
138 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignRight, tr(
"Symbols on Right" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsRight.svg" ) ) );
140 mSpaceBelowGroupHeadingSpinBox->setClearValue( 0 );
141 mGroupSideSpinBox->setClearValue( 0 );
142 mSpaceBelowSubgroupHeadingSpinBox->setClearValue( 0 );
143 mSubgroupSideSpinBox->setClearValue( 0 );
144 mSymbolSideSpaceSpinBox->setClearValue( 0 );
165 mFontColorButton->setColorDialogTitle( tr(
"Select Font Color" ) );
166 mFontColorButton->setContext( QStringLiteral(
"composer" ) );
168 mRasterStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
169 mRasterStrokeColorButton->setAllowOpacity(
true );
170 mRasterStrokeColorButton->setContext( QStringLiteral(
"composer " ) );
172 mMapComboBox->setCurrentLayout( legend->
layout() );
178 mainLayout->addWidget( mItemPropertiesWidget );
180 mItemTreeView->setHeaderHidden(
true );
182 mItemTreeView->setModel( legend->
model() );
183 mItemTreeView->setMenuProvider(
new QgsLayoutLegendMenuProvider( mItemTreeView,
this ) );
184 setLegendMapViewData();
190 connect( layoutAtlas(), &
QgsLayoutAtlas::toggled,
this, &QgsLayoutLegendWidget::updateFilterLegendByAtlasButton );
199 connect( mItemTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
200 this, &QgsLayoutLegendWidget::selectedChanged );
209 if ( mItemPropertiesWidget )
210 mItemPropertiesWidget->setMasterLayout( masterLayout );
213 void QgsLayoutLegendWidget::setGuiElements()
220 blockAllSignals(
true );
221 mTitleLineEdit->setText( mLegend->title() );
222 whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
226 whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
227 mFilterByMapCheckBox->setChecked( mLegend->legendFilterByMapEnabled() );
228 mColumnCountSpinBox->setValue( mLegend->columnCount() );
229 mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
230 mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
231 mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
232 mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
233 mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
234 mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
246 mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
247 mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
248 mLineSpacingSpinBox->setValue( mLegend->lineSpacing() );
250 mRasterStrokeGroupBox->setChecked( mLegend->drawRasterStroke() );
251 mRasterStrokeWidthSpinBox->setValue( mLegend->rasterStrokeWidth() );
252 mRasterStrokeColorButton->setColor( mLegend->rasterStrokeColor() );
254 mCheckBoxAutoUpdate->setChecked( mLegend->autoUpdateModel() );
256 mCheckboxResizeContents->setChecked( mLegend->resizeToContents() );
257 mFilterLegendByAtlasCheckBox->setChecked( mLegend->legendFilterOutAtlas() );
258 mWrapCharLineEdit->setText( mLegend->wrapString() );
261 mMapComboBox->setItem( map );
262 mFontColorButton->setColor( mLegend->fontColor() );
268 blockAllSignals(
false );
270 mCheckBoxAutoUpdate_stateChanged( mLegend->autoUpdateModel() ? Qt::Checked : Qt::Unchecked,
false );
271 updateDataDefinedButton( mLegendTitleDDBtn );
272 updateDataDefinedButton( mColumnsDDBtn );
275 void QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged(
const QString &text )
279 mLegend->beginCommand( tr(
"Change Legend Wrap" ) );
280 mLegend->setWrapString( text );
281 mLegend->adjustBoxSize();
283 mLegend->endCommand();
287 void QgsLayoutLegendWidget::mTitleLineEdit_textChanged(
const QString &text )
292 mLegend->setTitle( text );
293 mLegend->adjustBoxSize();
295 mLegend->endCommand();
299 void QgsLayoutLegendWidget::titleAlignmentChanged()
303 Qt::AlignmentFlag alignment =
static_cast< Qt::AlignmentFlag
>(
static_cast< int >( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
304 mLegend->beginCommand( tr(
"Change Title Alignment" ) );
305 mLegend->setTitleAlignment( alignment );
307 mLegend->endCommand();
311 void QgsLayoutLegendWidget::groupAlignmentChanged()
315 mLegend->beginCommand( tr(
"Change Group Alignment" ) );
318 mLegend->endCommand();
322 void QgsLayoutLegendWidget::subgroupAlignmentChanged()
326 mLegend->beginCommand( tr(
"Change Subgroup Alignment" ) );
329 mLegend->endCommand();
333 void QgsLayoutLegendWidget::itemAlignmentChanged()
337 mLegend->beginCommand( tr(
"Change Item Alignment" ) );
340 mLegend->endCommand();
344 void QgsLayoutLegendWidget::arrangementChanged()
348 Qt::AlignmentFlag alignment =
static_cast< Qt::AlignmentFlag
>(
static_cast< int >( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
349 mLegend->beginCommand( tr(
"Change Legend Arrangement" ) );
350 mLegend->setSymbolAlignment( alignment );
352 mLegend->endCommand();
356 void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged(
int c )
361 mLegend->setColumnCount(
c );
362 mLegend->adjustBoxSize();
364 mLegend->endCommand();
366 mSplitLayerCheckBox->setEnabled(
c > 1 );
367 mEqualColumnWidthCheckBox->setEnabled(
c > 1 );
370 void QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled(
bool checked )
374 mLegend->beginCommand( tr(
"Split Legend Layers" ) );
375 mLegend->setSplitLayer( checked );
376 mLegend->adjustBoxSize();
378 mLegend->endCommand();
382 void QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled(
bool checked )
386 mLegend->beginCommand( tr(
"Legend Column Width" ) );
387 mLegend->setEqualColumnWidth( checked );
388 mLegend->adjustBoxSize();
390 mLegend->endCommand();
394 void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged(
double d )
399 mLegend->setSymbolWidth( d );
400 mLegend->adjustBoxSize();
402 mLegend->endCommand();
406 void QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged(
double d )
411 mLegend->setSymbolHeight( d );
412 mLegend->adjustBoxSize();
414 mLegend->endCommand();
418 void QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged(
double d )
423 mLegend->setWmsLegendWidth( d );
424 mLegend->adjustBoxSize();
426 mLegend->endCommand();
430 void QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged(
double d )
435 mLegend->setWmsLegendHeight( d );
436 mLegend->adjustBoxSize();
438 mLegend->endCommand();
442 void QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged(
double d )
448 mLegend->adjustBoxSize();
450 mLegend->endCommand();
454 void QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged(
double d )
460 mLegend->adjustBoxSize();
462 mLegend->endCommand();
466 void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged(
double space )
472 mLegend->adjustBoxSize();
474 mLegend->endCommand();
478 void QgsLayoutLegendWidget::spaceGroupSideChanged(
double space )
484 mLegend->adjustBoxSize();
486 mLegend->endCommand();
490 void QgsLayoutLegendWidget::spaceSubGroupSideChanged(
double space )
496 mLegend->adjustBoxSize();
498 mLegend->endCommand();
502 void QgsLayoutLegendWidget::spaceSymbolSideChanged(
double space )
508 mLegend->adjustBoxSize();
510 mLegend->endCommand();
514 void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged(
double d )
520 mLegend->adjustBoxSize();
522 mLegend->endCommand();
526 void QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged(
double d )
534 mLegend->adjustBoxSize();
536 mLegend->endCommand();
540 void QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged(
double d )
546 mLegend->adjustBoxSize();
548 mLegend->endCommand();
552 void QgsLayoutLegendWidget::titleFontChanged()
558 mLegend->adjustBoxSize();
560 mLegend->endCommand();
564 void QgsLayoutLegendWidget::groupFontChanged()
570 mLegend->adjustBoxSize();
572 mLegend->endCommand();
576 void QgsLayoutLegendWidget::layerFontChanged()
582 mLegend->adjustBoxSize();
584 mLegend->endCommand();
588 void QgsLayoutLegendWidget::itemFontChanged()
594 mLegend->adjustBoxSize();
596 mLegend->endCommand();
600 void QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged(
double space )
606 mLegend->adjustBoxSize();
608 mLegend->endCommand();
612 void QgsLayoutLegendWidget::mFontColorButton_colorChanged(
const QColor &newFontColor )
620 mLegend->setFontColor( newFontColor );
622 mLegend->endCommand();
625 void QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged(
double d )
630 mLegend->setBoxSpace( d );
631 mLegend->adjustBoxSize();
633 mLegend->endCommand();
637 void QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged(
double d )
642 mLegend->setColumnSpace( d );
643 mLegend->adjustBoxSize();
645 mLegend->endCommand();
649 void QgsLayoutLegendWidget::mLineSpacingSpinBox_valueChanged(
double d )
654 mLegend->setLineSpacing( d );
655 mLegend->adjustBoxSize();
657 mLegend->endCommand();
661 static void _moveLegendNode(
QgsLayerTreeLayer *nodeLayer,
int legendNodeIndex,
int offset )
665 if ( legendNodeIndex < 0 || legendNodeIndex >= order.count() )
667 if ( legendNodeIndex + offset < 0 || legendNodeIndex + offset >= order.count() )
670 int id = order.takeAt( legendNodeIndex );
671 order.insert( legendNodeIndex + offset,
id );
677 void QgsLayoutLegendWidget::mMoveDownToolButton_clicked()
684 QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
685 QModelIndex parentIndex = index.parent();
686 if ( !index.isValid() || index.row() == mItemTreeView->model()->rowCount( parentIndex ) - 1 )
689 QgsLayerTreeNode *node = mItemTreeView->layerTreeModel()->index2node( index );
694 mLegend->beginCommand( tr(
"Moved Legend Item Down" ) );
708 mItemTreeView->setCurrentIndex( mItemTreeView->layerTreeModel()->index( index.row() + 1, 0, parentIndex ) );
711 mLegend->endCommand();
714 void QgsLayoutLegendWidget::mMoveUpToolButton_clicked()
721 QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
722 QModelIndex parentIndex = index.parent();
723 if ( !index.isValid() || index.row() == 0 )
726 QgsLayerTreeNode *node = mItemTreeView->layerTreeModel()->index2node( index );
731 mLegend->beginCommand( tr(
"Move Legend Item Up" ) );
745 mItemTreeView->setCurrentIndex( mItemTreeView->layerTreeModel()->index( index.row() - 1, 0, parentIndex ) );
748 mLegend->endCommand();
751 void QgsLayoutLegendWidget::mCheckBoxAutoUpdate_stateChanged(
int state,
bool userTriggered )
755 mLegend->beginCommand( tr(
"Change Auto Update" ) );
757 mLegend->setAutoUpdateModel( state == Qt::Checked );
759 mLegend->updateFilterByMap();
760 mLegend->endCommand();
764 QList<QWidget *> widgets;
765 widgets << mMoveDownToolButton << mMoveUpToolButton << mRemoveToolButton << mAddToolButton
766 << mEditPushButton << mCountToolButton << mUpdateAllPushButton << mAddGroupToolButton
767 << mExpressionFilterButton;
768 for ( QWidget *w : qgis::as_const( widgets ) )
769 w->setEnabled( state != Qt::Checked );
771 if ( state == Qt::Unchecked )
774 selectedChanged( QModelIndex(), QModelIndex() );
778 void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
794 mLegend->beginCommand( tr(
"Change Legend Map" ) );
795 mLegend->setLinkedMap( map );
796 mLegend->updateFilterByMap();
797 mLegend->endCommand();
799 setLegendMapViewData();
803 void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
810 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
811 mLegend->setResizeToContents( checked );
813 mLegend->adjustBoxSize();
814 mLegend->updateFilterByMap();
815 mLegend->endCommand();
818 void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
825 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
826 mLegend->setDrawRasterStroke( state );
827 mLegend->adjustBoxSize();
829 mLegend->endCommand();
832 void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
840 mLegend->setRasterStrokeWidth( d );
841 mLegend->adjustBoxSize();
843 mLegend->endCommand();
846 void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
854 mLegend->setRasterStrokeColor( newColor );
856 mLegend->endCommand();
859 void QgsLayoutLegendWidget::mAddToolButton_clicked()
866 QList< QgsMapLayer * > visibleLayers;
867 if ( mLegend->linkedMap() )
869 visibleLayers = mLegend->linkedMap()->layersToRender();
871 if ( visibleLayers.isEmpty() )
874 visibleLayers = mMapCanvas->layers();
878 addDialog.setVisibleLayers( visibleLayers );
879 if ( addDialog.exec() == QDialog::Accepted )
881 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
882 if ( !layers.empty() )
884 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
887 mLegend->model()->rootGroup()->addLayer( layer );
889 mLegend->updateLegend();
891 mLegend->endCommand();
896 void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
903 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
904 if ( !selectionModel )
909 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
911 QList<QPersistentModelIndex> indexes;
912 const auto constSelectedIndexes = selectionModel->selectedIndexes();
913 for (
const QModelIndex &index : constSelectedIndexes )
917 QHash<QgsLayerTreeLayer *, QList<int> > nodesWithRemoval;
918 for (
const QPersistentModelIndex &index : qgis::as_const( indexes ) )
923 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex(
legendNode ) );
926 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
928 QList<int> toDelete = it.value();
929 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
932 const auto constToDelete = toDelete;
933 for (
int i : constToDelete )
935 if ( i >= 0 && i < order.count() )
940 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
944 for (
const QPersistentModelIndex &index : qgis::as_const( indexes ) )
946 if ( index.isValid() && mItemTreeView->layerTreeModel()->index2node( index ) )
947 mLegend->model()->removeRow( index.row(), index.parent() );
950 mLegend->updateLegend();
952 mLegend->endCommand();
955 void QgsLayoutLegendWidget::mEditPushButton_clicked()
962 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
963 mItemTreeView_doubleClicked( idx );
966 void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
974 QModelIndex currentIndex = mItemTreeView->currentIndex();
975 if ( !currentIndex.isValid() )
981 if (
QgsLayerTreeNode *node = mItemTreeView->layerTreeModel()->index2node( currentIndex ) )
994 mLegend->beginCommand( tr(
"Update Legend" ) );
997 for (
const QString &key : constCustomProperties )
999 if ( key.startsWith( QLatin1String(
"legend/" ) ) )
1006 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1008 mLegend->updateLegend();
1010 mLegend->endCommand();
1013 void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1020 const QList< QModelIndex > selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1021 if ( selectedIndexes.empty() )
1024 mLegend->beginCommand( tr(
"Update Legend" ) );
1025 for (
const QModelIndex &index : selectedIndexes )
1027 QgsLayerTreeNode *currentNode = mItemTreeView->layerTreeModel()->index2node( index );
1031 currentNode->
setCustomProperty( QStringLiteral(
"showFeatureCount" ), checked ? 1 : 0 );
1033 mLegend->updateFilterByMap();
1034 mLegend->adjustBoxSize();
1035 mLegend->endCommand();
1038 void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1040 mLegend->beginCommand( tr(
"Update Legend" ) );
1041 mLegend->setLegendFilterByMapEnabled( checked );
1042 mLegend->adjustBoxSize();
1044 mLegend->endCommand();
1047 void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1055 QModelIndex currentIndex = mItemTreeView->currentIndex();
1056 if ( !currentIndex.isValid() )
1066 mExpressionFilterButton->expressionText(),
1069 mLegend->beginCommand( tr(
"Update Legend" ) );
1070 mLegend->updateFilterByMap();
1071 mLegend->adjustBoxSize();
1072 mLegend->endCommand();
1075 void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1082 QModelIndex currentIndex = mItemTreeView->currentIndex();
1083 if ( !currentIndex.isValid() )
1090 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1096 QString currentExpression;
1098 currentExpression = QStringLiteral(
"@symbol_label" );
1108 QStringList highlighted;
1113 if ( !legendSymbols.empty() )
1119 highlighted << QStringLiteral(
"symbol_label" ) << QStringLiteral(
"symbol_id" );
1121 highlighted << QStringLiteral(
"symbol_count" );
1130 if ( expressiondialog.exec() )
1133 mLegend->beginCommand( tr(
"Update Legend" ) );
1135 mLegend->adjustBoxSize();
1136 mLegend->endCommand();
1139 void QgsLayoutLegendWidget::mUpdateAllPushButton_clicked()
1144 void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1148 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1149 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1150 mLegend->updateLegend();
1152 mLegend->endCommand();
1156 void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1161 mLegend->setLegendFilterOutAtlas( toggled );
1167 void QgsLayoutLegendWidget::updateLegend()
1171 mLegend->beginCommand( tr(
"Update Legend" ) );
1174 mLegend->setAutoUpdateModel(
true );
1175 mLegend->setAutoUpdateModel(
false );
1176 mLegend->updateFilterByMap();
1177 mLegend->endCommand();
1181 void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1183 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1184 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1187 bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1197 mLegend = qobject_cast< QgsLayoutItemLegend * >( item );
1198 mItemPropertiesWidget->setItem( mLegend );
1202 mItemTreeView->setModel( mLegend->model() );
1211 void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1213 mTitleLineEdit->blockSignals( b );
1214 mTitleAlignCombo->blockSignals( b );
1215 mItemTreeView->blockSignals( b );
1216 mCheckBoxAutoUpdate->blockSignals( b );
1217 mMapComboBox->blockSignals( b );
1218 mFilterByMapCheckBox->blockSignals( b );
1219 mColumnCountSpinBox->blockSignals( b );
1220 mSplitLayerCheckBox->blockSignals( b );
1221 mEqualColumnWidthCheckBox->blockSignals( b );
1222 mSymbolWidthSpinBox->blockSignals( b );
1223 mSymbolHeightSpinBox->blockSignals( b );
1224 mGroupSpaceSpinBox->blockSignals( b );
1225 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1226 mGroupSideSpinBox->blockSignals( b );
1227 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1228 mSubgroupSideSpinBox->blockSignals( b );
1229 mLayerSpaceSpinBox->blockSignals( b );
1230 mSymbolSpaceSpinBox->blockSignals( b );
1231 mSymbolSideSpaceSpinBox->blockSignals( b );
1232 mIconLabelSpaceSpinBox->blockSignals( b );
1233 mBoxSpaceSpinBox->blockSignals( b );
1234 mColumnSpaceSpinBox->blockSignals( b );
1235 mFontColorButton->blockSignals( b );
1236 mRasterStrokeGroupBox->blockSignals( b );
1237 mRasterStrokeColorButton->blockSignals( b );
1238 mRasterStrokeWidthSpinBox->blockSignals( b );
1239 mWmsLegendWidthSpinBox->blockSignals( b );
1240 mWmsLegendHeightSpinBox->blockSignals( b );
1241 mCheckboxResizeContents->blockSignals( b );
1242 mTitleSpaceBottomSpinBox->blockSignals( b );
1243 mFilterLegendByAtlasCheckBox->blockSignals( b );
1244 mTitleFontButton->blockSignals( b );
1245 mGroupFontButton->blockSignals( b );
1246 mLayerFontButton->blockSignals( b );
1247 mItemFontButton->blockSignals( b );
1248 mWrapCharLineEdit->blockSignals( b );
1249 mLineSpacingSpinBox->blockSignals( b );
1252 void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1255 Q_UNUSED( previous )
1257 mLayerExpressionButton->setEnabled(
false );
1259 if ( mLegend && mLegend->autoUpdateModel() )
1270 mLayerExpressionButton->setEnabled(
true );
1274 mCountToolButton->setChecked(
false );
1275 mCountToolButton->setEnabled(
false );
1278 mExpressionFilterButton->blockSignals(
true );
1279 mExpressionFilterButton->setChecked(
false );
1280 mExpressionFilterButton->setEnabled(
false );
1281 mExpressionFilterButton->blockSignals(
false );
1292 mCountToolButton->setChecked( currentNode->
customProperty( QStringLiteral(
"showFeatureCount" ), 0 ).toInt() );
1293 mCountToolButton->setEnabled(
true );
1294 mLayerExpressionButton->setEnabled(
true );
1298 mExpressionFilterButton->blockSignals(
true );
1299 mExpressionFilterButton->setExpressionText( expr );
1300 mExpressionFilterButton->setVectorLayer( vl );
1301 mExpressionFilterButton->setEnabled(
true );
1302 mExpressionFilterButton->setChecked( exprEnabled );
1303 mExpressionFilterButton->blockSignals(
false );
1306 void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1308 QAction *a = qobject_cast<QAction *>( sender() );
1309 if ( !a || !mItemTreeView->currentNode() )
1313 mLegend->updateFilterByMap();
1316 void QgsLayoutLegendWidget::setLegendMapViewData()
1318 if ( mLegend->linkedMap() )
1322 measurementConverter.
setDpi( dpi );
1325 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1326 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1327 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1331 void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1335 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
QgsWkbTypes::PolygonGeometry );
1339 void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1341 if ( !mLegend || !idx.isValid() )
1346 if ( mLegend->autoUpdateModel() )
1353 int originalIndex = -1;
1356 originalIndex = _originalLegendNodeIndex(
legendNode );
1360 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode,
legendNode, originalIndex );
1361 openPanel( widget );
1369 QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1374 QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1376 if ( !mView->currentNode() )
1379 if ( mWidget->legend()->autoUpdateModel() )
1382 QMenu *menu =
new QMenu();
1386 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1387 menu->addSeparator();
1392 QList<QgsLegendStyle::Style> lst;
1396 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1397 action->setCheckable(
true );
1398 action->setChecked( currentStyle == style );
1399 action->setData(
static_cast< int >( style ) );
1414 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1417 setPanelTitle( tr(
"Legend Item Properties" ) );
1426 QString currentLabel;
1429 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1430 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1434 currentLabel = mLayer->name();
1435 QVariant v = mLayer->customProperty( QStringLiteral(
"legend/title-label" ) );
1437 currentLabel = v.toString();
1438 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1440 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1445 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1448 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1449 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1450 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1451 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1452 mPatchGroup->setVisible( mLegendNode || mLayer );
1453 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1454 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1455 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1456 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1457 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1460 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1461 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1465 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1466 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1469 mCustomSymbolCheckBox->setChecked(
false );
1474 patchShape = symbolLegendNode->patchShape();
1476 std::unique_ptr< QgsSymbol > customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() :
nullptr );
1477 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1480 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1481 mCustomSymbolButton->setSymbolType( customSymbol->type() );
1482 mCustomSymbolButton->setSymbol( customSymbol.release() );
1484 else if ( symbolLegendNode->symbol() )
1486 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1487 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1488 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1491 else if ( !mLegendNode && mLayer )
1493 patchShape = mLayer->patchShape();
1496 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1498 mCustomSymbolCheckBox->setChecked(
true );
1499 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1501 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1505 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1506 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1507 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1514 switch ( qobject_cast< QgsVectorLayer * >( mLayer->layer() )->geometryType() )
1529 mPatchShapeLabel->hide();
1530 mPatchShapeButton->hide();
1533 if ( !patchShape.
isNull() )
1534 mPatchShapeButton->setShape( patchShape );
1539 mPatchShapeLabel->hide();
1540 mPatchShapeButton->hide();
1543 mLabelEdit->setPlainText( currentLabel );
1544 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1546 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1548 connect( mWidthSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1549 connect( mHeightSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1551 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1554 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1556 connect( mColumnSplitBehaviorComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1559 void QgsLayoutLegendNodeWidget::labelChanged()
1563 const QString label = mLabelEdit->toPlainText();
1568 else if ( mLegendNode )
1571 mLegend->model()->refreshLayerLegend( mLayer );
1575 mLayer->setCustomProperty( QStringLiteral(
"legend/title-label" ), label );
1579 embeddedNode->setUserLabel( QString() );
1582 mLegend->adjustBoxSize();
1583 mLegend->updateFilterByMap();
1584 mLegend->endCommand();
1587 void QgsLayoutLegendNodeWidget::patchChanged()
1589 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1595 mLegend->model()->refreshLayerLegend( mLayer );
1599 mLayer->setPatchShape( shape );
1600 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1605 mLegend->model()->refreshLayerLegend( mLayer );
1608 mLegend->adjustBoxSize();
1609 mLegend->updateFilterByMap();
1610 mLegend->endCommand();
1613 void QgsLayoutLegendNodeWidget::insertExpression()
1618 QString selText = mLabelEdit->textCursor().selectedText();
1621 selText = selText.replace( QChar( 0x2029 ), QChar(
'\n' ) );
1624 if ( selText.startsWith( QLatin1String(
"[%" ) ) && selText.endsWith( QLatin1String(
"%]" ) ) )
1625 selText = selText.mid( 2, selText.size() - 4 );
1628 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1632 if ( mLayer && mLayer->layer() )
1638 << QStringLiteral(
"legend_column_count" )
1639 << QStringLiteral(
"legend_split_layers" )
1640 << QStringLiteral(
"legend_wrap_string" )
1641 << QStringLiteral(
"legend_filter_by_map" )
1642 << QStringLiteral(
"legend_filter_out_atlas" ) );
1646 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1647 if ( exprDlg.exec() == QDialog::Accepted )
1649 QString expression = exprDlg.expressionText();
1650 if ( !expression.isEmpty() )
1652 mLegend->beginCommand( tr(
"Insert expression" ) );
1653 mLabelEdit->insertPlainText(
"[%" + expression +
"%]" );
1654 mLegend->endCommand();
1659 void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1661 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1662 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1667 mLegend->model()->refreshLayerLegend( mLayer );
1671 mLayer->setPatchSize( size );
1672 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1677 mLegend->model()->refreshLayerLegend( mLayer );
1680 mLegend->adjustBoxSize();
1681 mLegend->updateFilterByMap();
1682 mLegend->endCommand();
1685 void QgsLayoutLegendNodeWidget::customSymbolChanged()
1687 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1689 if ( mCustomSymbolCheckBox->isChecked() )
1694 mLegend->model()->refreshLayerLegend( mLayer );
1698 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1703 mLegend->model()->refreshLayerLegend( mLayer );
1711 mLegend->model()->refreshLayerLegend( mLayer );
1715 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1720 mLegend->model()->refreshLayerLegend( mLayer );
1724 mLegend->adjustBoxSize();
1725 mLegend->updateFilterByMap();
1726 mLegend->endCommand();
1729 void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1731 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1736 mLegend->model()->refreshLayerLegend( mLayer );
1740 mLayer->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1744 mNode->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1747 mLegend->adjustBoxSize();
1748 mLegend->updateFilterByMap();
1749 mLegend->endCommand();
1752 void QgsLayoutLegendNodeWidget::columnSplitChanged()
1754 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1756 if ( mLayer && !mLegendNode )
1761 mLegend->adjustBoxSize();
1762 mLegend->updateFilterByMap();
1763 mLegend->endCommand();