summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx5
-rw-r--r--sfx2/sdi/sfx.sdi4
-rw-r--r--sfx2/source/control/dispatch.cxx18
-rw-r--r--sw/inc/IDocumentUndoRedo.hxx5
-rw-r--r--sw/qa/extras/tiledrendering/tiledrendering.cxx41
-rw-r--r--sw/source/core/inc/UndoManager.hxx4
-rw-r--r--sw/source/core/undo/docundo.cxx15
-rw-r--r--sw/source/uibase/shells/basesh.cxx17
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: