diff --git a/python/core/layout/qgslayoutframe.sip b/python/core/layout/qgslayoutframe.sip index 5a2de801d50..187f5b6a0d2 100644 --- a/python/core/layout/qgslayoutframe.sip +++ b/python/core/layout/qgslayoutframe.sip @@ -43,6 +43,9 @@ Creates a new QgsLayoutFrame belonging to the specified ``layout``. virtual QString displayName() const; + virtual void cleanup(); + + void setContentSection( const QRectF §ion ); %Docstring Sets the visible part of the multiframe's content which is visible within diff --git a/python/core/layout/qgslayoutmultiframe.sip b/python/core/layout/qgslayoutmultiframe.sip index 9c3ce3bebad..45683fb7b76 100644 --- a/python/core/layout/qgslayoutmultiframe.sip +++ b/python/core/layout/qgslayoutmultiframe.sip @@ -383,20 +383,6 @@ in finalizeRestoreFromXml(), not readPropertiesFromElement(). - protected slots: - - void handlePageChange(); -%Docstring -Adapts to changed number of layout pages if resize type is RepeatOnEveryPage. -%End - - void handleFrameRemoval(); -%Docstring -Called when a frame is removed. Updates frame list and recalculates -content of remaining frames. -%End - - }; diff --git a/src/core/layout/qgslayoutframe.cpp b/src/core/layout/qgslayoutframe.cpp index f573fe9740a..f94c5d12a59 100644 --- a/src/core/layout/qgslayoutframe.cpp +++ b/src/core/layout/qgslayoutframe.cpp @@ -192,6 +192,14 @@ QString QgsLayoutFrame::displayName() const return tr( "" ); } +void QgsLayoutFrame::cleanup() +{ + if ( mMultiFrame ) + mMultiFrame->handleFrameRemoval( this ); + + QgsLayoutItem::cleanup(); +} + void QgsLayoutFrame::draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle ) { if ( mMultiFrame ) diff --git a/src/core/layout/qgslayoutframe.h b/src/core/layout/qgslayoutframe.h index 69bb97334f6..2ba42a7a8aa 100644 --- a/src/core/layout/qgslayoutframe.h +++ b/src/core/layout/qgslayoutframe.h @@ -52,6 +52,8 @@ class CORE_EXPORT QgsLayoutFrame: public QgsLayoutItem //Overridden to allow multiframe to set display name QString displayName() const override; + void cleanup() override; + /** * Sets the visible part of the multiframe's content which is visible within * this frame (relative to the total multiframe extent in layout units). diff --git a/src/core/layout/qgslayoutmultiframe.cpp b/src/core/layout/qgslayoutmultiframe.cpp index df8f48e15b1..3f8a5647180 100644 --- a/src/core/layout/qgslayoutmultiframe.cpp +++ b/src/core/layout/qgslayoutmultiframe.cpp @@ -60,7 +60,10 @@ void QgsLayoutMultiFrame::addFrame( QgsLayoutFrame *frame, bool recalcFrameSizes mFrameItems.push_back( frame ); frame->mMultiFrame = this; connect( frame, &QgsLayoutItem::sizePositionChanged, this, &QgsLayoutMultiFrame::recalculateFrameSizes ); - connect( frame, &QgsLayoutFrame::destroyed, this, &QgsLayoutMultiFrame::handleFrameRemoval ); + connect( frame, &QgsLayoutFrame::destroyed, this, [this, frame ] + { + handleFrameRemoval( frame ); + } ); if ( mLayout ) { mLayout->addLayoutItem( frame ); @@ -306,12 +309,11 @@ void QgsLayoutMultiFrame::refresh() refreshDataDefinedProperty(); } -void QgsLayoutMultiFrame::handleFrameRemoval() +void QgsLayoutMultiFrame::handleFrameRemoval( QgsLayoutFrame *frame ) { if ( mBlockUpdates ) return; - QgsLayoutFrame *frame = qobject_cast( sender() ); if ( !frame ) { return; diff --git a/src/core/layout/qgslayoutmultiframe.h b/src/core/layout/qgslayoutmultiframe.h index 8b6cef3b3de..390c8fbd34a 100644 --- a/src/core/layout/qgslayoutmultiframe.h +++ b/src/core/layout/qgslayoutmultiframe.h @@ -370,7 +370,7 @@ class CORE_EXPORT QgsLayoutMultiFrame: public QgsLayoutObject, public QgsLayoutU ResizeMode mResizeMode = UseExistingFrames; - protected slots: + private slots: /** * Adapts to changed number of layout pages if resize type is RepeatOnEveryPage. @@ -381,7 +381,7 @@ class CORE_EXPORT QgsLayoutMultiFrame: public QgsLayoutObject, public QgsLayoutU * Called when a frame is removed. Updates frame list and recalculates * content of remaining frames. */ - void handleFrameRemoval(); + void handleFrameRemoval( QgsLayoutFrame *frame ); private: @@ -394,6 +394,7 @@ class CORE_EXPORT QgsLayoutMultiFrame: public QgsLayoutObject, public QgsLayoutU //! Unique id QString mUuid; + friend class QgsLayoutFrame; }; diff --git a/tests/src/core/testqgslayoutmultiframe.cpp b/tests/src/core/testqgslayoutmultiframe.cpp index ac279f69b56..c1678fce870 100644 --- a/tests/src/core/testqgslayoutmultiframe.cpp +++ b/tests/src/core/testqgslayoutmultiframe.cpp @@ -47,6 +47,7 @@ class TestQgsLayoutMultiFrame : public QObject void undoRedoRemovedFrame(); //test that undo doesn't crash with removed frames void undoRedoRemovedFrame2(); void registry(); + void deleteFrame(); private: QgsLayout *mLayout = nullptr; @@ -556,5 +557,28 @@ void TestQgsLayoutMultiFrame::registry() QVERIFY( props.isEmpty() ); } +void TestQgsLayoutMultiFrame::deleteFrame() +{ + QgsLayout l( QgsProject::instance() ); + l.initializeDefaults(); + + QgsLayoutItemHtml *htmlItem = new QgsLayoutItemHtml( &l ); + QgsLayoutFrame *frame1 = new QgsLayoutFrame( &l, htmlItem ); + frame1->attemptSetSceneRect( QRectF( 0, 0, 100, 200 ) ); + htmlItem->addFrame( frame1 ); + QgsLayoutFrame *frame2 = new QgsLayoutFrame( &l, htmlItem ); + frame2->attemptSetSceneRect( QRectF( 0, 0, 100, 200 ) ); + htmlItem->addFrame( frame2 ); + + QCOMPARE( htmlItem->frameCount(), 2 ); + QCOMPARE( htmlItem->frames(), QList< QgsLayoutFrame * >() << frame1 << frame2 ); + l.removeLayoutItem( frame1 ); + QCOMPARE( htmlItem->frameCount(), 1 ); + QCOMPARE( htmlItem->frames(), QList< QgsLayoutFrame * >() << frame2 ); + l.removeLayoutItem( frame2 ); + QCOMPARE( htmlItem->frameCount(), 0 ); + QVERIFY( htmlItem->frames().empty() ); +} + QGSTEST_MAIN( TestQgsLayoutMultiFrame ) #include "testqgslayoutmultiframe.moc"