summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2024-02-29 17:03:31 +0600
committerMiklos Vajna <vmiklos@collabora.com>2024-03-18 14:37:41 +0100
commit6c07558f71af485700f4cff8a4ce1723569efb2a (patch)
tree81df22d67d33000cfa8f113aeb1f3ff2173315a4
parentc5e0b00374bf9ad96c0ec3ab4d8f9ed76f2f2882 (diff)
cool#8443 let Insert Chart dialog to undo out of order on Canceldistro/collabora/co-23.05
Change-Id: I66d749362c9fb5f2c228f0f5d2c927cc0cf3f89f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164179 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164839 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--include/svl/undo.hxx10
-rw-r--r--sc/source/ui/drawfunc/fuins2.cxx1
-rw-r--r--sc/source/ui/inc/tabvwsh.hxx6
-rw-r--r--sc/source/ui/inc/undomanager.hxx1
-rw-r--r--sc/source/ui/view/tabvwshb.cxx21
-rw-r--r--svl/source/undo/undo.cxx40
6 files changed, 72 insertions, 7 deletions
diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx
index a64a1f5151f3..3fb6b9ebe292 100644
--- a/include/svl/undo.hxx
+++ b/include/svl/undo.hxx
@@ -288,8 +288,11 @@ public:
/** removes a mark given by its ID.
After the call, the mark ID is invalid.
+
+ @return the index at which the mark was removed, or std::numeric_limits<size_t>::max()
+ if failed
*/
- void RemoveMark( UndoStackMark const i_mark );
+ size_t RemoveMark(UndoStackMark const i_mark);
/** determines whether the top action on the Undo stack has a given mark
*/
@@ -305,6 +308,11 @@ protected:
bool UndoWithContext( SfxUndoContext& i_context );
bool RedoWithContext( SfxUndoContext& i_context );
+ // Undoes a specific mark on the undo stack, and removes it from the undo/redo stack,
+ // but only in case when the redo stack is empty. This is a dangerous operation, because
+ // it undoes out of order.
+ void UndoMark(UndoStackMark i_mark);
+
void ImplClearRedo_NoLock( bool const i_currentLevel );
/** clears all undo actions on the current level, plus all undo actions on superordinate levels,
diff --git a/sc/source/ui/drawfunc/fuins2.cxx b/sc/source/ui/drawfunc/fuins2.cxx
index f35b77e82fce..439cea33ca8c 100644
--- a/sc/source/ui/drawfunc/fuins2.cxx
+++ b/sc/source/ui/drawfunc/fuins2.cxx
@@ -673,6 +673,7 @@ FuInsertChart::FuInsertChart(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawV
}
pView->AddUndo(std::make_unique<SdrUndoNewObj>(*pObj));
+ rViewSh.SetInsertWizardUndoMark();
rtl::Reference<::svt::DialogClosedListener> pListener = new ::svt::DialogClosedListener();
pListener->SetDialogClosedLink( rLink );
diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx
index aaf51915609b..92c14e7f5558 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -187,6 +187,10 @@ private:
OUString maScope;
std::unique_ptr<ScDragData> m_pDragData;
+
+ // Chart insert wizard's mark to make sure it undoes the correct thing in LOK case
+ UndoStackMark m_InsertWizardUndoMark = MARK_INVALID;
+
private:
void Construct( TriState nForceDesignMode );
@@ -449,6 +453,8 @@ public:
void SetMoveKeepEdit(bool value) { bMoveKeepEdit = value; };
bool GetMoveKeepEdit() { return bMoveKeepEdit; };
+
+ void SetInsertWizardUndoMark();
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/undomanager.hxx b/sc/source/ui/inc/undomanager.hxx
index 03168dfab980..e36ae179f04e 100644
--- a/sc/source/ui/inc/undomanager.hxx
+++ b/sc/source/ui/inc/undomanager.hxx
@@ -27,6 +27,7 @@ public:
/// Make these public
using SdrUndoManager::UndoWithContext;
using SdrUndoManager::RedoWithContext;
+ using SdrUndoManager::UndoMark;
private:
static std::optional<ScRange> getAffectedRangeFromUndo(const SfxUndoAction*);
diff --git a/sc/source/ui/view/tabvwshb.cxx b/sc/source/ui/view/tabvwshb.cxx
index 6d7d89421d09..2401dc1c4eb5 100644
--- a/sc/source/ui/view/tabvwshb.cxx
+++ b/sc/source/ui/view/tabvwshb.cxx
@@ -317,8 +317,17 @@ void ScTabViewShell::DeactivateOle()
pClient->DeactivateObject();
}
+void ScTabViewShell::SetInsertWizardUndoMark()
+{
+ assert(m_InsertWizardUndoMark == MARK_INVALID);
+ m_InsertWizardUndoMark = GetUndoManager()->MarkTopUndoAction();
+}
+
IMPL_LINK( ScTabViewShell, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*, pEvent, void )
{
+ assert(m_InsertWizardUndoMark != MARK_INVALID);
+ UndoStackMark nInsertWizardUndoMark = m_InsertWizardUndoMark;
+ m_InsertWizardUndoMark = MARK_INVALID;
if( pEvent->DialogResult == ui::dialogs::ExecutableDialogResults::CANCEL )
{
ScTabView* pTabView = GetViewData().GetView();
@@ -331,8 +340,16 @@ IMPL_LINK( ScTabViewShell, DialogClosedHdl, css::ui::dialogs::DialogClosedEvent*
DeactivateOle();
pView->UnMarkAll();
- rScDoc.GetUndoManager()->Undo();
- rScDoc.GetUndoManager()->ClearRedo();
+ auto pUndoManager = rScDoc.GetUndoManager();
+ if (pUndoManager->GetRedoActionCount())
+ {
+ pUndoManager->RemoveMark(nInsertWizardUndoMark);
+ }
+ else
+ {
+ pUndoManager->UndoMark(nInsertWizardUndoMark);
+ pUndoManager->ClearRedo();
+ }
// leave the draw shell
SetDrawShell( false );
diff --git a/svl/source/undo/undo.cxx b/svl/source/undo/undo.cxx
index 1ddb3b35f274..81967b92e124 100644
--- a/svl/source/undo/undo.cxx
+++ b/svl/source/undo/undo.cxx
@@ -34,6 +34,26 @@
#include <limits.h>
#include <algorithm>
+namespace
+{
+class SfxMarkedUndoContext final : public SfxUndoContext
+{
+public:
+ SfxMarkedUndoContext(SfxUndoManager& manager, UndoStackMark mark)
+ {
+ m_offset = manager.RemoveMark(mark);
+ size_t count = manager.GetUndoActionCount();
+ if (m_offset < count)
+ m_offset = count - m_offset - 1;
+ else
+ m_offset = std::numeric_limits<size_t>::max();
+ }
+ size_t GetUndoOffset() override { return m_offset; }
+
+private:
+ size_t m_offset;
+};
+}
SfxRepeatTarget::~SfxRepeatTarget()
{
@@ -1083,18 +1103,18 @@ UndoStackMark SfxUndoManager::MarkTopUndoAction()
return m_xData->mnMarks;
}
-void SfxUndoManager::RemoveMark( UndoStackMark const i_mark )
+size_t SfxUndoManager::RemoveMark(UndoStackMark i_mark)
{
UndoManagerGuard aGuard( *m_xData );
if ((m_xData->mnEmptyMark < i_mark) || (MARK_INVALID == i_mark))
{
- return; // nothing to remove
+ return std::numeric_limits<size_t>::max(); // nothing to remove
}
else if (i_mark == m_xData->mnEmptyMark)
{
--m_xData->mnEmptyMark; // never returned from MarkTop => invalid
- return;
+ return std::numeric_limits<size_t>::max();
}
for ( size_t i=0; i<m_xData->maUndoArray.maUndoActions.size(); ++i )
@@ -1104,13 +1124,15 @@ void SfxUndoManager::RemoveMark( UndoStackMark const i_mark )
if (markPos != rAction.aMarks.end())
{
rAction.aMarks.erase( markPos );
- return;
+ return i;
}
}
SAL_WARN("svl", "SfxUndoManager::RemoveMark: mark not found!");
// TODO: this might be too offensive. There are situations where we implicitly remove marks
// without our clients, in particular the client which created the mark, having a chance to know
// about this.
+
+ return std::numeric_limits<size_t>::max();
}
bool SfxUndoManager::HasTopUndoActionMark( UndoStackMark const i_mark )
@@ -1130,6 +1152,16 @@ bool SfxUndoManager::HasTopUndoActionMark( UndoStackMark const i_mark )
}
+void SfxUndoManager::UndoMark(UndoStackMark i_mark)
+{
+ SfxMarkedUndoContext context(*this, i_mark); // Removes the mark
+ if (context.GetUndoOffset() == std::numeric_limits<size_t>::max())
+ return; // nothing to undo
+
+ UndoWithContext(context);
+}
+
+
void SfxUndoManager::RemoveOldestUndoAction()
{
UndoManagerGuard aGuard( *m_xData );