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
                             {

Reply via email to