diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2024-02-29 17:03:31 +0600 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2024-03-18 14:37:41 +0100 |
commit | 6c07558f71af485700f4cff8a4ce1723569efb2a (patch) | |
tree | 81df22d67d33000cfa8f113aeb1f3ff2173315a4 | |
parent | c5e0b00374bf9ad96c0ec3ab4d8f9ed76f2f2882 (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.hxx | 10 | ||||
-rw-r--r-- | sc/source/ui/drawfunc/fuins2.cxx | 1 | ||||
-rw-r--r-- | sc/source/ui/inc/tabvwsh.hxx | 6 | ||||
-rw-r--r-- | sc/source/ui/inc/undomanager.hxx | 1 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwshb.cxx | 21 | ||||
-rw-r--r-- | svl/source/undo/undo.cxx | 40 |
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 ); |