summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorMarco Cecchetti <marco.cecchetti@collabora.com>2017-01-06 18:35:08 +0100
committerMarco Cecchetti <mrcekets@gmail.com>2017-03-29 18:39:23 +0000
commitfc97021142786298418d80e0ed9634908b0ba9d7 (patch)
treee3a216e1a73301d309b6db9f3f2776168046e380 /sc
parent9ec6519650280c8cda33ff921926d42840ef89c6 (diff)
LOK: Calc: limiting undo and add support for repair mode
During collaborative editing changes can be undone regardless of who made them. This patch avoids this possibility and introduce support for repair mode, for cases where undo/redo of others' changes is intentional. Change-Id: I69fd435e96c4c675ffd1df81e936b5eae109daa0 Reviewed-on: https://gerrit.libreoffice.org/33223 Reviewed-by: Jan Holesovsky <kendy@collabora.com> Tested-by: Jenkins <ci@libreoffice.org>
Diffstat (limited to 'sc')
-rw-r--r--sc/qa/unit/tiledrendering/tiledrendering.cxx133
-rw-r--r--sc/source/ui/view/tabvwshb.cxx28
2 files changed, 161 insertions, 0 deletions
diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 6186ab9964ce..2510d161387a 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -77,6 +77,8 @@ public:
void testInvalidateOnCopyPasteCells();
void testInvalidateOnInserRowCol();
void testCommentCallback();
+ void testUndoLimiting();
+ void testUndoRepairDispatch();
CPPUNIT_TEST_SUITE(ScTiledRenderingTest);
CPPUNIT_TEST(testRowColumnSelections);
@@ -99,6 +101,8 @@ public:
CPPUNIT_TEST(testInvalidateOnCopyPasteCells);
CPPUNIT_TEST(testInvalidateOnInserRowCol);
CPPUNIT_TEST(testCommentCallback);
+ CPPUNIT_TEST(testUndoLimiting);
+ CPPUNIT_TEST(testUndoRepairDispatch);
CPPUNIT_TEST_SUITE_END();
private:
@@ -1135,6 +1139,135 @@ void ScTiledRenderingTest::testCommentCallback()
comphelper::LibreOfficeKit::setActive(false);
}
+void ScTiledRenderingTest::testUndoLimiting()
+{
+ comphelper::LibreOfficeKit::setActive();
+
+ ScModelObj* pModelObj = createDoc("small.ods");
+ CPPUNIT_ASSERT(pModelObj);
+ ScDocument* pDoc = pModelObj->GetDocument();
+ CPPUNIT_ASSERT(pDoc);
+ SfxUndoManager* pUndoManager = pDoc->GetUndoManager();
+ CPPUNIT_ASSERT(pUndoManager);
+
+ // view #1
+ ViewCallback aView1;
+ int nView1 = SfxLokHelper::getView();
+ SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1);
+
+ // view #2
+ SfxLokHelper::createView();
+ ViewCallback aView2;
+ int nView2 = SfxLokHelper::getView();
+ pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+ SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &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, 0, awt::Key::RETURN);
+ pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN);
+ Scheduler::ProcessEventsToIdle();
+
+ // check that undo action count in not 0
+ CPPUNIT_ASSERT(pUndoManager->GetUndoActionCount() == 1);
+
+ // try to execute undo in view #2
+ SfxLokHelper::setView(nView2);
+ comphelper::dispatchCommand(".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+ // check that undo has not been executed on view #2
+ CPPUNIT_ASSERT(pUndoManager->GetUndoActionCount() == 1);
+
+ // try to execute undo in view #1
+ SfxLokHelper::setView(nView1);
+ comphelper::dispatchCommand(".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+ // check that undo has been executed on view #1
+ CPPUNIT_ASSERT(pUndoManager->GetUndoActionCount() == 0);
+
+ // check that redo action count in not 0
+ CPPUNIT_ASSERT(pUndoManager->GetRedoActionCount() == 1);
+
+ // try to execute redo in view #2
+ SfxLokHelper::setView(nView2);
+ comphelper::dispatchCommand(".uno:Redo", {});
+ Scheduler::ProcessEventsToIdle();
+ // check that redo has not been executed on view #2
+ CPPUNIT_ASSERT(pUndoManager->GetRedoActionCount() == 1);
+
+ // try to execute redo in view #1
+ SfxLokHelper::setView(nView1);
+ comphelper::dispatchCommand(".uno:Redo", {});
+ Scheduler::ProcessEventsToIdle();
+ // check that redo has been executed on view #1
+ CPPUNIT_ASSERT(pUndoManager->GetRedoActionCount() == 0);
+
+ mxComponent->dispose();
+ mxComponent.clear();
+
+ comphelper::LibreOfficeKit::setActive(false);
+}
+
+void ScTiledRenderingTest::testUndoRepairDispatch()
+{
+ comphelper::LibreOfficeKit::setActive();
+
+ ScModelObj* pModelObj = createDoc("small.ods");
+ CPPUNIT_ASSERT(pModelObj);
+ ScDocument* pDoc = pModelObj->GetDocument();
+ CPPUNIT_ASSERT(pDoc);
+ SfxUndoManager* pUndoManager = pDoc->GetUndoManager();
+ CPPUNIT_ASSERT(pUndoManager);
+
+ // view #1
+ ViewCallback aView1;
+ int nView1 = SfxLokHelper::getView();
+ SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1);
+
+ // view #2
+ SfxLokHelper::createView();
+ ViewCallback aView2;
+ int nView2 = SfxLokHelper::getView();
+ pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+ SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &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, 0, awt::Key::RETURN);
+ pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::RETURN);
+ Scheduler::ProcessEventsToIdle();
+
+ // check that undo action count in not 0
+ CPPUNIT_ASSERT(pUndoManager->GetUndoActionCount() == 1);
+
+ // try to execute undo in view #2
+ SfxLokHelper::setView(nView2);
+ comphelper::dispatchCommand(".uno:Undo", {});
+ Scheduler::ProcessEventsToIdle();
+ // check that undo has not been executed on view #2
+ CPPUNIT_ASSERT(pUndoManager->GetUndoActionCount() == 1);
+
+ // try to execute undo in view #2 in repair mode
+ SfxLokHelper::setView(nView2);
+ uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
+ {
+ {"Repair", uno::makeAny(true)}
+ }));
+ comphelper::dispatchCommand(".uno:Undo", aPropertyValues);
+ Scheduler::ProcessEventsToIdle();
+ // check that undo has been executed on view #2 in repair mode
+ CPPUNIT_ASSERT(pUndoManager->GetUndoActionCount() == 0);
+
+ mxComponent->dispose();
+ mxComponent.clear();
+
+ comphelper::LibreOfficeKit::setActive(false);
+}
+
}
CPPUNIT_TEST_SUITE_REGISTRATION(ScTiledRenderingTest);
diff --git a/sc/source/ui/view/tabvwshb.cxx b/sc/source/ui/view/tabvwshb.cxx
index 23b1ec9532de..ee81fab78563 100644
--- a/sc/source/ui/view/tabvwshb.cxx
+++ b/sc/source/ui/view/tabvwshb.cxx
@@ -62,6 +62,7 @@
#include <tools/urlobj.hxx>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <comphelper/lok.hxx>
using namespace com::sun::star;
@@ -522,6 +523,33 @@ void ScTabViewShell::ExecuteUndo(SfxRequest& rReq)
if ( pReqArgs && pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
nCount = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
+ // Repair mode: allow undo/redo of all undo actions, even if access would
+ // be limited based on the view shell ID.
+ bool bRepair = false;
+ if (pReqArgs && pReqArgs->GetItemState(SID_REPAIRPACKAGE, false, &pItem) == SfxItemState::SET)
+ bRepair = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+
+ if (comphelper::LibreOfficeKit::isActive() && !bRepair)
+ {
+ SfxUndoAction* pAction = nullptr;
+ if (bIsUndo)
+ {
+ if (pUndoManager->GetUndoActionCount() != 0)
+ pAction = pUndoManager->GetUndoAction();
+ }
+ else
+ {
+ if (pUndoManager->GetRedoActionCount() != 0)
+ pAction = pUndoManager->GetRedoAction();
+ }
+ if (pAction)
+ {
+ ViewShellId nViewShellId = GetViewShellId();
+ if (pAction->GetViewShellId() != nViewShellId)
+ return;
+ }
+ }
+
// lock paint for more than one cell undo action (not for editing within a cell)
bool bLockPaint = ( nCount > 1 && pUndoManager == GetUndoManager() );
if ( bLockPaint )