summaryrefslogtreecommitdiff
path: root/svx
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2021-11-30 20:27:24 +0100
committerMichael Stahl <michael.stahl@allotropia.de>2021-12-03 16:57:29 +0100
commit5a57ef3293bb2581a83487d1fd5534ed3b414217 (patch)
tree8d9e05af1a8c78a4f90614faa0fac462d4b00081 /svx
parentf9ea114171cb422dac60100aa4d51502563f37a1 (diff)
tdf#145928 svx: fix undo of sorting shapes
The problem is that in sw there are these obnoxious virtual SdrObjects that are created and destroyed by the layout. 0 SdrObject::~SdrObject() 3 SwVirtFlyDrawObj::~SwVirtFlyDrawObj() 5 SwFlyFrame::FinitDrawObj() 12 SwFrame::DestroyFrame(SwFrame*) 13 SwFrameFormat::DelFrames() 14 SwUndoFlyBase::DelFly(SwDoc*) 15 SwUndoDelLayFormat::SwUndoDelLayFormat(SwFrameFormat*) 16 SwHistoryTextFlyCnt::SwHistoryTextFlyCnt(SwFrameFormat*) This misdesign means that SdrUndoObj::pObj may point to a deleted object. Commit 9bc6160e0acbc78be998129ea55ed7e4529959fa may create SdrUnoObj when saving the document, so that is now an additional way to introduce the problem. Try to work around it by not using a SdrUndoObj subclass in this case, but create a new SdrUndoAction subclass that uses SdrPage::sort() and stores no pointers. There is still the problem that changes in the layout or view settings like "Hide tracked changes" could cause different virtual SdrObjects to exist between when the Undo was recorded and when it is activated, in which case nothing is done. But that really requires a larger refactoring such as having a SdrPage for the model that never contains virtual SdrObjects, and another SdrPage for the view that does contain virtual SdrObjects to fix. Change-Id: I4cf5d4eb8bb24a51730c55ff34a043b8a88fdb52 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126153 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> (cherry picked from commit 25a368c30acb54e0819d2b2b890a3fd1530d8a76) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126136
Diffstat (limited to 'svx')
-rw-r--r--svx/source/svdraw/svdpage.cxx12
-rw-r--r--svx/source/svdraw/svdundo.cxx48
2 files changed, 49 insertions, 11 deletions
diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx
index 1ebfe6cad4ac..473b06d1f394 100644
--- a/svx/source/svdraw/svdpage.cxx
+++ b/svx/source/svdraw/svdpage.cxx
@@ -718,25 +718,15 @@ void SdrObjList::sort( std::vector<sal_Int32>& sortOrder)
bool const isUndo(rModel.IsUndoEnabled());
if (isUndo)
{
- rModel.BegUndo(SvxResId(STR_SortShapes));
+ rModel.AddUndo(rModel.GetSdrUndoFactory().CreateUndoSort(*getSdrPageFromSdrObjList(), sortOrder));
}
for (size_t i = 0; i < aNewSortOrder.size(); ++i)
{
aNewList[i] = maList[ aNewSortOrder[i] ];
- if (isUndo && i != sal::static_int_cast<size_t>(aNewSortOrder[i]))
- {
- rModel.AddUndo(rModel.GetSdrUndoFactory().CreateUndoObjectOrdNum(
- *aNewList[i], aNewSortOrder[i], i));
- }
aNewList[i]->SetOrdNum(i);
}
- if (isUndo)
- {
- rModel.EndUndo();
- }
-
std::swap(aNewList, maList);
}
diff --git a/svx/source/svdraw/svdundo.cxx b/svx/source/svdraw/svdundo.cxx
index 116c5e479a13..d26a27339541 100644
--- a/svx/source/svdraw/svdundo.cxx
+++ b/svx/source/svdraw/svdundo.cxx
@@ -42,6 +42,7 @@
#include <vcl/svapp.hxx>
#include <sfx2/viewsh.hxx>
#include <svx/svdoashp.hxx>
+#include <sal/log.hxx>
#include <osl/diagnose.h>
@@ -970,6 +971,48 @@ OUString SdrUndoObjOrdNum::GetComment() const
return ImpGetDescriptionStr(STR_UndoObjOrdNum);
}
+SdrUndoSort::SdrUndoSort(SdrPage & rPage,
+ ::std::vector<sal_Int32> const& rSortOrder)
+ : SdrUndoAction(rPage.getSdrModelFromSdrPage())
+ , m_OldSortOrder(rSortOrder.size())
+ , m_NewSortOrder(rSortOrder)
+ , m_nPage(rPage.GetPageNum())
+{
+ // invert order
+ for (size_t i = 0; i < rSortOrder.size(); ++i)
+ {
+ m_OldSortOrder[rSortOrder[i]] = i;
+ }
+}
+
+void SdrUndoSort::Do(::std::vector<sal_Int32> & rSortOrder)
+{
+ SdrPage & rPage(*rMod.GetPage(m_nPage));
+ if (rPage.GetObjCount() != rSortOrder.size())
+ {
+ // can probably happen with sw's cursed SdrVirtObj mess - no good solution for that
+ SAL_WARN("svx", "SdrUndoSort size mismatch");
+ return;
+ }
+
+ // hopefully this can't throw
+ rPage.sort(rSortOrder);
+}
+
+void SdrUndoSort::Undo()
+{
+ Do(m_OldSortOrder);
+}
+
+void SdrUndoSort::Redo()
+{
+ Do(m_NewSortOrder);
+}
+
+OUString SdrUndoSort::GetComment() const
+{
+ return SvxResId(STR_SortShapes);
+}
SdrUndoObjSetText::SdrUndoObjSetText(SdrObject& rNewObj, sal_Int32 nText)
: SdrUndoObj(rNewObj)
@@ -1668,6 +1711,11 @@ std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoObjectOrdNum( SdrObject
return std::make_unique<SdrUndoObjOrdNum>( rObject, nOldOrdNum1, nNewOrdNum1 );
}
+std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoSort(SdrPage & rPage, ::std::vector<sal_Int32> const& rSortOrder)
+{
+ return std::make_unique<SdrUndoSort>(rPage, rSortOrder);
+}
+
std::unique_ptr<SdrUndoAction> SdrUndoFactory::CreateUndoReplaceObject( SdrObject& rOldObject, SdrObject& rNewObject )
{
return std::make_unique<SdrUndoReplaceObj>( rOldObject, rNewObject );