sc/qa/unit/tiledrendering/tiledrendering.cxx | 74 +++++++++++++++++++++++++++ sc/source/ui/inc/undomanager.hxx | 4 - sc/source/ui/undo/undobase.cxx | 15 ++++- sc/source/ui/view/tabvwshb.cxx | 5 + 4 files changed, 90 insertions(+), 8 deletions(-)
New commits: commit dd0761acb481f16627c841da08fde7bcb9399e48 Author: Noel Grandin <[email protected]> AuthorDate: Sun Jul 31 18:59:01 2022 +0200 Commit: Noel Grandin <[email protected]> CommitDate: Tue Aug 2 10:53:34 2022 +0200 sc, out of order undo: allow multiple actions from other view this is the calc equivalent of commit c88c2d40d1a4aebc46b25368b80c02bc2f136658 Date: Fri Nov 12 08:39:35 2021 +0100 sw, out of order undo: allow multiple actions from other views Change-Id: I5acbd1e1cacef7c2e2a549f4d2270e961f576a65 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137652 Tested-by: Jenkins Reviewed-by: Noel Grandin <[email protected]> (cherry picked from commit 3ccbfaaf95005a34ca64ad250463ef5ce8842f43) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137608 Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index 3007fad47529..327c7102eae1 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -132,6 +132,7 @@ public: void testInvalidEntrySave(); void testUndoReordering(); void testUndoReorderingRedo(); + void testUndoReorderingMulti(); CPPUNIT_TEST_SUITE(ScTiledRenderingTest); CPPUNIT_TEST(testRowColumnHeaders); @@ -191,6 +192,7 @@ public: CPPUNIT_TEST(testInvalidEntrySave); CPPUNIT_TEST(testUndoReordering); CPPUNIT_TEST(testUndoReorderingRedo); + CPPUNIT_TEST(testUndoReorderingMulti); CPPUNIT_TEST_SUITE_END(); private: @@ -3260,6 +3262,78 @@ void ScTiledRenderingTest::testUndoReorderingRedo() CPPUNIT_ASSERT_EQUAL(OUString("CC"), pDoc->GetString(ScAddress(0, 2, 0))); } +void ScTiledRenderingTest::testUndoReorderingMulti() +{ + comphelper::LibreOfficeKit::setActive(); + + ScModelObj* pModelObj = createDoc("empty.ods"); + CPPUNIT_ASSERT(pModelObj); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + ScUndoManager* pUndoManager = pDoc->GetUndoManager(); + CPPUNIT_ASSERT(pUndoManager); + CPPUNIT_ASSERT_EQUAL(std::size_t(0), pUndoManager->GetUndoActionCount()); + + // view #1 + int nView1 = SfxLokHelper::getView(); + ViewCallback aView1; + + // view #2 + SfxLokHelper::createView(); + int nView2 = SfxLokHelper::getView(); + pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + ViewCallback aView2; + + // text edit a cell in view #1 + SfxLokHelper::setView(nView1); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::RETURN); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(std::size_t(1), pUndoManager->GetUndoActionCount()); + + // text edit a different cell in view #2 + SfxLokHelper::setView(nView2); + ScTabViewShell* pView2 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); + pView2->SetCursor(0, 2); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'C', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'C', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'C', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'C', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::RETURN); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(std::size_t(2), pUndoManager->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("xx"), pDoc->GetString(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(OUString("CC"), pDoc->GetString(ScAddress(0, 2, 0))); + + // and another cell in view #2 + pView2->SetCursor(0, 3); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'D', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'D', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'D', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'D', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::RETURN); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(std::size_t(3), pUndoManager->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString("xx"), pDoc->GetString(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(OUString("CC"), pDoc->GetString(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(OUString("DD"), pDoc->GetString(ScAddress(0, 3, 0))); + + // View 1 presses undo + SfxLokHelper::setView(nView1); + dispatchCommand(mxComponent, ".uno:Undo", {}); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(std::size_t(2), pUndoManager->GetUndoActionCount()); + CPPUNIT_ASSERT_EQUAL(OUString(""), pDoc->GetString(ScAddress(0, 0, 0))); + CPPUNIT_ASSERT_EQUAL(OUString("CC"), pDoc->GetString(ScAddress(0, 2, 0))); + CPPUNIT_ASSERT_EQUAL(OUString("DD"), pDoc->GetString(ScAddress(0, 3, 0))); +} + } CPPUNIT_TEST_SUITE_REGISTRATION(ScTiledRenderingTest); diff --git a/sc/source/ui/inc/undomanager.hxx b/sc/source/ui/inc/undomanager.hxx index 585e32e5fee7..03168dfab980 100644 --- a/sc/source/ui/inc/undomanager.hxx +++ b/sc/source/ui/inc/undomanager.hxx @@ -20,9 +20,9 @@ public: /** * Checks if the topmost undo action owned by pView is independent from the topmost action undo - * action. + * action. Sets rOffset to the offset of that independent undo action on success. */ - bool IsViewUndoActionIndependent(const SfxViewShell* pView) const; + bool IsViewUndoActionIndependent(const SfxViewShell* pView, sal_uInt16& rOffset) const; /// Make these public using SdrUndoManager::UndoWithContext; diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx index 3a5fec1bf975..cc7b8069cfe5 100644 --- a/sc/source/ui/undo/undobase.cxx +++ b/sc/source/ui/undo/undobase.cxx @@ -621,7 +621,7 @@ ScUndoManager::~ScUndoManager() {} * Checks if the topmost undo action owned by pView is independent from the topmost action undo * action. */ -bool ScUndoManager::IsViewUndoActionIndependent(const SfxViewShell* pView) const +bool ScUndoManager::IsViewUndoActionIndependent(const SfxViewShell* pView, sal_uInt16& rOffset) const { if (GetUndoActionCount() <= 1) { @@ -641,10 +641,16 @@ bool ScUndoManager::IsViewUndoActionIndependent(const SfxViewShell* pView) const // Earlier undo action that belongs to the view, but is not the top one. const SfxUndoAction* pViewAction = nullptr; - const SfxUndoAction* pAction = GetUndoAction(1); - if (pAction->GetViewShellId() == nViewId) + size_t nOffset = 0; + for (size_t i = 0; i < GetUndoActionCount(); ++i) { - pViewAction = pAction; + const SfxUndoAction* pAction = GetUndoAction(i); + if (pAction->GetViewShellId() == nViewId) + { + pViewAction = pAction; + nOffset = i; + break; + } } if (!pViewAction) @@ -679,6 +685,7 @@ bool ScUndoManager::IsViewUndoActionIndependent(const SfxViewShell* pView) const } } + rOffset = nOffset; return true; } diff --git a/sc/source/ui/view/tabvwshb.cxx b/sc/source/ui/view/tabvwshb.cxx index cb58b0299069..249ad86abc87 100644 --- a/sc/source/ui/view/tabvwshb.cxx +++ b/sc/source/ui/view/tabvwshb.cxx @@ -756,11 +756,12 @@ void ScTabViewShell::ExecuteUndo(SfxRequest& rReq) ViewShellId nViewShellId = GetViewShellId(); if (pAction->GetViewShellId() != nViewShellId) { - if (pUndoManager->IsViewUndoActionIndependent(this)) + sal_uInt16 nOffset = 0; + if (pUndoManager->IsViewUndoActionIndependent(this, nOffset)) { // Execute the undo with an offset: don't undo the top action, but an // earlier one, since it's independent and that belongs to our view. - nUndoOffset = 1; + nUndoOffset += nOffset; } else {
