[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.3' - desktop/source include/sfx2 include/svl include/svx sc/qa sc/source sd/qa sd/source sfx2/sdi sfx2/source svl/source svx/source sw/qa sw/source

Henry Castro hcastro at collabora.com
Thu Jan 18 12:35:16 UTC 2018


 desktop/source/lib/init.cxx                    |    3 -
 include/sfx2/sfxsids.hrc                       |    2 
 include/svl/hint.hxx                           |    1 
 include/svl/undo.hxx                           |   10 +++-
 include/svx/sdrundomanager.hxx                 |    5 ++
 sc/qa/unit/tiledrendering/tiledrendering.cxx   |   51 +++++++++++++++++++++++++
 sc/source/core/data/document.cxx               |    5 +-
 sd/qa/unit/tiledrendering/tiledrendering.cxx   |   51 +++++++++++++++++++++++++
 sd/source/ui/docshell/docshell.cxx             |    6 ++
 sfx2/sdi/docslots.sdi                          |    4 +
 sfx2/sdi/sfx.sdi                               |   19 +++++++++
 sfx2/source/control/unoctitm.cxx               |    3 -
 sfx2/source/doc/objserv.cxx                    |   10 ++++
 sfx2/source/view/viewfrm.cxx                   |    6 ++
 svl/source/undo/undo.cxx                       |   39 +++++++++++++++++++
 svx/source/svdraw/sdrundomanager.cxx           |   16 +++++++
 sw/qa/extras/tiledrendering/tiledrendering.cxx |   48 +++++++++++++++++++++++
 sw/source/core/inc/UndoManager.hxx             |    3 +
 sw/source/core/undo/docundo.cxx                |    8 +++
 19 files changed, 280 insertions(+), 10 deletions(-)

New commits:
commit e3c1713807499fdbe63fad0944d0ce3b91b28637
Author: Henry Castro <hcastro at collabora.com>
Date:   Sat Jun 17 13:52:15 2017 -0400

    lokit: add .uno:DocumentRepair command
    
    Change-Id: I5b13ea6f4785bc91c29111fa63c4a1b0ea9b2660
    Reviewed-on: https://gerrit.libreoffice.org/38908
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Henry Castro <hcastro at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/47915
    Reviewed-by: Jan Holesovsky <kendy at collabora.com>
    Tested-by: Jan Holesovsky <kendy at collabora.com>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index a993a3a30a90..9cd6337fc395 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -1770,7 +1770,8 @@ static void doc_iniUnoCommands ()
         OUString(".uno:FontDialog"),
         OUString(".uno:ParagraphDialog"),
         OUString(".uno:OutlineBullet"),
-        OUString(".uno:InsertIndexesEntry")
+        OUString(".uno:InsertIndexesEntry"),
+        OUString(".uno:DocumentRepair")
     };
 
     util::URL aCommandURL;
diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index 20afe0808bc2..d5620c01e9dd 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -258,7 +258,7 @@
 //      SID_SFX_free_END                    (SID_SFX_START + 3999)
 
 #define SID_OPEN_NEW_VIEW                   (SID_SFX_START + 520)
-    // FREE, was SID_VIEW_ZOOM_MODE
+#define SID_DOC_REPAIR                      (SID_SFX_START + 521)
     // FREE, was SID_VIEW_POS_SIZE
 #define SID_VIEW_ID                         (SID_SFX_START + 523)
     // FREE, was SID_USER_DATA
diff --git a/include/svl/hint.hxx b/include/svl/hint.hxx
index e3f0e2672ef4..3e7b748c3b49 100644
--- a/include/svl/hint.hxx
+++ b/include/svl/hint.hxx
@@ -32,6 +32,7 @@
 #define SFX_HINT_MODECHANGED        0x00000080
 #define SFX_HINT_LANGUAGECHANGED    0x00000100
 #define SFX_HINT_REDLINECHANGED     0x00000200
+#define SFX_HINT_DOCREPAIR          0x00000400
     // unused, formerly SFX_HINT_CANCELLABLE
     // unused, formerly SFX_HINT_DATAAVAILABLE
     // unused, formerly SFX_HINT_SAVECOMPLETED
diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx
index 52a2918afd36..532d2f161db2 100644
--- a/include/svl/undo.hxx
+++ b/include/svl/undo.hxx
@@ -291,6 +291,7 @@ namespace svl
         /// adds a new listener to be notified about changes in the UndoManager's state
         virtual void            AddUndoListener( SfxUndoListener& i_listener ) = 0;
         virtual void            RemoveUndoListener( SfxUndoListener& i_listener ) = 0;
+        virtual bool            IsEmptyActions() const = 0;
    };
 }
 
@@ -342,6 +343,8 @@ public:
     virtual bool            IsUndoEnabled() const override;
     virtual void            AddUndoListener( SfxUndoListener& i_listener ) override;
     virtual void            RemoveUndoListener( SfxUndoListener& i_listener ) override;
+    virtual bool            IsEmptyActions() const override;
+
 
     /** marks the current top-level element of the Undo stack, and returns a unique ID for it
     */
@@ -378,6 +381,7 @@ protected:
         undo actions on the then-current level are removed, too. This is continued until the top level is reached.
     */
     void    ClearAllLevels();
+    virtual void EmptyActionsChanged();
 
 private:
     size_t  ImplLeaveListAction( const bool i_merge, ::svl::undo::impl::UndoManagerGuard& i_guard );
@@ -390,8 +394,10 @@ private:
     bool    ImplIsInListAction_Lock() const;
     void    ImplEnableUndo_Lock( bool const i_enable );
 
-    bool ImplUndo( SfxUndoContext* i_contextOrNull );
-    bool ImplRedo( SfxUndoContext* i_contextOrNull );
+    bool    ImplUndo( SfxUndoContext* i_contextOrNull );
+    bool    ImplRedo( SfxUndoContext* i_contextOrNull );
+    void    ImplCheckEmptyActions();
+    inline  bool    ImplIsEmptyActions() const;
 
     friend class ::svl::undo::impl::LockGuard;
 };
diff --git a/include/svx/sdrundomanager.hxx b/include/svx/sdrundomanager.hxx
index 2add5cac9553..762fe7b0bcfb 100644
--- a/include/svx/sdrundomanager.hxx
+++ b/include/svx/sdrundomanager.hxx
@@ -24,6 +24,8 @@
 #include <editeng/editund2.hxx>
 #include <tools/link.hxx>
 
+class SfxObjectShell;
+
 class SVX_DLLPUBLIC SdrUndoManager : public EditUndoManager
 {
 private:
@@ -35,8 +37,10 @@ private:
     bool            mbEndTextEditTriggeredFromUndo;
 
 protected:
+    SfxObjectShell* m_pDocSh;
     // call to check for TextEdit active
     bool isTextEditActive() const;
+    virtual void EmptyActionsChanged() override;
 
 public:
     SdrUndoManager(sal_uInt16 nMaxUndoActionCount = 20);
@@ -59,6 +63,7 @@ public:
     // is needed to detect inside end text edit if it is a regular one or triggered
     // by a last undo during text edit
     bool isEndTextEditTriggeredFromUndo() { return mbEndTextEditTriggeredFromUndo; }
+    void SetDocShell(SfxObjectShell* pDocShell);
 };
 
 #endif // INCLUDED_SVX_SDRUNDOMANAGER_HXX
diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 53d96494ad75..f8357435f0e3 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -78,6 +78,7 @@ public:
     void testInsertGraphicInvalidations();
     void testDocumentSizeWithTwoViews();
     void testDisableUndoRepair();
+    void testDocumentRepair();
     void testLanguageStatus();
     void testMultiViewCopyPaste();
 
@@ -107,6 +108,7 @@ public:
     CPPUNIT_TEST(testInsertGraphicInvalidations);
     CPPUNIT_TEST(testDocumentSizeWithTwoViews);
     CPPUNIT_TEST(testDisableUndoRepair);
+    CPPUNIT_TEST(testDocumentRepair);
     CPPUNIT_TEST(testLanguageStatus);
     CPPUNIT_TEST(testMultiViewCopyPaste);
     CPPUNIT_TEST_SUITE_END();
@@ -1420,6 +1422,55 @@ void ScTiledRenderingTest::testDisableUndoRepair()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void ScTiledRenderingTest::testDocumentRepair()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    // Create two views.
+    ScModelObj* pModelObj = createDoc("cursor-away.ods");
+    CPPUNIT_ASSERT(pModelObj);
+
+    // view #1
+    SfxViewShell* pView1 = SfxViewShell::Current();
+
+    // view #2
+    SfxLokHelper::createView();
+    SfxViewShell* pView2 = SfxViewShell::Current();
+    int nView2 = SfxLokHelper::getView();
+    CPPUNIT_ASSERT(pView1 != pView2);
+    {
+        std::unique_ptr<SfxPoolItem> pItem1;
+        std::unique_ptr<SfxPoolItem> pItem2;
+        pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem1);
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem2);
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem1.get()));
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem2.get()));
+        CPPUNIT_ASSERT_EQUAL(false, dynamic_cast< const SfxBoolItem* >(pItem1.get())->GetValue());
+        CPPUNIT_ASSERT_EQUAL(false, dynamic_cast< const SfxBoolItem* >(pItem2.get())->GetValue());
+    }
+
+    // Insert a character in the second view.
+    SfxLokHelper::setView(nView2);
+    pModelObj->setPart(1);
+    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();
+    {
+        std::unique_ptr<SfxPoolItem> pItem1;
+        std::unique_ptr<SfxPoolItem> pItem2;
+        pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem1);
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem2);
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem1.get()));
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem2.get()));
+        CPPUNIT_ASSERT_EQUAL(true, dynamic_cast< const SfxBoolItem* >(pItem1.get())->GetValue());
+        CPPUNIT_ASSERT_EQUAL(true, dynamic_cast< const SfxBoolItem* >(pItem2.get())->GetValue());
+    }
+
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 void ScTiledRenderingTest::testLanguageStatus()
 {
     comphelper::LibreOfficeKit::setActive();
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 4c5084f8d752..2b4bf337f40b 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6256,8 +6256,9 @@ SfxUndoManager* ScDocument::GetUndoManager()
 {
     if (!mpUndoManager)
     {
-        // to support enhanced text edit for draw objects, use an SdrUndoManager
-        mpUndoManager = new SdrUndoManager;
+        SdrUndoManager* pUndoManager = new SdrUndoManager;
+        pUndoManager->SetDocShell(GetDocumentShell());
+        mpUndoManager = pUndoManager;
     }
 
     return mpUndoManager;
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 03d756e5a260..8d624dc70c48 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -98,6 +98,7 @@ public:
     void testCommentCallbacks();
     void testMultiViewInsertDeletePage();
     void testDisableUndoRepair();
+    void testDocumentRepair();
     void testLanguageStatus();
     void testDefaultView();
 
@@ -137,6 +138,7 @@ public:
     CPPUNIT_TEST(testCommentCallbacks);
     CPPUNIT_TEST(testMultiViewInsertDeletePage);
     CPPUNIT_TEST(testDisableUndoRepair);
+    CPPUNIT_TEST(testDocumentRepair);
     CPPUNIT_TEST(testLanguageStatus);
     CPPUNIT_TEST(testDefaultView);
 
@@ -1825,6 +1827,55 @@ void SdTiledRenderingTest::testDisableUndoRepair()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void SdTiledRenderingTest::testDocumentRepair()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    // Create two views.
+    SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+    CPPUNIT_ASSERT(pXImpressDocument);
+
+    // view #1
+    SfxViewShell* pView1 = SfxViewShell::Current();
+
+    // view #2
+    SfxLokHelper::createView();
+    SfxViewShell* pView2 = SfxViewShell::Current();
+    int nView2 = SfxLokHelper::getView();
+    CPPUNIT_ASSERT(pView1 != pView2);
+    {
+        std::unique_ptr<SfxPoolItem> pItem1;
+        std::unique_ptr<SfxPoolItem> pItem2;
+        pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem1);
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem2);
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem1.get()));
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem2.get()));
+        CPPUNIT_ASSERT_EQUAL(false, dynamic_cast< const SfxBoolItem* >(pItem1.get())->GetValue());
+        CPPUNIT_ASSERT_EQUAL(false, dynamic_cast< const SfxBoolItem* >(pItem2.get())->GetValue());
+    }
+
+    // Insert a character in the second view.
+    SfxLokHelper::setView(nView2);
+    pXImpressDocument->setPart(1);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
+    Scheduler::ProcessEventsToIdle();
+    {
+        std::unique_ptr<SfxPoolItem> pItem1;
+        std::unique_ptr<SfxPoolItem> pItem2;
+        pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem1);
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem2);
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem1.get()));
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem2.get()));
+        CPPUNIT_ASSERT_EQUAL(true, dynamic_cast< const SfxBoolItem* >(pItem1.get())->GetValue());
+        CPPUNIT_ASSERT_EQUAL(true, dynamic_cast< const SfxBoolItem* >(pItem2.get())->GetValue());
+    }
+
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 void SdTiledRenderingTest::testLanguageStatus()
 {
     // Load the document.
diff --git a/sd/source/ui/docshell/docshell.cxx b/sd/source/ui/docshell/docshell.cxx
index 0ec666309be0..eebff1427171 100644
--- a/sd/source/ui/docshell/docshell.cxx
+++ b/sd/source/ui/docshell/docshell.cxx
@@ -113,7 +113,11 @@ void DrawDocShell::Construct( bool bClipboard )
 
     SetBaseModel( new SdXImpressDocument( this, bClipboard ) );
     SetPool( &mpDoc->GetItemPool() );
-    mpUndoManager = new sd::UndoManager;
+
+    sd::UndoManager* pUndoManager = new sd::UndoManager;
+    pUndoManager->SetDocShell(this);
+    mpUndoManager = pUndoManager;
+
     mpDoc->SetSdrUndoManager( mpUndoManager );
     mpDoc->SetSdrUndoFactory( new sd::UndoFactory );
     UpdateTablePointers();
diff --git a/sfx2/sdi/docslots.sdi b/sfx2/sdi/docslots.sdi
index 18bd74133624..621e5a05779c 100644
--- a/sfx2/sdi/docslots.sdi
+++ b/sfx2/sdi/docslots.sdi
@@ -202,6 +202,10 @@ interface OfficeDocument : Document
         ExecMethod = ExecFile_Impl;
         StateMethod = GetState_Impl;
     ]
+    SID_DOC_REPAIR
+    [
+        StateMethod = GetState_Impl;
+    ]
 }
 
 
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index 95d16d1588ee..f1c0ef53c703 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -3481,6 +3481,25 @@ SfxVoidItem Redo SID_REDO
     GroupId = GID_EDIT;
 ]
 
+SfxBoolItem DocumentRepair SID_DOC_REPAIR
+
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = FALSE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+    Asynchron;
+
+
+    AccelConfig = FALSE,
+    MenuConfig = FALSE,
+    ToolBoxConfig = FALSE,
+    GroupId = ;
+]
+
 SfxBoolItem Reload SID_RELOAD
 ()
 [
diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx
index 263f9d2111c9..60c55bdeb3d6 100644
--- a/sfx2/source/control/unoctitm.cxx
+++ b/sfx2/source/control/unoctitm.cxx
@@ -1005,7 +1005,8 @@ static void InterceptLOKStateChangeEvent(const SfxViewFrame* pViewFrame, const c
         aEvent.FeatureURL.Path == "PreviousTrackedChange" ||
         aEvent.FeatureURL.Path == "AlignLeft" ||
         aEvent.FeatureURL.Path == "AlignHorizontalCenter" ||
-        aEvent.FeatureURL.Path == "AlignRight")
+        aEvent.FeatureURL.Path == "AlignRight" ||
+        aEvent.FeatureURL.Path == "DocumentRepair")
     {
         bool bTemp = false;
         aEvent.State >>= bTemp;
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 6547aff74b5d..728dd05d9273 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -51,6 +51,7 @@
 #include <vcl/layout.hxx>
 #include <svl/intitem.hxx>
 #include <svl/eitem.hxx>
+#include <svl/undo.hxx>
 #include <svl/visitem.hxx>
 #include <vcl/wrkwin.hxx>
 #include <svtools/sfxecode.hxx>
@@ -1064,6 +1065,15 @@ void SfxObjectShell::GetState_Impl(SfxItemSet &rSet)
                     rSet.DisableItem( nWhich );
                 break;
             }
+            case SID_DOC_REPAIR:
+            {
+                svl::IUndoManager* pIUndoMgr = GetUndoManager();
+                if (pIUndoMgr)
+                    rSet.Put( SfxBoolItem(nWhich, pIUndoMgr->IsEmptyActions()) );
+                else
+                    rSet.DisableItem( nWhich );
+                break;
+            }
         }
     }
 }
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index cbe1947b37f8..751891d3cf0a 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -1312,6 +1312,12 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
                 break;
             }
 
+            case SFX_HINT_DOCREPAIR:
+            {
+                GetBindings().Invalidate( SID_DOC_REPAIR );
+                break;
+            }
+
             case SFX_HINT_DEINITIALIZING:
                 GetFrame().DoClose();
                 break;
diff --git a/svl/source/undo/undo.cxx b/svl/source/undo/undo.cxx
index 770c0821cd82..dfdcd7b3aa8b 100644
--- a/svl/source/undo/undo.cxx
+++ b/svl/source/undo/undo.cxx
@@ -233,6 +233,7 @@ struct SfxUndoManager_Data
     bool            mbUndoEnabled;
     bool            mbDoing;
     bool            mbClearUntilTopLevel;
+    bool            mbEmptyActions;
 
     UndoListeners   aListeners;
 
@@ -245,6 +246,7 @@ struct SfxUndoManager_Data
         ,mbUndoEnabled( true )
         ,mbDoing( false )
         ,mbClearUntilTopLevel( false )
+        ,mbEmptyActions( true )
     {
         pActUndoArray = pUndoArray;
     }
@@ -417,6 +419,7 @@ using namespace ::svl::undo::impl;
 SfxUndoManager::SfxUndoManager( size_t nMaxUndoActionCount )
     :m_xData( new SfxUndoManager_Data( nMaxUndoActionCount ) )
 {
+    m_xData->mbEmptyActions = !ImplIsEmptyActions();
 }
 
 
@@ -497,6 +500,7 @@ void SfxUndoManager::SetMaxUndoActionCount( size_t nMaxUndoActionCount )
     }
 
     m_xData->pActUndoArray->nMaxUndoActions = nMaxUndoActionCount;
+    ImplCheckEmptyActions();
 }
 
 
@@ -515,6 +519,7 @@ void SfxUndoManager::ImplClearCurrentLevel_NoNotify( UndoManagerGuard& i_guard )
 
     m_xData->mnMarks = 0;
     m_xData->mnEmptyMark = MARK_INVALID;
+    ImplCheckEmptyActions();
 }
 
 
@@ -595,6 +600,7 @@ void SfxUndoManager::ImplClearUndo( UndoManagerGuard& i_guard )
         i_guard.markForDeletion( pUndoAction );
         --m_xData->pActUndoArray->nCurUndoAction;
     }
+    ImplCheckEmptyActions();
     // TODO: notifications? We don't have clearedUndo, only cleared and clearedRedo at the SfxUndoListener
 }
 
@@ -612,6 +618,7 @@ void SfxUndoManager::ImplClearRedo( UndoManagerGuard& i_guard, bool const i_curr
         i_guard.markForDeletion( pAction );
     }
 
+    ImplCheckEmptyActions();
     // notification - only if the top level's stack was cleared
     if ( i_currentLevel == IUndoManager::TopLevel )
         i_guard.scheduleNotification( &SfxUndoListener::clearedRedo );
@@ -665,6 +672,7 @@ bool SfxUndoManager::ImplAddUndoAction_NoNotify( SfxUndoAction *pAction, bool bT
 
     // append new action
     m_xData->pActUndoArray->aUndoActions.Insert( pAction, m_xData->pActUndoArray->nCurUndoAction++ );
+    ImplCheckEmptyActions();
     return true;
 }
 
@@ -743,6 +751,7 @@ void SfxUndoManager::RemoveLastUndoAction()
     m_xData->pActUndoArray->aUndoActions.Remove(
         m_xData->pActUndoArray->nCurUndoAction,
         m_xData->pActUndoArray->aUndoActions.size() - m_xData->pActUndoArray->nCurUndoAction );
+    ImplCheckEmptyActions();
 }
 
 
@@ -932,6 +941,7 @@ bool SfxUndoManager::ImplRedo( SfxUndoContext* i_contextOrNull )
         throw;
     }
 
+    ImplCheckEmptyActions();
     aGuard.scheduleNotification( &SfxUndoListener::actionRedone, sActionComment );
 
     return true;
@@ -1157,6 +1167,7 @@ size_t SfxUndoManager::ImplLeaveListAction( const bool i_merge, UndoManagerGuard
         }
     }
 
+    ImplIsEmptyActions();
     // notify listeners
     i_guard.scheduleNotification( &SfxUndoListener::listActionLeft, pListAction->GetComment() );
 
@@ -1260,6 +1271,7 @@ void SfxUndoManager::RemoveOldestUndoAction()
     aGuard.markForDeletion( pActionToRemove );
     m_xData->pUndoArray->aUndoActions.Remove( 0 );
     --m_xData->pUndoArray->nCurUndoAction;
+    ImplCheckEmptyActions();
 }
 
 void SfxUndoManager::dumpAsXml(xmlTextWriterPtr pWriter) const
@@ -1351,6 +1363,33 @@ OUString SfxUndoManager::GetRedoActionsInfo() const
     return OUString::fromUtf8(aStream.str().c_str());
 }
 
+bool SfxUndoManager::IsEmptyActions() const
+{
+    UndoManagerGuard aGuard(*m_xData);
+
+    return ImplIsEmptyActions();
+}
+
+inline bool SfxUndoManager::ImplIsEmptyActions() const
+{
+    return m_xData->pUndoArray->nCurUndoAction || m_xData->pUndoArray->aUndoActions.size() - m_xData->pUndoArray->nCurUndoAction;
+}
+
+void SfxUndoManager::ImplCheckEmptyActions()
+{
+    bool bEmptyActions = ImplIsEmptyActions();
+    if (m_xData->mbEmptyActions != bEmptyActions)
+    {
+        m_xData->mbEmptyActions = bEmptyActions;
+        EmptyActionsChanged();
+    }
+}
+
+void SfxUndoManager::EmptyActionsChanged()
+{
+
+}
+
 struct SfxListUndoAction::Impl
 {
     sal_uInt16 mnId;
diff --git a/svx/source/svdraw/sdrundomanager.cxx b/svx/source/svdraw/sdrundomanager.cxx
index 4d020c8f0779..3c424e38f412 100644
--- a/svx/source/svdraw/sdrundomanager.cxx
+++ b/svx/source/svdraw/sdrundomanager.cxx
@@ -18,7 +18,8 @@
  */
 
 #include <svx/sdrundomanager.hxx>
-
+#include <sfx2/objsh.hxx>
+#include <svl/hint.hxx>
 
 SdrUndoManager::SdrUndoManager(sal_uInt16 nMaxUndoActionCount)
     : EditUndoManager(nMaxUndoActionCount)
@@ -131,4 +132,17 @@ bool SdrUndoManager::isTextEditActive() const
     return maEndTextEditHdl.IsSet();
 }
 
+void SdrUndoManager::SetDocShell(SfxObjectShell* pDocShell)
+{
+    m_pDocSh = pDocShell;
+}
+
+void SdrUndoManager::EmptyActionsChanged()
+{
+    if (m_pDocSh)
+    {
+        m_pDocSh->Broadcast(SfxHint(SFX_HINT_DOCREPAIR));
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index 0365ec10cc75..91cc2140716b 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -32,6 +32,7 @@
 #include <sfx2/viewsh.hxx>
 #include <sfx2/bindings.hxx>
 #include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
 #include <sfx2/lokhelper.hxx>
 #include <redline.hxx>
 #include <IDocumentRedlineAccess.hxx>
@@ -87,7 +88,7 @@ public:
     void testRedoRepairResult();
     void testDisableUndoRepair();
     void testAllTrackedChanges();
-
+    void testDocumentRepair();
 
     CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
     CPPUNIT_TEST(testRegisterCallback);
@@ -134,6 +135,7 @@ public:
     CPPUNIT_TEST(testRedoRepairResult);
     CPPUNIT_TEST(testDisableUndoRepair);
     CPPUNIT_TEST(testAllTrackedChanges);
+    CPPUNIT_TEST(testDocumentRepair);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1875,6 +1877,50 @@ void SwTiledRenderingTest::testAllTrackedChanges()
     comphelper::LibreOfficeKit::setActive(false);
 }
 
+void SwTiledRenderingTest::testDocumentRepair()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    // Create two views.
+    SwXTextDocument* pXTextDocument = createDoc("dummy.fodt");
+    // view #1
+    SfxViewShell* pView1 = SfxViewShell::Current();
+
+    // view #2
+    SfxLokHelper::createView();
+    SfxViewShell* pView2 = SfxViewShell::Current();
+    int nView2 = SfxLokHelper::getView();
+    CPPUNIT_ASSERT(pView1 != pView2);
+    {
+        std::unique_ptr<SfxPoolItem> pItem1;
+        std::unique_ptr<SfxPoolItem> pItem2;
+        pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem1);
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem2);
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem1.get()));
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem2.get()));
+        CPPUNIT_ASSERT_EQUAL(false, dynamic_cast< const SfxBoolItem* >(pItem1.get())->GetValue());
+        CPPUNIT_ASSERT_EQUAL(false, dynamic_cast< const SfxBoolItem* >(pItem2.get())->GetValue());
+    }
+
+    // Insert a character in the second view.
+    SfxLokHelper::setView(nView2);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'u', 0);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'u', 0);
+    Scheduler::ProcessEventsToIdle();
+    {
+        std::unique_ptr<SfxPoolItem> pItem1;
+        std::unique_ptr<SfxPoolItem> pItem2;
+        pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem1);
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, pItem2);
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem1.get()));
+        CPPUNIT_ASSERT(dynamic_cast< const SfxBoolItem* >(pItem2.get()));
+        CPPUNIT_ASSERT_EQUAL(true, dynamic_cast< const SfxBoolItem* >(pItem1.get())->GetValue());
+        CPPUNIT_ASSERT_EQUAL(true, dynamic_cast< const SfxBoolItem* >(pItem2.get())->GetValue());
+    }
+
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 
 CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest);
 
diff --git a/sw/source/core/inc/UndoManager.hxx b/sw/source/core/inc/UndoManager.hxx
index ede9604059ad..d5db9f69bc5e 100644
--- a/sw/source/core/inc/UndoManager.hxx
+++ b/sw/source/core/inc/UndoManager.hxx
@@ -94,6 +94,9 @@ public:
     SwNodes      & GetUndoNodes();
     void SetDocShell(SwDocShell* pDocShell);
 
+protected:
+    virtual void EmptyActionsChanged() override;
+
 private:
     IDocumentDrawModelAccess & m_rDrawModelAccess;
     IDocumentRedlineAccess & m_rRedlineAccess;
diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx
index 4d117dac50ae..cecf40c180ee 100644
--- a/sw/source/core/undo/docundo.cxx
+++ b/sw/source/core/undo/docundo.cxx
@@ -629,6 +629,14 @@ bool UndoManager::Redo()
     }
 }
 
+void UndoManager::EmptyActionsChanged()
+{
+    if (m_pDocShell)
+    {
+        m_pDocShell->Broadcast(SfxHint(SFX_HINT_DOCREPAIR));
+    }
+}
+
 /** N.B.: this does _not_ call SdrUndoManager::Repeat because it is not
           possible to wrap a list action around it:
           calling EnterListAction here will cause SdrUndoManager::Repeat


More information about the Libreoffice-commits mailing list