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( mMaxSymbolSizeSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged );
90 connect( mMinSymbolSizeSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged );
91 connect( mWmsLegendWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged );
92 connect( mWmsLegendHeightSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged );
93 connect( mTitleSpaceBottomSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged );
94 connect( mGroupSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged );
95 connect( mSpaceBelowGroupHeadingSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged );
96 connect( mGroupSideSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceGroupSideChanged );
97 connect( mLayerSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged );
98 connect( mSpaceBelowSubgroupHeadingSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged );
99 connect( mSubgroupSideSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSubGroupSideChanged );
100 connect( mSymbolSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged );
101 connect( mSymbolSideSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::spaceSymbolSideChanged );
102 connect( mIconLabelSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged );
104 connect( mBoxSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged );
105 connect( mColumnSpaceSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged );
106 connect( mLineSpacingSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mLineSpacingSpinBox_valueChanged );
107 connect( mCheckBoxAutoUpdate, &QCheckBox::stateChanged,
this, [ = ](
int state ) { mCheckBoxAutoUpdate_stateChanged( state ); } );
108 connect( mCheckboxResizeContents, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mCheckboxResizeContents_toggled );
109 connect( mRasterStrokeGroupBox, &QgsCollapsibleGroupBoxBasic::toggled,
this, &QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled );
110 connect( mRasterStrokeWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged );
111 connect( mRasterStrokeColorButton, &
QgsColorButton::colorChanged,
this, &QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged );
112 connect( mMoveDownToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveDownToolButton_clicked );
113 connect( mMoveUpToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mMoveUpToolButton_clicked );
114 connect( mRemoveToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mRemoveToolButton_clicked );
115 connect( mAddToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddToolButton_clicked );
116 connect( mEditPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mEditPushButton_clicked );
117 connect( mCountToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mCountToolButton_clicked );
118 connect( mExpressionFilterButton, &QgsLegendFilterButton::toggled,
this, &QgsLayoutLegendWidget::mExpressionFilterButton_toggled );
119 connect( mLayerExpressionButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mLayerExpressionButton_clicked );
120 connect( mFilterByMapCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled );
121 connect( mUpdateAllPushButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mUpdateAllPushButton_clicked );
122 connect( mAddGroupToolButton, &QToolButton::clicked,
this, &QgsLayoutLegendWidget::mAddGroupToolButton_clicked );
123 connect( mFilterLegendByAtlasCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled );
124 connect( mItemTreeView, &QgsLayerTreeView::doubleClicked,
this, &QgsLayoutLegendWidget::mItemTreeView_doubleClicked );
125 setPanelTitle( tr(
"Legend Properties" ) );
132 mTitleAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
133 mGroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
134 mSubgroupAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
135 mItemAlignCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
137 mArrangementCombo->setAvailableAlignments( Qt::AlignLeft | Qt::AlignRight );
139 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignLeft, tr(
"Symbols on Left" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsLeft.svg" ) ) );
140 mArrangementCombo->customizeAlignmentDisplay( Qt::AlignRight, tr(
"Symbols on Right" ),
QgsApplication::getThemeIcon( QStringLiteral(
"/mIconArrangeSymbolsRight.svg" ) ) );
142 mSpaceBelowGroupHeadingSpinBox->setClearValue( 0 );
143 mGroupSideSpinBox->setClearValue( 0 );
144 mSpaceBelowSubgroupHeadingSpinBox->setClearValue( 0 );
145 mSubgroupSideSpinBox->setClearValue( 0 );
146 mSymbolSideSpaceSpinBox->setClearValue( 0 );
167 mFontColorButton->setColorDialogTitle( tr(
"Select Font Color" ) );
168 mFontColorButton->setContext( QStringLiteral(
"composer" ) );
170 mRasterStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
171 mRasterStrokeColorButton->setAllowOpacity(
true );
172 mRasterStrokeColorButton->setContext( QStringLiteral(
"composer " ) );
174 mMapComboBox->setCurrentLayout( legend->
layout() );
180 mainLayout->addWidget( mItemPropertiesWidget );
182 mItemTreeView->setHeaderHidden(
true );
184 mItemTreeView->setModel( legend->
model() );
185 mItemTreeView->setMenuProvider(
new QgsLayoutLegendMenuProvider( mItemTreeView,
this ) );
186 setLegendMapViewData();
192 connect( layoutAtlas(), &
QgsLayoutAtlas::toggled,
this, &QgsLayoutLegendWidget::updateFilterLegendByAtlasButton );
201 connect( mItemTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
202 this, &QgsLayoutLegendWidget::selectedChanged );
211 if ( mItemPropertiesWidget )
212 mItemPropertiesWidget->setMasterLayout( masterLayout );
215 void QgsLayoutLegendWidget::setGuiElements()
222 blockAllSignals(
true );
223 mTitleLineEdit->setText( mLegend->title() );
224 whileBlocking( mTitleAlignCombo )->setCurrentAlignment( mLegend->titleAlignment() );
228 whileBlocking( mArrangementCombo )->setCurrentAlignment( mLegend->symbolAlignment() );
229 mFilterByMapCheckBox->setChecked( mLegend->legendFilterByMapEnabled() );
230 mColumnCountSpinBox->setValue( mLegend->columnCount() );
231 mSplitLayerCheckBox->setChecked( mLegend->splitLayer() );
232 mEqualColumnWidthCheckBox->setChecked( mLegend->equalColumnWidth() );
233 mSymbolWidthSpinBox->setValue( mLegend->symbolWidth() );
234 mSymbolHeightSpinBox->setValue( mLegend->symbolHeight() );
235 mMaxSymbolSizeSpinBox->setValue( mLegend->maximumSymbolSize() );
236 mMinSymbolSizeSpinBox->setValue( mLegend->minimumSymbolSize() );
237 mWmsLegendWidthSpinBox->setValue( mLegend->wmsLegendWidth() );
238 mWmsLegendHeightSpinBox->setValue( mLegend->wmsLegendHeight() );
250 mBoxSpaceSpinBox->setValue( mLegend->boxSpace() );
251 mColumnSpaceSpinBox->setValue( mLegend->columnSpace() );
252 mLineSpacingSpinBox->setValue( mLegend->lineSpacing() );
254 mRasterStrokeGroupBox->setChecked( mLegend->drawRasterStroke() );
255 mRasterStrokeWidthSpinBox->setValue( mLegend->rasterStrokeWidth() );
256 mRasterStrokeColorButton->setColor( mLegend->rasterStrokeColor() );
258 mCheckBoxAutoUpdate->setChecked( mLegend->autoUpdateModel() );
260 mCheckboxResizeContents->setChecked( mLegend->resizeToContents() );
261 mFilterLegendByAtlasCheckBox->setChecked( mLegend->legendFilterOutAtlas() );
262 mWrapCharLineEdit->setText( mLegend->wrapString() );
265 mMapComboBox->setItem( map );
266 mFontColorButton->setColor( mLegend->fontColor() );
272 blockAllSignals(
false );
274 mCheckBoxAutoUpdate_stateChanged( mLegend->autoUpdateModel() ? Qt::Checked : Qt::Unchecked,
false );
275 updateDataDefinedButton( mLegendTitleDDBtn );
276 updateDataDefinedButton( mColumnsDDBtn );
279 void QgsLayoutLegendWidget::mWrapCharLineEdit_textChanged(
const QString &text )
283 mLegend->beginCommand( tr(
"Change Legend Wrap" ) );
284 mLegend->setWrapString( text );
285 mLegend->adjustBoxSize();
287 mLegend->endCommand();
291 void QgsLayoutLegendWidget::mTitleLineEdit_textChanged(
const QString &text )
296 mLegend->setTitle( text );
297 mLegend->adjustBoxSize();
299 mLegend->endCommand();
303 void QgsLayoutLegendWidget::titleAlignmentChanged()
307 Qt::AlignmentFlag alignment =
static_cast< Qt::AlignmentFlag
>(
static_cast< int >( mTitleAlignCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
308 mLegend->beginCommand( tr(
"Change Title Alignment" ) );
309 mLegend->setTitleAlignment( alignment );
311 mLegend->endCommand();
315 void QgsLayoutLegendWidget::groupAlignmentChanged()
319 mLegend->beginCommand( tr(
"Change Group Alignment" ) );
322 mLegend->endCommand();
326 void QgsLayoutLegendWidget::subgroupAlignmentChanged()
330 mLegend->beginCommand( tr(
"Change Subgroup Alignment" ) );
333 mLegend->endCommand();
337 void QgsLayoutLegendWidget::itemAlignmentChanged()
341 mLegend->beginCommand( tr(
"Change Item Alignment" ) );
344 mLegend->endCommand();
348 void QgsLayoutLegendWidget::arrangementChanged()
352 Qt::AlignmentFlag alignment =
static_cast< Qt::AlignmentFlag
>(
static_cast< int >( mArrangementCombo->currentAlignment() & Qt::AlignHorizontal_Mask ) );
353 mLegend->beginCommand( tr(
"Change Legend Arrangement" ) );
354 mLegend->setSymbolAlignment( alignment );
356 mLegend->endCommand();
360 void QgsLayoutLegendWidget::mColumnCountSpinBox_valueChanged(
int c )
365 mLegend->setColumnCount(
c );
366 mLegend->adjustBoxSize();
368 mLegend->endCommand();
370 mSplitLayerCheckBox->setEnabled(
c > 1 );
371 mEqualColumnWidthCheckBox->setEnabled(
c > 1 );
374 void QgsLayoutLegendWidget::mSplitLayerCheckBox_toggled(
bool checked )
378 mLegend->beginCommand( tr(
"Split Legend Layers" ) );
379 mLegend->setSplitLayer( checked );
380 mLegend->adjustBoxSize();
382 mLegend->endCommand();
386 void QgsLayoutLegendWidget::mEqualColumnWidthCheckBox_toggled(
bool checked )
390 mLegend->beginCommand( tr(
"Legend Column Width" ) );
391 mLegend->setEqualColumnWidth( checked );
392 mLegend->adjustBoxSize();
394 mLegend->endCommand();
398 void QgsLayoutLegendWidget::mSymbolWidthSpinBox_valueChanged(
double d )
403 mLegend->setSymbolWidth( d );
404 mLegend->adjustBoxSize();
406 mLegend->endCommand();
410 void QgsLayoutLegendWidget::mMaxSymbolSizeSpinBox_valueChanged(
double d )
415 mLegend->setMaximumSymbolSize( d );
416 mLegend->adjustBoxSize();
418 mLegend->endCommand();
422 void QgsLayoutLegendWidget::mMinSymbolSizeSpinBox_valueChanged(
double d )
427 mLegend->setMinimumSymbolSize( d );
428 mLegend->adjustBoxSize();
430 mLegend->endCommand();
434 void QgsLayoutLegendWidget::mSymbolHeightSpinBox_valueChanged(
double d )
439 mLegend->setSymbolHeight( d );
440 mLegend->adjustBoxSize();
442 mLegend->endCommand();
446 void QgsLayoutLegendWidget::mWmsLegendWidthSpinBox_valueChanged(
double d )
451 mLegend->setWmsLegendWidth( d );
452 mLegend->adjustBoxSize();
454 mLegend->endCommand();
458 void QgsLayoutLegendWidget::mWmsLegendHeightSpinBox_valueChanged(
double d )
463 mLegend->setWmsLegendHeight( d );
464 mLegend->adjustBoxSize();
466 mLegend->endCommand();
470 void QgsLayoutLegendWidget::mTitleSpaceBottomSpinBox_valueChanged(
double d )
476 mLegend->adjustBoxSize();
478 mLegend->endCommand();
482 void QgsLayoutLegendWidget::mGroupSpaceSpinBox_valueChanged(
double d )
488 mLegend->adjustBoxSize();
490 mLegend->endCommand();
494 void QgsLayoutLegendWidget::spaceBelowGroupHeadingChanged(
double space )
500 mLegend->adjustBoxSize();
502 mLegend->endCommand();
506 void QgsLayoutLegendWidget::spaceGroupSideChanged(
double space )
512 mLegend->adjustBoxSize();
514 mLegend->endCommand();
518 void QgsLayoutLegendWidget::spaceSubGroupSideChanged(
double space )
524 mLegend->adjustBoxSize();
526 mLegend->endCommand();
530 void QgsLayoutLegendWidget::spaceSymbolSideChanged(
double space )
536 mLegend->adjustBoxSize();
538 mLegend->endCommand();
542 void QgsLayoutLegendWidget::mLayerSpaceSpinBox_valueChanged(
double d )
548 mLegend->adjustBoxSize();
550 mLegend->endCommand();
554 void QgsLayoutLegendWidget::mSymbolSpaceSpinBox_valueChanged(
double d )
562 mLegend->adjustBoxSize();
564 mLegend->endCommand();
568 void QgsLayoutLegendWidget::mIconLabelSpaceSpinBox_valueChanged(
double d )
574 mLegend->adjustBoxSize();
576 mLegend->endCommand();
580 void QgsLayoutLegendWidget::titleFontChanged()
586 mLegend->adjustBoxSize();
588 mLegend->endCommand();
592 void QgsLayoutLegendWidget::groupFontChanged()
598 mLegend->adjustBoxSize();
600 mLegend->endCommand();
604 void QgsLayoutLegendWidget::layerFontChanged()
610 mLegend->adjustBoxSize();
612 mLegend->endCommand();
616 void QgsLayoutLegendWidget::itemFontChanged()
622 mLegend->adjustBoxSize();
624 mLegend->endCommand();
628 void QgsLayoutLegendWidget::spaceBelowSubGroupHeadingChanged(
double space )
634 mLegend->adjustBoxSize();
636 mLegend->endCommand();
640 void QgsLayoutLegendWidget::mFontColorButton_colorChanged(
const QColor &newFontColor )
648 mLegend->setFontColor( newFontColor );
650 mLegend->endCommand();
653 void QgsLayoutLegendWidget::mBoxSpaceSpinBox_valueChanged(
double d )
658 mLegend->setBoxSpace( d );
659 mLegend->adjustBoxSize();
661 mLegend->endCommand();
665 void QgsLayoutLegendWidget::mColumnSpaceSpinBox_valueChanged(
double d )
670 mLegend->setColumnSpace( d );
671 mLegend->adjustBoxSize();
673 mLegend->endCommand();
677 void QgsLayoutLegendWidget::mLineSpacingSpinBox_valueChanged(
double d )
682 mLegend->setLineSpacing( d );
683 mLegend->adjustBoxSize();
685 mLegend->endCommand();
689 static void _moveLegendNode(
QgsLayerTreeLayer *nodeLayer,
int legendNodeIndex,
int offset )
693 if ( legendNodeIndex < 0 || legendNodeIndex >= order.count() )
695 if ( legendNodeIndex + offset < 0 || legendNodeIndex + offset >= order.count() )
698 int id = order.takeAt( legendNodeIndex );
699 order.insert( legendNodeIndex + offset,
id );
705 void QgsLayoutLegendWidget::mMoveDownToolButton_clicked()
712 QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
713 QModelIndex parentIndex = index.parent();
714 if ( !index.isValid() || index.row() == mItemTreeView->model()->rowCount( parentIndex ) - 1 )
717 QgsLayerTreeNode *node = mItemTreeView->layerTreeModel()->index2node( index );
722 mLegend->beginCommand( tr(
"Moved Legend Item Down" ) );
736 mItemTreeView->setCurrentIndex( mItemTreeView->layerTreeModel()->index( index.row() + 1, 0, parentIndex ) );
739 mLegend->endCommand();
742 void QgsLayoutLegendWidget::mMoveUpToolButton_clicked()
749 QModelIndex index = mItemTreeView->selectionModel()->currentIndex();
750 QModelIndex parentIndex = index.parent();
751 if ( !index.isValid() || index.row() == 0 )
754 QgsLayerTreeNode *node = mItemTreeView->layerTreeModel()->index2node( index );
759 mLegend->beginCommand( tr(
"Move Legend Item Up" ) );
773 mItemTreeView->setCurrentIndex( mItemTreeView->layerTreeModel()->index( index.row() - 1, 0, parentIndex ) );
776 mLegend->endCommand();
779 void QgsLayoutLegendWidget::mCheckBoxAutoUpdate_stateChanged(
int state,
bool userTriggered )
783 mLegend->beginCommand( tr(
"Change Auto Update" ) );
785 mLegend->setAutoUpdateModel( state == Qt::Checked );
787 mLegend->updateFilterByMap();
788 mLegend->endCommand();
792 QList<QWidget *> widgets;
793 widgets << mMoveDownToolButton << mMoveUpToolButton << mRemoveToolButton << mAddToolButton
794 << mEditPushButton << mCountToolButton << mUpdateAllPushButton << mAddGroupToolButton
795 << mExpressionFilterButton;
796 for ( QWidget *w : qgis::as_const( widgets ) )
797 w->setEnabled( state != Qt::Checked );
799 if ( state == Qt::Unchecked )
802 selectedChanged( QModelIndex(), QModelIndex() );
806 void QgsLayoutLegendWidget::composerMapChanged(
QgsLayoutItem *item )
822 mLegend->beginCommand( tr(
"Change Legend Map" ) );
823 mLegend->setLinkedMap( map );
824 mLegend->updateFilterByMap();
825 mLegend->endCommand();
827 setLegendMapViewData();
831 void QgsLayoutLegendWidget::mCheckboxResizeContents_toggled(
bool checked )
838 mLegend->beginCommand( tr(
"Resize Legend to Contents" ) );
839 mLegend->setResizeToContents( checked );
841 mLegend->adjustBoxSize();
842 mLegend->updateFilterByMap();
843 mLegend->endCommand();
846 void QgsLayoutLegendWidget::mRasterStrokeGroupBox_toggled(
bool state )
853 mLegend->beginCommand( tr(
"Change Legend Borders" ) );
854 mLegend->setDrawRasterStroke( state );
855 mLegend->adjustBoxSize();
857 mLegend->endCommand();
860 void QgsLayoutLegendWidget::mRasterStrokeWidthSpinBox_valueChanged(
double d )
868 mLegend->setRasterStrokeWidth( d );
869 mLegend->adjustBoxSize();
871 mLegend->endCommand();
874 void QgsLayoutLegendWidget::mRasterStrokeColorButton_colorChanged(
const QColor &newColor )
882 mLegend->setRasterStrokeColor( newColor );
884 mLegend->endCommand();
887 void QgsLayoutLegendWidget::mAddToolButton_clicked()
894 QList< QgsMapLayer * > visibleLayers;
895 if ( mLegend->linkedMap() )
897 visibleLayers = mLegend->linkedMap()->layersToRender();
899 if ( visibleLayers.isEmpty() )
902 visibleLayers = mMapCanvas->layers();
906 addDialog.setVisibleLayers( visibleLayers );
907 if ( addDialog.exec() == QDialog::Accepted )
909 const QList<QgsMapLayer *> layers = addDialog.selectedLayers();
910 if ( !layers.empty() )
912 mLegend->beginCommand( tr(
"Add Legend Item(s)" ) );
915 mLegend->model()->rootGroup()->addLayer( layer );
917 mLegend->updateLegend();
919 mLegend->endCommand();
924 void QgsLayoutLegendWidget::mRemoveToolButton_clicked()
931 QItemSelectionModel *selectionModel = mItemTreeView->selectionModel();
932 if ( !selectionModel )
937 mLegend->beginCommand( tr(
"Remove Legend Item" ) );
939 QList<QPersistentModelIndex> indexes;
940 const auto constSelectedIndexes = selectionModel->selectedIndexes();
941 for (
const QModelIndex &index : constSelectedIndexes )
945 QHash<QgsLayerTreeLayer *, QList<int> > nodesWithRemoval;
946 for (
const QPersistentModelIndex &index : qgis::as_const( indexes ) )
951 nodesWithRemoval[nodeLayer].append( _unfilteredLegendNodeIndex(
legendNode ) );
954 for (
auto it = nodesWithRemoval.constBegin(); it != nodesWithRemoval.constEnd(); ++it )
956 QList<int> toDelete = it.value();
957 std::sort( toDelete.begin(), toDelete.end(), std::greater<int>() );
960 const auto constToDelete = toDelete;
961 for (
int i : constToDelete )
963 if ( i >= 0 && i < order.count() )
968 mItemTreeView->layerTreeModel()->refreshLayerLegend( it.key() );
972 for (
const QPersistentModelIndex &index : qgis::as_const( indexes ) )
974 if ( index.isValid() && mItemTreeView->layerTreeModel()->index2node( index ) )
975 mLegend->model()->removeRow( index.row(), index.parent() );
978 mLegend->updateLegend();
980 mLegend->endCommand();
983 void QgsLayoutLegendWidget::mEditPushButton_clicked()
990 QModelIndex idx = mItemTreeView->selectionModel()->currentIndex();
991 mItemTreeView_doubleClicked( idx );
994 void QgsLayoutLegendWidget::resetLayerNodeToDefaults()
1002 QModelIndex currentIndex = mItemTreeView->currentIndex();
1003 if ( !currentIndex.isValid() )
1009 if (
QgsLayerTreeNode *node = mItemTreeView->layerTreeModel()->index2node( currentIndex ) )
1022 mLegend->beginCommand( tr(
"Update Legend" ) );
1025 for (
const QString &key : constCustomProperties )
1027 if ( key.startsWith( QLatin1String(
"legend/" ) ) )
1034 mItemTreeView->layerTreeModel()->refreshLayerLegend( nodeLayer );
1036 mLegend->updateLegend();
1038 mLegend->endCommand();
1041 void QgsLayoutLegendWidget::mCountToolButton_clicked(
bool checked )
1048 const QList< QModelIndex > selectedIndexes = mItemTreeView->selectionModel()->selectedIndexes();
1049 if ( selectedIndexes.empty() )
1052 mLegend->beginCommand( tr(
"Update Legend" ) );
1053 for (
const QModelIndex &index : selectedIndexes )
1055 QgsLayerTreeNode *currentNode = mItemTreeView->layerTreeModel()->index2node( index );
1059 currentNode->
setCustomProperty( QStringLiteral(
"showFeatureCount" ), checked ? 1 : 0 );
1061 mLegend->updateFilterByMap();
1062 mLegend->adjustBoxSize();
1063 mLegend->endCommand();
1066 void QgsLayoutLegendWidget::mFilterByMapCheckBox_toggled(
bool checked )
1068 mLegend->beginCommand( tr(
"Update Legend" ) );
1069 mLegend->setLegendFilterByMapEnabled( checked );
1070 mLegend->adjustBoxSize();
1072 mLegend->endCommand();
1075 void QgsLayoutLegendWidget::mExpressionFilterButton_toggled(
bool checked )
1083 QModelIndex currentIndex = mItemTreeView->currentIndex();
1084 if ( !currentIndex.isValid() )
1094 mExpressionFilterButton->expressionText(),
1097 mLegend->beginCommand( tr(
"Update Legend" ) );
1098 mLegend->updateFilterByMap();
1099 mLegend->adjustBoxSize();
1100 mLegend->endCommand();
1103 void QgsLayoutLegendWidget::mLayerExpressionButton_clicked()
1110 QModelIndex currentIndex = mItemTreeView->currentIndex();
1111 if ( !currentIndex.isValid() )
1118 QgsLayerTreeLayer *layerNode = qobject_cast<QgsLayerTreeLayer *>( currentNode );
1124 QString currentExpression;
1126 currentExpression = QStringLiteral(
"@symbol_label" );
1136 QStringList highlighted;
1141 if ( !legendSymbols.empty() )
1147 highlighted << QStringLiteral(
"symbol_label" ) << QStringLiteral(
"symbol_id" );
1149 highlighted << QStringLiteral(
"symbol_count" );
1158 if ( expressiondialog.exec() )
1161 mLegend->beginCommand( tr(
"Update Legend" ) );
1163 mLegend->adjustBoxSize();
1164 mLegend->endCommand();
1167 void QgsLayoutLegendWidget::mUpdateAllPushButton_clicked()
1172 void QgsLayoutLegendWidget::mAddGroupToolButton_clicked()
1176 mLegend->beginCommand( tr(
"Add Legend Group" ) );
1177 mLegend->model()->rootGroup()->addGroup( tr(
"Group" ) );
1178 mLegend->updateLegend();
1180 mLegend->endCommand();
1184 void QgsLayoutLegendWidget::mFilterLegendByAtlasCheckBox_toggled(
bool toggled )
1189 mLegend->setLegendFilterOutAtlas( toggled );
1195 void QgsLayoutLegendWidget::updateLegend()
1199 mLegend->beginCommand( tr(
"Update Legend" ) );
1202 mLegend->setAutoUpdateModel(
true );
1203 mLegend->setAutoUpdateModel(
false );
1204 mLegend->updateFilterByMap();
1205 mLegend->endCommand();
1209 void QgsLayoutLegendWidget::setReportTypeString(
const QString &
string )
1211 mFilterLegendByAtlasCheckBox->setText( tr(
"Only show items inside current %1 feature" ).arg(
string ) );
1212 mFilterLegendByAtlasCheckBox->setToolTip( tr(
"Filter out legend elements that lie outside the current %1 feature." ).arg(
string ) );
1215 bool QgsLayoutLegendWidget::setNewItem(
QgsLayoutItem *item )
1225 mLegend = qobject_cast< QgsLayoutItemLegend * >( item );
1226 mItemPropertiesWidget->setItem( mLegend );
1230 mItemTreeView->setModel( mLegend->model() );
1239 void QgsLayoutLegendWidget::blockAllSignals(
bool b )
1241 mTitleLineEdit->blockSignals( b );
1242 mTitleAlignCombo->blockSignals( b );
1243 mItemTreeView->blockSignals( b );
1244 mCheckBoxAutoUpdate->blockSignals( b );
1245 mMapComboBox->blockSignals( b );
1246 mFilterByMapCheckBox->blockSignals( b );
1247 mColumnCountSpinBox->blockSignals( b );
1248 mSplitLayerCheckBox->blockSignals( b );
1249 mEqualColumnWidthCheckBox->blockSignals( b );
1250 mSymbolWidthSpinBox->blockSignals( b );
1251 mSymbolHeightSpinBox->blockSignals( b );
1252 mMaxSymbolSizeSpinBox->blockSignals( b );
1253 mMinSymbolSizeSpinBox->blockSignals( b );
1254 mGroupSpaceSpinBox->blockSignals( b );
1255 mSpaceBelowGroupHeadingSpinBox->blockSignals( b );
1256 mGroupSideSpinBox->blockSignals( b );
1257 mSpaceBelowSubgroupHeadingSpinBox->blockSignals( b );
1258 mSubgroupSideSpinBox->blockSignals( b );
1259 mLayerSpaceSpinBox->blockSignals( b );
1260 mSymbolSpaceSpinBox->blockSignals( b );
1261 mSymbolSideSpaceSpinBox->blockSignals( b );
1262 mIconLabelSpaceSpinBox->blockSignals( b );
1263 mBoxSpaceSpinBox->blockSignals( b );
1264 mColumnSpaceSpinBox->blockSignals( b );
1265 mFontColorButton->blockSignals( b );
1266 mRasterStrokeGroupBox->blockSignals( b );
1267 mRasterStrokeColorButton->blockSignals( b );
1268 mRasterStrokeWidthSpinBox->blockSignals( b );
1269 mWmsLegendWidthSpinBox->blockSignals( b );
1270 mWmsLegendHeightSpinBox->blockSignals( b );
1271 mCheckboxResizeContents->blockSignals( b );
1272 mTitleSpaceBottomSpinBox->blockSignals( b );
1273 mFilterLegendByAtlasCheckBox->blockSignals( b );
1274 mTitleFontButton->blockSignals( b );
1275 mGroupFontButton->blockSignals( b );
1276 mLayerFontButton->blockSignals( b );
1277 mItemFontButton->blockSignals( b );
1278 mWrapCharLineEdit->blockSignals( b );
1279 mLineSpacingSpinBox->blockSignals( b );
1282 void QgsLayoutLegendWidget::selectedChanged(
const QModelIndex ¤t,
const QModelIndex &previous )
1285 Q_UNUSED( previous )
1287 mLayerExpressionButton->setEnabled(
false );
1289 if ( mLegend && mLegend->autoUpdateModel() )
1300 mLayerExpressionButton->setEnabled(
true );
1304 mCountToolButton->setChecked(
false );
1305 mCountToolButton->setEnabled(
false );
1308 mExpressionFilterButton->blockSignals(
true );
1309 mExpressionFilterButton->setChecked(
false );
1310 mExpressionFilterButton->setEnabled(
false );
1311 mExpressionFilterButton->blockSignals(
false );
1322 mCountToolButton->setChecked( currentNode->
customProperty( QStringLiteral(
"showFeatureCount" ), 0 ).toInt() );
1323 mCountToolButton->setEnabled(
true );
1324 mLayerExpressionButton->setEnabled(
true );
1328 mExpressionFilterButton->blockSignals(
true );
1329 mExpressionFilterButton->setExpressionText( expr );
1330 mExpressionFilterButton->setVectorLayer( vl );
1331 mExpressionFilterButton->setEnabled(
true );
1332 mExpressionFilterButton->setChecked( exprEnabled );
1333 mExpressionFilterButton->blockSignals(
false );
1336 void QgsLayoutLegendWidget::setCurrentNodeStyleFromAction()
1338 QAction *a = qobject_cast<QAction *>( sender() );
1339 if ( !a || !mItemTreeView->currentNode() )
1343 mLegend->updateFilterByMap();
1346 void QgsLayoutLegendWidget::setLegendMapViewData()
1348 if ( mLegend->linkedMap() )
1352 measurementConverter.
setDpi( dpi );
1355 double mapUnitsPerPixelX = mLegend->linkedMap()->extent().width() / mapWidth;
1356 double mapUnitsPerPixelY = mLegend->linkedMap()->extent().height() / mapHeight;
1357 mLegend->model()->setLegendMapViewData( ( mapUnitsPerPixelX > mapUnitsPerPixelY ? mapUnitsPerPixelX : mapUnitsPerPixelY ), dpi, mLegend->linkedMap()->scale() );
1361 void QgsLayoutLegendWidget::updateFilterLegendByAtlasButton()
1365 mFilterLegendByAtlasCheckBox->setEnabled( atlas->enabled() && mLegend->layout()->reportContext().layer() && mLegend->layout()->reportContext().layer()->geometryType() ==
QgsWkbTypes::PolygonGeometry );
1369 void QgsLayoutLegendWidget::mItemTreeView_doubleClicked(
const QModelIndex &idx )
1371 if ( !mLegend || !idx.isValid() )
1376 if ( mLegend->autoUpdateModel() )
1383 int originalIndex = -1;
1386 originalIndex = _originalLegendNodeIndex(
legendNode );
1390 QgsLayoutLegendNodeWidget *widget =
new QgsLayoutLegendNodeWidget( mLegend, currentNode,
legendNode, originalIndex );
1391 openPanel( widget );
1399 QgsLayoutLegendMenuProvider::QgsLayoutLegendMenuProvider(
QgsLayerTreeView *view, QgsLayoutLegendWidget *w )
1404 QMenu *QgsLayoutLegendMenuProvider::createContextMenu()
1406 if ( !mView->currentNode() )
1409 if ( mWidget->legend()->autoUpdateModel() )
1412 QMenu *menu =
new QMenu();
1416 menu->addAction( QObject::tr(
"Reset to Defaults" ), mWidget, &QgsLayoutLegendWidget::resetLayerNodeToDefaults );
1417 menu->addSeparator();
1422 QList<QgsLegendStyle::Style> lst;
1426 QAction *action = menu->addAction(
QgsLegendStyle::styleLabel( style ), mWidget, &QgsLayoutLegendWidget::setCurrentNodeStyleFromAction );
1427 action->setCheckable(
true );
1428 action->setChecked( currentStyle == style );
1429 action->setData(
static_cast< int >( style ) );
1444 , mOriginalLegendNodeIndex( originalLegendNodeIndex )
1447 setPanelTitle( tr(
"Legend Item Properties" ) );
1456 QString currentLabel;
1459 currentLabel = mLegendNode->data( Qt::EditRole ).toString();
1460 mColumnBreakBeforeCheckBox->setChecked( mLegendNode->columnBreak() );
1464 currentLabel = mLayer->name();
1465 QVariant v = mLayer->customProperty( QStringLiteral(
"legend/title-label" ) );
1467 currentLabel = v.toString();
1468 mColumnBreakBeforeCheckBox->setChecked( mLayer->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1470 mColumnSplitBehaviorComboBox->setCurrentIndex( mColumnSplitBehaviorComboBox->findData( mLayer->legendSplitBehavior() ) );
1475 mColumnBreakBeforeCheckBox->setChecked( mNode->customProperty( QStringLiteral(
"legend/column-break" ) ).toInt() );
1478 mWidthSpinBox->setClearValue( 0, tr(
"Default" ) );
1479 mHeightSpinBox->setClearValue( 0, tr(
"Default" ) );
1480 mWidthSpinBox->setVisible( mLegendNode || mLayer );
1481 mHeightSpinBox->setVisible( mLegendNode || mLayer );
1482 mPatchGroup->setVisible( mLegendNode || mLayer );
1483 mPatchWidthLabel->setVisible( mLegendNode || mLayer );
1484 mPatchHeightLabel->setVisible( mLegendNode || mLayer );
1485 mCustomSymbolCheckBox->setVisible( mLegendNode || mLegend->model()->legendNodeEmbeddedInParent( mLayer ) );
1486 mColumnSplitLabel->setVisible( mLayer && !mLegendNode );
1487 mColumnSplitBehaviorComboBox->setVisible( mLayer && !mLegendNode );
1490 mWidthSpinBox->setValue( mLegendNode->userPatchSize().width() );
1491 mHeightSpinBox->setValue( mLegendNode->userPatchSize().height() );
1495 mWidthSpinBox->setValue( mLayer->patchSize().width() );
1496 mHeightSpinBox->setValue( mLayer->patchSize().height() );
1499 mCustomSymbolCheckBox->setChecked(
false );
1504 patchShape = symbolLegendNode->patchShape();
1506 std::unique_ptr< QgsSymbol > customSymbol( symbolLegendNode->customSymbol() ? symbolLegendNode->customSymbol()->clone() :
nullptr );
1507 mCustomSymbolCheckBox->setChecked( customSymbol.get() );
1510 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1511 mCustomSymbolButton->setSymbolType( customSymbol->type() );
1512 mCustomSymbolButton->setSymbol( customSymbol.release() );
1514 else if ( symbolLegendNode->symbol() )
1516 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1517 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1518 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1521 else if ( !mLegendNode && mLayer )
1523 patchShape = mLayer->patchShape();
1526 if (
QgsSymbol *customSymbol = symbolLegendNode->customSymbol() )
1528 mCustomSymbolCheckBox->setChecked(
true );
1529 mPatchShapeButton->setPreviewSymbol( customSymbol->clone() );
1531 mCustomSymbolButton->setSymbol( customSymbol->clone() );
1535 mPatchShapeButton->setPreviewSymbol( symbolLegendNode->symbol()->clone() );
1536 mCustomSymbolButton->setSymbolType( symbolLegendNode->symbol()->type() );
1537 mCustomSymbolButton->setSymbol( symbolLegendNode->symbol()->clone() );
1544 switch ( qobject_cast< QgsVectorLayer * >( mLayer->layer() )->geometryType() )
1559 mPatchShapeLabel->hide();
1560 mPatchShapeButton->hide();
1563 if ( !patchShape.
isNull() )
1564 mPatchShapeButton->setShape( patchShape );
1569 mPatchShapeLabel->hide();
1570 mPatchShapeButton->hide();
1573 mLabelEdit->setPlainText( currentLabel );
1574 connect( mLabelEdit, &QPlainTextEdit::textChanged,
this, &QgsLayoutLegendNodeWidget::labelChanged );
1576 connect( mInsertExpressionButton, &QPushButton::clicked,
this, &QgsLayoutLegendNodeWidget::insertExpression );
1578 connect( mWidthSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1579 connect( mHeightSpinBox, qgis::overload<double>::of( &QgsDoubleSpinBox::valueChanged ),
this, &QgsLayoutLegendNodeWidget::sizeChanged );
1581 connect( mCustomSymbolCheckBox, &QGroupBox::toggled,
this, &QgsLayoutLegendNodeWidget::customSymbolChanged );
1584 connect( mColumnBreakBeforeCheckBox, &QCheckBox::toggled,
this, &QgsLayoutLegendNodeWidget::columnBreakToggled );
1586 connect( mColumnSplitBehaviorComboBox, qgis::overload<int>::of( &QComboBox::currentIndexChanged ),
this, &QgsLayoutLegendNodeWidget::columnSplitChanged );
1589 void QgsLayoutLegendNodeWidget::labelChanged()
1593 const QString label = mLabelEdit->toPlainText();
1598 else if ( mLegendNode )
1601 mLegend->model()->refreshLayerLegend( mLayer );
1605 mLayer->setCustomProperty( QStringLiteral(
"legend/title-label" ), label );
1609 embeddedNode->setUserLabel( QString() );
1612 mLegend->adjustBoxSize();
1613 mLegend->updateFilterByMap();
1614 mLegend->endCommand();
1617 void QgsLayoutLegendNodeWidget::patchChanged()
1619 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1625 mLegend->model()->refreshLayerLegend( mLayer );
1629 mLayer->setPatchShape( shape );
1630 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1635 mLegend->model()->refreshLayerLegend( mLayer );
1638 mLegend->adjustBoxSize();
1639 mLegend->updateFilterByMap();
1640 mLegend->endCommand();
1643 void QgsLayoutLegendNodeWidget::insertExpression()
1648 QString selText = mLabelEdit->textCursor().selectedText();
1651 selText = selText.replace( QChar( 0x2029 ), QChar(
'\n' ) );
1654 if ( selText.startsWith( QLatin1String(
"[%" ) ) && selText.endsWith( QLatin1String(
"%]" ) ) )
1655 selText = selText.mid( 2, selText.size() - 4 );
1658 QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() :
nullptr;
1662 if ( mLayer && mLayer->layer() )
1668 << QStringLiteral(
"legend_column_count" )
1669 << QStringLiteral(
"legend_split_layers" )
1670 << QStringLiteral(
"legend_wrap_string" )
1671 << QStringLiteral(
"legend_filter_by_map" )
1672 << QStringLiteral(
"legend_filter_out_atlas" ) );
1676 exprDlg.setWindowTitle( tr(
"Insert Expression" ) );
1677 if ( exprDlg.exec() == QDialog::Accepted )
1679 QString expression = exprDlg.expressionText();
1680 if ( !expression.isEmpty() )
1682 mLegend->beginCommand( tr(
"Insert expression" ) );
1683 mLabelEdit->insertPlainText(
"[%" + expression +
"%]" );
1684 mLegend->endCommand();
1689 void QgsLayoutLegendNodeWidget::sizeChanged(
double )
1691 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1692 const QSizeF size = QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() );
1697 mLegend->model()->refreshLayerLegend( mLayer );
1701 mLayer->setPatchSize( size );
1702 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1707 mLegend->model()->refreshLayerLegend( mLayer );
1710 mLegend->adjustBoxSize();
1711 mLegend->updateFilterByMap();
1712 mLegend->endCommand();
1715 void QgsLayoutLegendNodeWidget::customSymbolChanged()
1717 mLegend->beginCommand( tr(
"Edit Legend Item" ) );
1719 if ( mCustomSymbolCheckBox->isChecked() )
1724 mLegend->model()->refreshLayerLegend( mLayer );
1728 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1733 mLegend->model()->refreshLayerLegend( mLayer );
1741 mLegend->model()->refreshLayerLegend( mLayer );
1745 const QList<QgsLayerTreeModelLegendNode *> layerLegendNodes = mLegend->model()->layerLegendNodes( mLayer,
false );
1750 mLegend->model()->refreshLayerLegend( mLayer );
1754 mLegend->adjustBoxSize();
1755 mLegend->updateFilterByMap();
1756 mLegend->endCommand();
1759 void QgsLayoutLegendNodeWidget::columnBreakToggled(
bool checked )
1761 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1766 mLegend->model()->refreshLayerLegend( mLayer );
1770 mLayer->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1774 mNode->setCustomProperty( QStringLiteral(
"legend/column-break" ), QString( checked ?
'1' :
'0' ) );
1777 mLegend->adjustBoxSize();
1778 mLegend->updateFilterByMap();
1779 mLegend->endCommand();
1782 void QgsLayoutLegendNodeWidget::columnSplitChanged()
1784 mLegend->beginCommand( tr(
"Edit Legend Columns" ) );
1786 if ( mLayer && !mLegendNode )
1791 mLegend->adjustBoxSize();
1792 mLegend->updateFilterByMap();
1793 mLegend->endCommand();