diff options
-rw-r--r-- | libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx | 5 | ||||
-rw-r--r-- | sfx2/sdi/sfx.sdi | 4 | ||||
-rw-r--r-- | sfx2/source/control/dispatch.cxx | 18 | ||||
-rw-r--r-- | sw/inc/IDocumentUndoRedo.hxx | 5 | ||||
-rw-r--r-- | sw/qa/extras/tiledrendering/tiledrendering.cxx | 41 | ||||
-rw-r--r-- | sw/source/core/inc/UndoManager.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/undo/docundo.cxx | 15 | ||||
-rw-r--r-- | sw/source/uibase/shells/basesh.cxx | 17 |
8 files changed, 103 insertions, 6 deletions
diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx index 6c8e2d54dd50..a53bd00c5d7c 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 f5e366abcdb1..5275aef5d335 100644 --- a/sfx2/sdi/sfx.sdi +++ b/sfx2/sdi/sfx.sdi @@ -3428,7 +3428,7 @@ SfxBoolItem MacroRecordingFloat SID_RECORDING_FLOATWINDOW SfxVoidItem Redo SID_REDO -( SfxUInt16Item Redo SID_REDO ) +( SfxUInt16Item Redo SID_REDO, SfxBoolItem Repair SID_REPAIRPACKAGE ) [ AutoUpdate = FALSE, FastCall = FALSE, @@ -4555,7 +4555,7 @@ SfxVoidItem BasicIDEShowWindow SID_BASICIDE_SHOWWINDOW SfxVoidItem Undo SID_UNDO -( SfxUInt16Item Undo SID_UNDO ) +( SfxUInt16Item Undo SID_UNDO, SfxBoolItem Repair SID_REPAIRPACKAGE ) [ AutoUpdate = FALSE, FastCall = FALSE, diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx index 0d973a911205..c464fba861a0 100644 --- a/sfx2/source/control/dispatch.cxx +++ b/sfx2/source/control/dispatch.cxx @@ -313,6 +313,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 */ @@ -321,7 +337,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 6c044f618a5b..2266f3018afc 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 1219d0143e27..504de6c5321f 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -62,6 +62,7 @@ public: void testUndoInvalidations(); void testUndoLimiting(); void testUndoDispatch(); + void testUndoRepairDispatch(); void testShapeTextUndoShells(); void testShapeTextUndoGroupShells(); @@ -91,6 +92,7 @@ public: CPPUNIT_TEST(testUndoInvalidations); CPPUNIT_TEST(testUndoLimiting); CPPUNIT_TEST(testUndoDispatch); + CPPUNIT_TEST(testUndoRepairDispatch); CPPUNIT_TEST(testShapeTextUndoShells); CPPUNIT_TEST(testShapeTextUndoGroupShells); CPPUNIT_TEST_SUITE_END(); @@ -960,6 +962,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 5092e95a34ab..00132625bdcd 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 ba4aeff8d575..127d92827b1e 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 6f802bed355f..7c281a5a4721 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; @@ -483,9 +484,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: |