From 2fb85192aad7ff5757b50d545a8d6119434a0483 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 22 Jul 2024 10:52:31 +1000 Subject: [PATCH] Fix crash when extracting symbols from project with layout legend Legend must be initialized before calling style visitor function Fixes #57609 --- .../layout/qgslayoutitemlegend.sip.in | 1 + .../layout/qgslayoutitemlegend.sip.in | 1 + src/core/layout/qgslayoutitemlegend.cpp | 15 +++++++++++---- src/core/layout/qgslayoutitemlegend.h | 9 ++++++++- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/python/PyQt6/core/auto_generated/layout/qgslayoutitemlegend.sip.in b/python/PyQt6/core/auto_generated/layout/qgslayoutitemlegend.sip.in index fd646b104aed..6d45578e3c7f 100644 --- a/python/PyQt6/core/auto_generated/layout/qgslayoutitemlegend.sip.in +++ b/python/PyQt6/core/auto_generated/layout/qgslayoutitemlegend.sip.in @@ -122,6 +122,7 @@ Returns whether the legend should automatically resize to fit its contents. Returns the legend model. %End + void setAutoUpdateModel( bool autoUpdate ); %Docstring Sets whether the legend content should auto update to reflect changes in the project's diff --git a/python/core/auto_generated/layout/qgslayoutitemlegend.sip.in b/python/core/auto_generated/layout/qgslayoutitemlegend.sip.in index fd646b104aed..6d45578e3c7f 100644 --- a/python/core/auto_generated/layout/qgslayoutitemlegend.sip.in +++ b/python/core/auto_generated/layout/qgslayoutitemlegend.sip.in @@ -122,6 +122,7 @@ Returns whether the legend should automatically resize to fit its contents. Returns the legend model. %End + void setAutoUpdateModel( bool autoUpdate ); %Docstring Sets whether the legend content should auto update to reflect changes in the project's diff --git a/src/core/layout/qgslayoutitemlegend.cpp b/src/core/layout/qgslayoutitemlegend.cpp index cf14e3789d8e..b14e9c7665d1 100644 --- a/src/core/layout/qgslayoutitemlegend.cpp +++ b/src/core/layout/qgslayoutitemlegend.cpp @@ -319,12 +319,13 @@ void QgsLayoutItemLegend::setCustomLayerTree( QgsLayerTree *rootGroup ) mCustomLayerTree.reset( rootGroup ); } -void QgsLayoutItemLegend::ensureModelIsInitialized() +void QgsLayoutItemLegend::ensureModelIsInitialized() const { if ( mDeferLegendModelInitialization ) { - mDeferLegendModelInitialization = false; - setCustomLayerTree( mCustomLayerTree.release() ); + QgsLayoutItemLegend *mutableThis = const_cast< QgsLayoutItemLegend * >( this ); + mutableThis->mDeferLegendModelInitialization = false; + mutableThis->setCustomLayerTree( mutableThis->mCustomLayerTree.release() ); } } @@ -334,6 +335,12 @@ QgsLegendModel *QgsLayoutItemLegend::model() return mLegendModel.get(); } +const QgsLegendModel *QgsLayoutItemLegend::model() const +{ + ensureModelIsInitialized(); + return mLegendModel.get(); +} + void QgsLayoutItemLegend::setAutoUpdateModel( bool autoUpdate ) { if ( autoUpdate == autoUpdateModel() ) @@ -1345,7 +1352,7 @@ bool QgsLayoutItemLegend::accept( QgsStyleEntityVisitorInterface *visitor ) cons } return true; }; - return visit( mLegendModel->rootGroup( ) ); + return visit( model()->rootGroup( ) ); } bool QgsLayoutItemLegend::isRefreshing() const diff --git a/src/core/layout/qgslayoutitemlegend.h b/src/core/layout/qgslayoutitemlegend.h index 0302c18141a7..8c4b8e31fbeb 100644 --- a/src/core/layout/qgslayoutitemlegend.h +++ b/src/core/layout/qgslayoutitemlegend.h @@ -158,6 +158,13 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem */ QgsLegendModel *model(); + /** + * Returns the legend model. + * + * \note Not available in Python bindings + */ + const QgsLegendModel *model() const SIP_SKIP; + /** * Sets whether the legend content should auto update to reflect changes in the project's * layer tree. @@ -634,7 +641,7 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem void setModelStyleOverrides( const QMap &overrides ); - void ensureModelIsInitialized(); + void ensureModelIsInitialized() const; std::unique_ptr< QgsLegendModel > mLegendModel; std::unique_ptr< QgsLayerTree > mCustomLayerTree; bool mDeferLegendModelInitialization = true;