[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.1' - 2 commits - libreofficekit/qa sfx2/sdi sfx2/source sw/inc sw/qa sw/source

Miklos Vajna vmiklos at collabora.co.uk
Mon Aug 15 08:04:24 UTC 2016


 libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx |    5 +
 sfx2/sdi/sfx.sdi                                    |    4 -
 sfx2/source/control/dispatch.cxx                    |   18 ++++
 sfx2/source/view/lokhelper.cxx                      |   10 ++
 sw/inc/IDocumentUndoRedo.hxx                        |    5 +
 sw/qa/extras/tiledrendering/tiledrendering.cxx      |   78 ++++++++++++++++++++
 sw/source/core/inc/UndoManager.hxx                  |    4 +
 sw/source/core/undo/docundo.cxx                     |   15 +++
 sw/source/uibase/shells/basesh.cxx                  |   17 ++++
 9 files changed, 150 insertions(+), 6 deletions(-)

New commits:
commit d7ceb72ff0b1ce94118d3c85cdc7641e461e44a6
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Aug 10 17:42:54 2016 +0200

    sw undo: add a Repair argument to the .uno:Undo/Redo commands
    
    Undo/redo is limited to undo actions created by the same view in the LOK
    case, this argument removes this limit. This can be used by a client for
    "document repair" purposes, where undo/redo of others' changes is
    intentional.
    
    The sfx command dispatch has support for FASTCALL slots (a state
    function is not called, the command is always enabled) and also has
    support for state functions, but those functions only get the ID of the
    slots, not its parameters. What is needed here is a command that's
    disabled by default, but in case a Repair argument is used, then it's
    unconditionally enabled. So handle that case in the sfx dispatcher
    directly for now.
    
    Change-Id: I96c1130bf51abcdd722684b1fa4a8277f92fd555
    (cherry picked from commit e9bcd3475131b24b0b8818cfdfa256854ca5a59d)

diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
index 5b95e35..b52c256 100644
--- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
+++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
@@ -535,6 +535,11 @@ static void documentRepair(GtkWidget* pButton, gpointer /*pItem*/)
             boost::property_tree::ptree aTree;
             aTree.put(boost::property_tree::ptree::path_type(aKey + "/type", '/'), "unsigned short");
             aTree.put(boost::property_tree::ptree::path_type(aKey + "/value", '/'), nIndex + 1);
+
+            // Without this, we could only undo our own commands.
+            aTree.put(boost::property_tree::ptree::path_type("Repair/type", '/'), "boolean");
+            aTree.put(boost::property_tree::ptree::path_type("Repair/value", '/'), true);
+
             std::stringstream aStream;
             boost::property_tree::write_json(aStream, aTree);
             std::string aArguments = aStream.str();
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index 82838ee..aedca15 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -4724,7 +4724,7 @@ SfxBoolItem MacroRecordingFloat SID_RECORDING_FLOATWINDOW
 
 
 SfxVoidItem Redo SID_REDO
-( SfxUInt16Item Redo SID_REDO )
+( SfxUInt16Item Redo SID_REDO, SfxBoolItem Repair SID_REPAIRPACKAGE )
 [
     /* flags: */
     AutoUpdate = FALSE,
@@ -6228,7 +6228,7 @@ SfxVoidItem BasicIDEShowWindow SID_BASICIDE_SHOWWINDOW
 
 
 SfxVoidItem Undo SID_UNDO
-( SfxUInt16Item Undo SID_UNDO )
+( SfxUInt16Item Undo SID_UNDO, SfxBoolItem Repair SID_REPAIRPACKAGE )
 [
     /* flags: */
     AutoUpdate = FALSE,
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx
index c0a35de..bd0b86b 100644
--- a/sfx2/source/control/dispatch.cxx
+++ b/sfx2/source/control/dispatch.cxx
@@ -214,6 +214,22 @@ bool SfxDispatcher::IsAppDispatcher() const
     return !xImp->pFrame;
 }
 
+/// Decides if the request is FASTCALL or not, depending on arguments.
+bool lcl_IsConditionalFastCall(SfxRequest &rReq)
+{
+    sal_uInt16 nId = rReq.GetSlot();
+    bool bRet = false;
+
+    if (nId == SID_UNDO || nId == SID_REDO)
+    {
+        const SfxItemSet* pArgs = rReq.GetArgs();
+        if (pArgs && pArgs->HasItem(SID_REPAIRPACKAGE))
+            bRet = true;
+    }
+
+    return bRet;
+}
+
 /** Helper function to check whether a slot can be executed and
     check the execution itself
 */
@@ -222,7 +238,7 @@ void SfxDispatcher::Call_Impl(SfxShell& rShell, const SfxSlot &rSlot, SfxRequest
     SFX_STACK(SfxDispatcher::Call_Impl);
 
     // The slot may be called (meaning enabled)
-    if ( rSlot.IsMode(SfxSlotMode::FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) )
+    if ( rSlot.IsMode(SfxSlotMode::FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) || lcl_IsConditionalFastCall(rReq))
     {
         if ( GetFrame() )
         {
diff --git a/sw/inc/IDocumentUndoRedo.hxx b/sw/inc/IDocumentUndoRedo.hxx
index 6c044f6..2266f30 100644
--- a/sw/inc/IDocumentUndoRedo.hxx
+++ b/sw/inc/IDocumentUndoRedo.hxx
@@ -64,6 +64,11 @@ public:
      */
     virtual bool DoesDrawUndo() const = 0;
 
+    /// Enable repair mode.
+    virtual void DoRepair(bool bRepair) = 0;
+    /// Is repair mode active?
+    virtual bool DoesRepair() const = 0;
+
     /** Set the position at which the document is in the "unmodified" state
         to the current position in the Undo stack.
     */
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index 1447248..a51d0c8 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -63,6 +63,7 @@ public:
     void testUndoInvalidations();
     void testUndoLimiting();
     void testUndoDispatch();
+    void testUndoRepairDispatch();
     void testShapeTextUndoShells();
     void testShapeTextUndoGroupShells();
 
@@ -92,6 +93,7 @@ public:
     CPPUNIT_TEST(testUndoInvalidations);
     CPPUNIT_TEST(testUndoLimiting);
     CPPUNIT_TEST(testUndoDispatch);
+    CPPUNIT_TEST(testUndoRepairDispatch);
     CPPUNIT_TEST(testShapeTextUndoShells);
     CPPUNIT_TEST(testShapeTextUndoGroupShells);
     CPPUNIT_TEST_SUITE_END();
@@ -961,6 +963,45 @@ void SwTiledRenderingTest::testUndoDispatch()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void SwTiledRenderingTest::testUndoRepairDispatch()
+{
+    // Load a document and create two views.
+    comphelper::LibreOfficeKit::setActive();
+    SwXTextDocument* pXTextDocument = createDoc("dummy.fodt");
+    int nView1 = SfxLokHelper::getView();
+    SfxLokHelper::createView();
+    pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+    int nView2 = SfxLokHelper::getView();
+
+    // Insert a character in the first view.
+    SfxLokHelper::setView(nView1);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
+
+    // Assert that by default the second view can't undo the action.
+    SfxLokHelper::setView(nView2);
+    SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc();
+    sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount());
+    comphelper::dispatchCommand(".uno:Undo", {});
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount());
+
+    // But the same is allowed in repair mode.
+    SfxLokHelper::setView(nView2);
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount());
+    uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence(
+    {
+        {"Repair", uno::makeAny(true)}
+    }));
+    comphelper::dispatchCommand(".uno:Undo", aPropertyValues);
+    Scheduler::ProcessEventsToIdle();
+    // This was 1: repair mode couldn't undo the action, either.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rUndoManager.GetUndoActionCount());
+
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 void SwTiledRenderingTest::testShapeTextUndoShells()
 {
     // Load a document and create a view.
diff --git a/sw/source/core/inc/UndoManager.hxx b/sw/source/core/inc/UndoManager.hxx
index 5092e95..0013262 100644
--- a/sw/source/core/inc/UndoManager.hxx
+++ b/sw/source/core/inc/UndoManager.hxx
@@ -49,6 +49,8 @@ public:
     virtual bool DoesGroupUndo() const override;
     virtual void DoDrawUndo(bool const bDoUndo) override;
     virtual bool DoesDrawUndo() const override;
+    void DoRepair(bool bRepair) override;
+    bool DoesRepair() const override;
     virtual void SetUndoNoModifiedPosition() override;
     virtual void LockUndoNoModifiedPosition() override;
     virtual void UnLockUndoNoModifiedPosition() override;
@@ -100,6 +102,8 @@ private:
 
     bool m_bGroupUndo       : 1;    // TRUE: Undo grouping enabled
     bool m_bDrawUndo        : 1;    // TRUE: Draw Undo enabled
+    /// If true, then repair mode is enabled.
+    bool m_bRepair;
     bool m_bLockUndoNoModifiedPosition : 1;
     /// position in Undo-Array at which Doc was saved (and is not modified)
     UndoStackMark m_UndoSaveMark;
diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx
index 46a6693..943de4b 100644
--- a/sw/source/core/undo/docundo.cxx
+++ b/sw/source/core/undo/docundo.cxx
@@ -58,6 +58,7 @@ UndoManager::UndoManager(std::shared_ptr<SwNodes> xUndoNodes,
     ,   m_xUndoNodes(xUndoNodes)
     ,   m_bGroupUndo(true)
     ,   m_bDrawUndo(true)
+    ,   m_bRepair(false)
     ,   m_bLockUndoNoModifiedPosition(false)
     ,   m_UndoSaveMark(MARK_INVALID)
 {
@@ -138,6 +139,16 @@ bool UndoManager::DoesDrawUndo() const
     return m_bDrawUndo;
 }
 
+void UndoManager::DoRepair(bool bRepair)
+{
+    m_bRepair = bRepair;
+}
+
+bool UndoManager::DoesRepair() const
+{
+    return m_bRepair;
+}
+
 bool UndoManager::IsUndoNoResetModified() const
 {
     return MARK_INVALID == m_UndoSaveMark;
@@ -308,7 +319,7 @@ UndoManager::GetLastUndoInfo(
 
     SfxUndoAction *const pAction( SdrUndoManager::GetUndoAction() );
 
-    if (comphelper::LibreOfficeKit::isActive())
+    if (comphelper::LibreOfficeKit::isActive() && !m_bRepair)
     {
         // If an other view created the undo action, prevent undoing it from this view.
         sal_Int32 nViewShellId = pView ? pView->GetViewShellId() : m_pDocShell->GetView()->GetViewShellId();
@@ -361,7 +372,7 @@ bool UndoManager::GetFirstRedoInfo(OUString *const o_pStr,
         return false;
     }
 
-    if (comphelper::LibreOfficeKit::isActive())
+    if (comphelper::LibreOfficeKit::isActive() && !m_bRepair)
     {
         // If an other view created the undo action, prevent redoing it from this view.
         sal_Int32 nViewShellId = pView ? pView->GetViewShellId() : m_pDocShell->GetView()->GetViewShellId();
diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx
index 4d3b743..8400b0b 100644
--- a/sw/source/uibase/shells/basesh.cxx
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -94,6 +94,7 @@
 #include <fmtinfmt.hxx>
 #include <doc.hxx>
 #include <IDocumentSettingAccess.hxx>
+#include <IDocumentUndoRedo.hxx>
 #include "swabstdlg.hxx"
 #include "dialog.hrc"
 #include "fldui.hrc"
@@ -108,8 +109,8 @@
 #include <com/sun/star/gallery/GalleryItemType.hpp>
 #include <memory>
 
-//UUUU
 #include <svx/unobrushitemhelper.hxx>
+#include <comphelper/scopeguard.hxx>
 
 FlyMode SwBaseShell::eFrameMode = FLY_DRAG_END;
 
@@ -482,9 +483,23 @@ void SwBaseShell::ExecUndo(SfxRequest &rReq)
     if( pArgs && SfxItemState::SET == pArgs->GetItemState( nId, false, &pItem ))
         nCnt = 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 (pArgs && pArgs->GetItemState(SID_REPAIRPACKAGE, false, &pItem) == SfxItemState::SET)
+        bRepair = static_cast<const SfxBoolItem*>(pItem)->GetValue();
+
     // #i106349#: save pointer: undo/redo may delete the shell, i.e., this!
     SfxViewFrame *const pViewFrame( GetView().GetViewFrame() );
 
+    IDocumentUndoRedo& rUndoRedo = rWrtShell.GetIDocumentUndoRedo();
+    bool bWasRepair = rUndoRedo.DoesRepair();
+    rUndoRedo.DoRepair(bRepair);
+    comphelper::ScopeGuard aGuard([&rUndoRedo, bWasRepair]()
+    {
+        rUndoRedo.DoRepair(bWasRepair);
+    });
+
     switch( nId )
     {
         case SID_UNDO:
commit 01e160686140299002df52e76dc8e3411c6e01c2
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Aug 10 15:51:51 2016 +0200

    sfx2: make SfxLokHelper::setView() set also the active frame
    
    Without this, comphelper::dispatchCommand() doesn't work on the current
    frame. This causes e.g. undo not working when only a given view is
    allowed to do undo.
    
    In the desktop case vcl::Window::ImplGrabFocus() calls both
    SfxViewFrame::MakeActive_Impl() and
    framework::Desktop::setActiveFrame(), but in the LOK case the first was
    called directly, that's how the active frame was outdated.
    
    Change-Id: If97a9de316b4c8dd49e55cd273bdb2dfe9866f38
    Reviewed-on: https://gerrit.libreoffice.org/28032
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>
    Tested-by: Jenkins <ci at libreoffice.org>
    (cherry picked from commit d6e8d4f773d970b69baedd8523a426f18a8d8eef)

diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 856a007..4113160 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -11,12 +11,17 @@
 
 #include <boost/property_tree/json_parser.hpp>
 
+#include <com/sun/star/frame/Desktop.hpp>
+
+#include <comphelper/processfactory.hxx>
 #include <sfx2/viewsh.hxx>
 #include <sfx2/request.hxx>
 #include <sfx2/viewfrm.hxx>
 
 #include <shellimpl.hxx>
 
+using namespace com::sun::star;
+
 int SfxLokHelper::createView()
 {
     SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst();
@@ -59,6 +64,11 @@ void SfxLokHelper::setView(int nId)
 
             SfxViewFrame* pViewFrame = pViewShell->GetViewFrame();
             pViewFrame->MakeActive_Impl(false);
+
+            // Make comphelper::dispatchCommand() find the correct frame.
+            uno::Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface();
+            uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(comphelper::getProcessComponentContext());
+            xDesktop->setActiveFrame(xFrame);
             return;
         }
     }
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index cba7997..1447248 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -62,6 +62,7 @@ public:
     void testTextEditViewInvalidations();
     void testUndoInvalidations();
     void testUndoLimiting();
+    void testUndoDispatch();
     void testShapeTextUndoShells();
     void testShapeTextUndoGroupShells();
 
@@ -90,6 +91,7 @@ public:
     CPPUNIT_TEST(testTextEditViewInvalidations);
     CPPUNIT_TEST(testUndoInvalidations);
     CPPUNIT_TEST(testUndoLimiting);
+    CPPUNIT_TEST(testUndoDispatch);
     CPPUNIT_TEST(testShapeTextUndoShells);
     CPPUNIT_TEST(testShapeTextUndoGroupShells);
     CPPUNIT_TEST_SUITE_END();
@@ -924,6 +926,41 @@ void SwTiledRenderingTest::testUndoLimiting()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void SwTiledRenderingTest::testUndoDispatch()
+{
+    // Load a document and create two views.
+    comphelper::LibreOfficeKit::setActive();
+    SwXTextDocument* pXTextDocument = createDoc("dummy.fodt");
+    int nView1 = SfxLokHelper::getView();
+    SfxLokHelper::createView();
+    pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+    int nView2 = SfxLokHelper::getView();
+
+    // Insert a character in the first view.
+    SfxLokHelper::setView(nView1);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
+
+    // Click before the first word in the second view.
+    SfxLokHelper::setView(nView2);
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false);
+    Point aStart = pShellCursor->GetSttPos();
+    aStart.setX(aStart.getX() - 1000);
+    pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aStart.getX(), aStart.getY(), 1, MOUSE_LEFT, 0);
+    pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aStart.getX(), aStart.getY(), 1, MOUSE_LEFT, 0);
+    uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(comphelper::getProcessComponentContext());
+    uno::Reference<frame::XFrame> xFrame2 = xDesktop->getActiveFrame();
+
+    // Now switch back to the first view, and make sure that the active frame is updated.
+    SfxLokHelper::setView(nView1);
+    uno::Reference<frame::XFrame> xFrame1 = xDesktop->getActiveFrame();
+    // This failed: setView() did not update the active frame.
+    CPPUNIT_ASSERT(xFrame1 != xFrame2);
+
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 void SwTiledRenderingTest::testShapeTextUndoShells()
 {
     // Load a document and create a view.


More information about the Libreoffice-commits mailing list