Kaydet (Commit) 0fe7bda2 authored tarafından Armin Le Grand's avatar Armin Le Grand

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/53839Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarArmin Le Grand <Armin.Le.Grand@cib.de>
üst b72a31b3
......@@ -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 )
......
......@@ -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
......
......@@ -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; }
......
......@@ -175,7 +175,8 @@ SdPage::~SdPage()
clearChildNodes(mxAnimationNode);
Clear();
// clear SdrObjects with broadcasting
ClearSdrObjList();
}
struct OrdNumSorter
......
......@@ -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++)
{
......
......@@ -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())
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment