diff --git a/python/core/auto_generated/qgsgrouplayer.sip.in b/python/core/auto_generated/qgsgrouplayer.sip.in index bb3b03100dd..03fbcd49235 100644 --- a/python/core/auto_generated/qgsgrouplayer.sip.in +++ b/python/core/auto_generated/qgsgrouplayer.sip.in @@ -108,6 +108,17 @@ Sets the current paint ``effect`` for the renderer. Ownership is transferred to the renderer. .. seealso:: :py:func:`paintEffect` +%End + + void prepareLayersForRemovalFromGroup(); +%Docstring +Prepares all child layers in the group prior to removal from the group. + +This method should be called before removing a group layer from a project, to ensure +that the existing child layers are in a state which is compatible with non-group +layer children. + +.. versionadded:: 3.30 %End }; diff --git a/src/core/layertree/qgslayertreegroup.cpp b/src/core/layertree/qgslayertreegroup.cpp index 80ae191acab..b05d4d9eeb3 100644 --- a/src/core/layertree/qgslayertreegroup.cpp +++ b/src/core/layertree/qgslayertreegroup.cpp @@ -490,15 +490,7 @@ void QgsLayerTreeGroup::setGroupLayer( QgsGroupLayer *layer ) { if ( !layer ) { - // clearing the group layer -- ensure all child layers have consistent settings - const QList< QgsMapLayer * > children = groupLayer->childLayers(); - for ( QgsMapLayer *child : children ) - { - if ( QgsPainting::isClippingMode( QgsPainting::getBlendModeEnum( child->blendMode() ) ) ) - { - child->setBlendMode( QPainter::CompositionMode_SourceOver ); - } - } + groupLayer->prepareLayersForRemovalFromGroup(); } } mGroupLayer.setLayer( layer ); diff --git a/src/core/qgsgrouplayer.cpp b/src/core/qgsgrouplayer.cpp index 4bc8e18bb3a..d9acf3a065c 100644 --- a/src/core/qgsgrouplayer.cpp +++ b/src/core/qgsgrouplayer.cpp @@ -289,9 +289,15 @@ void QgsGroupLayer::setChildLayers( const QList< QgsMapLayer * > &layers ) } for ( QgsMapLayer *layer : currentLayers ) { - if ( !layers.contains( layer ) ) + if ( layer && !layers.contains( layer ) ) { + // layer removed from group disconnect( layer, &QgsMapLayer::repaintRequested, this, &QgsMapLayer::triggerRepaint ); + + if ( QgsPainting::isClippingMode( QgsPainting::getBlendModeEnum( layer->blendMode() ) ) ) + { + layer->setBlendMode( QPainter::CompositionMode_SourceOver ); + } } } mChildren = _qgis_listRawToRef( layers ); @@ -331,6 +337,17 @@ void QgsGroupLayer::setPaintEffect( QgsPaintEffect *effect ) mPaintEffect.reset( effect ); } +void QgsGroupLayer::prepareLayersForRemovalFromGroup() +{ + for ( const QgsMapLayerRef &child : std::as_const( mChildren ) ) + { + if ( child.get() && QgsPainting::isClippingMode( QgsPainting::getBlendModeEnum( child->blendMode() ) ) ) + { + child->setBlendMode( QPainter::CompositionMode_SourceOver ); + } + } +} + // // QgsGroupLayerDataProvider // diff --git a/src/core/qgsgrouplayer.h b/src/core/qgsgrouplayer.h index b1ff9ef734f..f3362bbbd0e 100644 --- a/src/core/qgsgrouplayer.h +++ b/src/core/qgsgrouplayer.h @@ -126,6 +126,17 @@ class CORE_EXPORT QgsGroupLayer : public QgsMapLayer */ void setPaintEffect( QgsPaintEffect *effect SIP_TRANSFER ); + /** + * Prepares all child layers in the group prior to removal from the group. + * + * This method should be called before removing a group layer from a project, to ensure + * that the existing child layers are in a state which is compatible with non-group + * layer children. + * + * \since QGIS 3.30 + */ + void prepareLayersForRemovalFromGroup(); + private: QgsGroupLayerDataProvider *mDataProvider = nullptr;