basctl/source/dlged/dlged.cxx | 5 +- basctl/source/dlged/dlgedpage.cxx | 3 - include/svx/svdpage.hxx | 15 ++++++ sd/source/core/sdpage.cxx | 3 - svx/source/dialog/contwnd.cxx | 3 - svx/source/dialog/imapwnd.cxx | 4 - svx/source/svdraw/svdpage.cxx | 82 +++++++++++++++++++++----------------- 7 files changed, 72 insertions(+), 43 deletions(-)
New commits: commit 0fe7bda233da3c1f95a82c0050c8f917dc39c22e Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Fri May 4 11:21:15 2018 +0200 tdf#116879 Separate SdrObjList::Clear() as needed SdrObjList::Clear() does broadcast the SdrObject removals and deletions and a SetChanged() to SdrModel. The old version avoided this in the destructor (with a comment to not call virtual methods in destructor, but the problem is more that the ::Notify triggered works on the SdrPage already in destruction). To allow calls to Clear() without broadcasting I splitted this to a impClearSdrObjList(bool bBrodacast) and rename of ::Clear to ::ClearSdrObjList to get all places. Adapted all places in the code as needed, already pre- checked on Linux that this fixes the problem. Change-Id: Iea46758fb6b57f2b3d9896959a35260c6f6d52d5 Reviewed-on: https://gerrit.libreoffice.org/53839 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Armin Le Grand <armin.le.gr...@cib.de> diff --git a/basctl/source/dlged/dlged.cxx b/basctl/source/dlged/dlged.cxx index 186e83521b05..f3755414bfb3 100644 --- a/basctl/source/dlged/dlged.cxx +++ b/basctl/source/dlged/dlged.cxx @@ -414,7 +414,10 @@ void DlgEditor::ResetDialog () SdrPageView* pPgView = pDlgEdView->GetSdrPageView(); bool bWasMarked = pDlgEdView->IsObjMarked( pOldDlgEdForm ); pDlgEdView->UnmarkAll(); - pPage->Clear(); + + // clear SdrObjects with broadcasting + pPage->ClearSdrObjList(); + pPage->SetDlgEdForm( nullptr ); SetDialog( m_xUnoControlDialogModel ); if( bWasMarked ) diff --git a/basctl/source/dlged/dlgedpage.cxx b/basctl/source/dlged/dlgedpage.cxx index da9ba12ef1b0..73241128d447 100644 --- a/basctl/source/dlged/dlgedpage.cxx +++ b/basctl/source/dlged/dlgedpage.cxx @@ -34,7 +34,8 @@ DlgEdPage::DlgEdPage(DlgEdModel& rModel, bool bMasterPage) DlgEdPage::~DlgEdPage() { - Clear(); + // clear SdrObjects with broadcasting + ClearSdrObjList(); } SdrPage* DlgEdPage::Clone(SdrModel* const pNewModel) const diff --git a/include/svx/svdpage.hxx b/include/svx/svdpage.hxx index a4cc40feebd4..fa5364bae022 100644 --- a/include/svx/svdpage.hxx +++ b/include/svx/svdpage.hxx @@ -88,13 +88,24 @@ protected: private: /// simple ActionChildInserted forwarder to have it on a central place static void impChildInserted(SdrObject const & rChild); + + // tdf#116879 Clear SdrObjList, no Undo done. Used from destructor, but also + // from other places. When used from destructor, suppress broadcasts + // to not get callbacks to evtl. derived objects already in destruction + // (e.g. SdrPage) + void impClearSdrObjList(bool bBroadcast); + public: SdrObjList(SdrPage* pNewPage = nullptr); virtual ~SdrObjList(); void CopyObjects(const SdrObjList& rSrcList, SdrModel* pNewModel = nullptr); - /// clean up everything (without Undo) - void Clear(); + + // tdf#116879 clean up everything (without Undo), plus broadcasting + // changes. Split to this call and a private one (impClearSdrObjList) + // that allows cleanup without broadcasting in the destructor + void ClearSdrObjList(); + SdrObjListKind GetListKind() const { return eListKind; } void SetListKind(SdrObjListKind eNewKind) { eListKind=eNewKind; } SdrObjList* GetUpList() const { return pUpList; } diff --git a/sd/source/core/sdpage.cxx b/sd/source/core/sdpage.cxx index fc60775f6cef..aadb6a91e905 100644 --- a/sd/source/core/sdpage.cxx +++ b/sd/source/core/sdpage.cxx @@ -175,7 +175,8 @@ SdPage::~SdPage() clearChildNodes(mxAnimationNode); - Clear(); + // clear SdrObjects with broadcasting + ClearSdrObjList(); } struct OrdNumSorter diff --git a/svx/source/dialog/contwnd.cxx b/svx/source/dialog/contwnd.cxx index 4ac1e23083d5..014a10d9e472 100644 --- a/svx/source/dialog/contwnd.cxx +++ b/svx/source/dialog/contwnd.cxx @@ -54,7 +54,8 @@ void ContourWindow::SetPolyPolygon(const tools::PolyPolygon& rPolyPoly) // them first (!) pView->UnmarkAllObj(); - pPage->Clear(); + // clear SdrObjects with broadcasting + pPage->ClearSdrObjList(); for (sal_uInt16 i = 0; i < nPolyCount; i++) { diff --git a/svx/source/dialog/imapwnd.cxx b/svx/source/dialog/imapwnd.cxx index 3e3f1667fbf2..6275842c6791 100644 --- a/svx/source/dialog/imapwnd.cxx +++ b/svx/source/dialog/imapwnd.cxx @@ -101,8 +101,8 @@ void IMapWindow::ReplaceImageMap( const ImageMap& rImageMap ) if(pPage) { - // clear all draw objects - pPage->Clear(); + // clear SdrObjects with broadcasting + pPage->ClearSdrObjList(); } if(GetSdrView()) diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx index a5d16568e049..b5a7f81abccf 100644 --- a/svx/source/svdraw/svdpage.cxx +++ b/svx/source/svdraw/svdpage.cxx @@ -84,9 +84,52 @@ SdrObjList::SdrObjList(SdrPage* pNewPage) eListKind=SdrObjListKind::Unknown; } +void SdrObjList::impClearSdrObjList(bool bBroadcast) +{ + SdrModel* pSdrModelFromRemovedSdrObject(nullptr); + + while(!maList.empty()) + { + // remove last object from list + SdrObject* pObj = maList.back(); + RemoveObjectFromContainer(maList.size()-1); + + // flushViewObjectContacts() is done since SdrObject::Free is not guaranteed + // to delete the object and thus refresh visualisations + pObj->GetViewContact().flushViewObjectContacts(); + + if(bBroadcast) + { + if(nullptr == pSdrModelFromRemovedSdrObject) + { + pSdrModelFromRemovedSdrObject = &pObj->getSdrModelFromSdrObject(); + } + + // sent remove hint (after removal, see RemoveObject()) + SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj, mpPage); + pObj->getSdrModelFromSdrObject().Broadcast(aHint); + } + + // delete the object itself + SdrObject::Free( pObj ); + } + + if(bBroadcast && nullptr != pSdrModelFromRemovedSdrObject) + { + pSdrModelFromRemovedSdrObject->SetChanged(); + } +} + +void SdrObjList::ClearSdrObjList() +{ + // clear SdrObjects with broadcasting + impClearSdrObjList(true); +} + SdrObjList::~SdrObjList() { - Clear(); // delete contents of container + // clear SdrObjects without broadcasting + impClearSdrObjList(false); } void SdrObjList::copyDataFromSdrObjList(const SdrObjList& rSrcList, SdrModel* pNewModelel) @@ -99,7 +142,9 @@ void SdrObjList::copyDataFromSdrObjList(const SdrObjList& rSrcList, SdrModel* pN void SdrObjList::CopyObjects(const SdrObjList& rSrcList, SdrModel* pNewModelel) { - Clear(); + // clear SdrObjects with broadcasting + ClearSdrObjList(); + bObjOrdNumsDirty = false; bRectsDirty = false; size_t nCloneErrCnt(0); @@ -187,39 +232,6 @@ void SdrObjList::CopyObjects(const SdrObjList& rSrcList, SdrModel* pNewModelel) } } -void SdrObjList::Clear() -{ - SdrModel* pSdrModelFromRemovedSdrObject(nullptr); - - while(!maList.empty()) - { - // remove last object from list - SdrObject* pObj = maList.back(); - RemoveObjectFromContainer(maList.size()-1); - - // flushViewObjectContacts() is done since SdrObject::Free is not guaranteed - // to delete the object and thus refresh visualisations - pObj->GetViewContact().flushViewObjectContacts(); - - if(nullptr == pSdrModelFromRemovedSdrObject) - { - pSdrModelFromRemovedSdrObject = &pObj->getSdrModelFromSdrObject(); - } - - // sent remove hint (after removal, see RemoveObject()) - SdrHint aHint(SdrHintKind::ObjectRemoved, *pObj, mpPage); - pObj->getSdrModelFromSdrObject().Broadcast(aHint); - - // delete the object itself - SdrObject::Free( pObj ); - } - - if(nullptr != pSdrModelFromRemovedSdrObject) - { - pSdrModelFromRemovedSdrObject->SetChanged(); - } -} - SdrPage* SdrObjList::GetPage() const { return mpPage; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits