include/sfx2/objsh.hxx | 4 officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu | 28 + officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu | 11 officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu | 16 + sc/source/ui/docshell/docsh.cxx | 4 sc/source/ui/inc/docsh.hxx | 4 sfx2/source/control/unoctitm.cxx | 2 sfx2/source/doc/objxtor.cxx | 4 sw/UIConfig_swriter.mk | 1 sw/inc/IDocumentRedlineAccess.hxx | 4 sw/inc/cmdid.h | 3 sw/inc/docsh.hxx | 4 sw/inc/editsh.hxx | 2 sw/qa/extras/tiledrendering/tiledrendering2.cxx | 153 +++++++++- sw/sdi/_viewsh.sdi | 19 + sw/sdi/swriter.sdi | 51 +++ sw/source/core/doc/DocumentRedlineManager.cxx | 26 + sw/source/core/edit/edredln.cxx | 4 sw/source/core/inc/DocumentRedlineManager.hxx | 4 sw/source/uibase/app/docsh.cxx | 28 + sw/source/uibase/inc/wrtsh.hxx | 2 sw/source/uibase/uiview/view2.cxx | 21 + sw/source/uibase/uiview/viewstat.cxx | 18 + sw/source/uibase/wrtsh/select.cxx | 4 sw/uiconfig/swriter/popupmenu/recordtrackedchanges.xml | 13 25 files changed, 382 insertions(+), 48 deletions(-)
New commits: commit e7e2a731ad57f6fc9728a2798ce3047c02fd4248 Author: Miklos Vajna <[email protected]> AuthorDate: Wed Mar 5 08:22:14 2025 +0100 Commit: Miklos Vajna <[email protected]> CommitDate: Thu Mar 6 08:09:58 2025 +0100 cool#11226 sw per-view redline on: state for the per-view and per-doc commands The UI for recording is one toolbar button (toggle) with a dropdown that has 2 radio buttons. The expectation is that once the toggle is on, one of the radio buttons report enabled state. So this is a tri-state: the record status is off, per-view or per-doc on the UI. At a code level, we have a per-doc flag and we have a boolean in each view. The requirements: 1) Compatibility: if the dropdown menu is not used, then clicking on the old toggle should enable recording for all views & once it's enabled (either per-view or per-doc), clicking on it should disable the recording. 2) If recording is on, the exactly one of per-view or per-doc radio button in the submenu should report enabled status. This leads to a not entirely symmetric behavior if you compare the enable, status and disable parts of this commands, and this is wanted to result in the least amount of surprise. Fix the problem by: 1) Enable: the toolbar button enables recording for all views (to stay compatible), the dropdown menu allows choosing between this view vs all views. 2) Status: the toolbar button reports enabled status if recording is on for this view for any reason; the "this view" command reports enabled status if recording is on in this view but not in all views; the "all views" command reports enabled status if recording is on in this view and no other view has it disabled. 3) Disable is almost the opposite of enabled, but the toolbar toggle can always disable recording, so a per-view -> off -> all-views transition is possible by clicking on the toggle twice. This required a single change to testTrackChangesPerViewEnableOne, because now going back to the no-record state is doable by clicking on the enabled toolbar button, i.e. by dispatching the .uno:TrackChanges command; dispatching .uno:TrackChangesInThisView always changes to the per-view recording. Change-Id: Iacc984f832b4c08e0e100a67774e1e559729d82a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182539 Tested-by: Jenkins Reviewed-by: Miklos Vajna <[email protected]> diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index a7f076b86ebe..8d5f8a68bcae 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -695,7 +695,7 @@ public: // change recording and respective passwword protection for Writer and Calc // slots available for Writer: FN_REDLINE_ON, FN_REDLINE_ON // slots used for Calc: FID_CHG_RECORD, SID_CHG_PROTECT - virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr) const; + virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr, bool bRecordAllViews = true) const; virtual bool HasChangeRecordProtection() const; virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false, bool bRecordAllViews = true ); virtual void SetProtectionPassword( const OUString &rPassword ); diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index fbacb2ea2dab..e9ace1fdfd3d 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -3394,7 +3394,7 @@ void ScDocShellModificator::SetDocumentModified() } } -bool ScDocShell::IsChangeRecording(SfxViewShell* /*pViewShell*/) const +bool ScDocShell::IsChangeRecording(SfxViewShell* /*pViewShell*/, bool /*bRecordAllViews*/) const { ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack(); return pChangeTrack != nullptr; diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index ffb276a7ae43..c6fd97f16db0 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -425,7 +425,7 @@ public: // password protection for Calc (derived from SfxObjectShell) // see also: FID_CHG_RECORD, SID_CHG_PROTECT - virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr) const override; + virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr, bool bRecordAllViews = true) const override; virtual bool HasChangeRecordProtection() const override; virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false, bool bRecordAllViews = true ) override; virtual void SetProtectionPassword( const OUString &rPassword ) override; diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx index 9cc61dbfb9fc..978bdbd5f579 100644 --- a/sfx2/source/doc/objxtor.cxx +++ b/sfx2/source/doc/objxtor.cxx @@ -1124,7 +1124,7 @@ void SfxObjectShell::SetInitialized_Impl( const bool i_fromInitNew ) } -bool SfxObjectShell::IsChangeRecording(SfxViewShell* /*pViewShell*/) const +bool SfxObjectShell::IsChangeRecording(SfxViewShell* /*pViewShell*/, bool /*bRecordAllViews*/) const { // currently this function needs to be overwritten by Writer and Calc only SAL_WARN( "sfx.doc", "function not implemented" ); diff --git a/sw/inc/docsh.hxx b/sw/inc/docsh.hxx index d6d54f136335..d67471627c5c 100644 --- a/sw/inc/docsh.hxx +++ b/sw/inc/docsh.hxx @@ -321,7 +321,7 @@ public: /** passwword protection for Writer (derived from SfxObjectShell) see also: FN_REDLINE_ON, FN_REDLINE_ON */ - virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr) const override; + virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr, bool bRecordAllViews = true) const override; virtual bool HasChangeRecordProtection() const override; virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false, bool bRecordAllViews = true ) override; virtual void SetProtectionPassword( const OUString &rPassword ) override; diff --git a/sw/qa/extras/tiledrendering/tiledrendering2.cxx b/sw/qa/extras/tiledrendering/tiledrendering2.cxx index d1d75f2a2738..9c2e7dba2155 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering2.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering2.cxx @@ -21,11 +21,13 @@ #include <comphelper/propertyvalue.hxx> #include <comphelper/dispatchcommand.hxx> #include <comphelper/scopeguard.hxx> +#include <sfx2/dispatch.hxx> #include <view.hxx> #include <IDocumentLayoutAccess.hxx> #include <rootfrm.hxx> #include <pagefrm.hxx> +#include <cmdid.h> namespace { @@ -521,6 +523,99 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerDocInsert) // i.e. track changes recording was unconditionally per-view. CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pWrtShell2->GetRedlineCount()); } + +CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesStates) +{ + // Given a document with 2 views: + SwXTextDocument* pXTextDocument = createDoc(); + CPPUNIT_ASSERT(pXTextDocument); + ViewCallback aView1; + int nView1 = SfxLokHelper::getView(); + SwView* pView1 = pXTextDocument->GetDocShell()->GetView(); + SfxLokHelper::createView(); + ViewCallback aView2; + SwView* pView2 = pXTextDocument->GetDocShell()->GetView(); + SfxLokHelper::setView(nView1); + + // When enabling recording in view1 only: + pView1->GetViewFrame().GetDispatcher()->Execute(FN_TRACK_CHANGES_IN_THIS_VIEW, + SfxCallMode::SYNCHRON); + + // Then make sure the "is record", "is record for this view on" and "is record for all views on" + // statuses are correct: + std::unique_ptr<SfxPoolItem> pItem; + pView1->GetViewFrame().GetBindings().QueryState(FN_REDLINE_ON, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_REDLINE_ON), pItem->Which()); + // Without the accompanying fix in place, this test would have failed, enabling recording for + // this view didn't enable the toolbar button in the same view, which looked confusing. + CPPUNIT_ASSERT(dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView1->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_THIS_VIEW, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_THIS_VIEW), pItem->Which()); + CPPUNIT_ASSERT(dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView1->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_ALL_VIEWS, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_ALL_VIEWS), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_REDLINE_ON, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_REDLINE_ON), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_THIS_VIEW, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_THIS_VIEW), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_ALL_VIEWS, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_ALL_VIEWS), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + + // When disabling recording: + SfxBoolItem aOn(FN_REDLINE_ON, false); + pView1->GetViewFrame().GetDispatcher()->ExecuteList(FN_REDLINE_ON, SfxCallMode::SYNCHRON, + { &aOn }); + + // Then make sure the "is record", "is record for this view on" and "is record for all views on" + // statuses are correct: + pView1->GetViewFrame().GetBindings().QueryState(FN_REDLINE_ON, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_REDLINE_ON), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView1->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_THIS_VIEW, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_THIS_VIEW), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView1->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_ALL_VIEWS, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_ALL_VIEWS), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_REDLINE_ON, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_REDLINE_ON), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_THIS_VIEW, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_THIS_VIEW), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_ALL_VIEWS, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_ALL_VIEWS), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + + // When enabling recording in all views: + pView1->GetViewFrame().GetDispatcher()->Execute(FN_TRACK_CHANGES_IN_ALL_VIEWS, + SfxCallMode::SYNCHRON); + + // Then make sure the "is record", "is record for this view on" and "is record for all views on" + // statuses are correct: + pView1->GetViewFrame().GetBindings().QueryState(FN_REDLINE_ON, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_REDLINE_ON), pItem->Which()); + CPPUNIT_ASSERT(dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView1->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_THIS_VIEW, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_THIS_VIEW), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView1->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_ALL_VIEWS, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_ALL_VIEWS), pItem->Which()); + CPPUNIT_ASSERT(dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_REDLINE_ON, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_REDLINE_ON), pItem->Which()); + CPPUNIT_ASSERT(dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_THIS_VIEW, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_THIS_VIEW), pItem->Which()); + CPPUNIT_ASSERT(!dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); + pView2->GetViewFrame().GetBindings().QueryState(FN_TRACK_CHANGES_IN_ALL_VIEWS, pItem); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(FN_TRACK_CHANGES_IN_ALL_VIEWS), pItem->Which()); + CPPUNIT_ASSERT(dynamic_cast<SfxBoolItem*>(pItem.get())->GetValue()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/uibase/app/docsh.cxx b/sw/source/uibase/app/docsh.cxx index ee91ca7c3f6f..c4a5f02d8e2b 100644 --- a/sw/source/uibase/app/docsh.cxx +++ b/sw/source/uibase/app/docsh.cxx @@ -1355,7 +1355,7 @@ const ::sfx2::IXmlIdRegistry* SwDocShell::GetXmlIdRegistry() const return m_xDoc ? &m_xDoc->GetXmlIdRegistry() : nullptr; } -bool SwDocShell::IsChangeRecording(SfxViewShell* pViewShell) const +bool SwDocShell::IsChangeRecording(SfxViewShell* pViewShell, bool bRecordAllViews) const { SwWrtShell* pWrtShell = nullptr; auto pView = dynamic_cast<SwView*>(pViewShell); @@ -1370,7 +1370,25 @@ bool SwDocShell::IsChangeRecording(SfxViewShell* pViewShell) const if (!pWrtShell) return false; - return bool(pWrtShell->GetRedlineFlags() & RedlineFlags::On); + + auto bOn = bool(pWrtShell->GetRedlineFlags() & RedlineFlags::On); + if (bOn) + { + if (bRecordAllViews) + { + for (SwViewShell& rSh : pWrtShell->GetRingContainer()) + { + if (!rSh.GetViewOptions()->IsRedlineRecordingOn()) + { + return false; + } + } + } + + return true; + } + + return false; } bool SwDocShell::HasChangeRecordProtection() const diff --git a/sw/source/uibase/uiview/viewstat.cxx b/sw/source/uibase/uiview/viewstat.cxx index c6846f15d486..526c7f8e0fa6 100644 --- a/sw/source/uibase/uiview/viewstat.cxx +++ b/sw/source/uibase/uiview/viewstat.cxx @@ -332,7 +332,8 @@ void SwView::GetState(SfxItemSet &rSet) } break; case FN_REDLINE_ON: - rSet.Put( SfxBoolItem( nWhich, GetDocShell()->IsChangeRecording(this) ) ); + // Enabled at least in this view. + rSet.Put( SfxBoolItem( nWhich, GetDocShell()->IsChangeRecording(this, /*bRecordAllViews=*/false) ) ); // When the view is new (e.g. on load), show the Hidden Track Changes infobar // if Show Changes is disabled, but recording of changes is enabled // or hidden tracked changes are there already in the document. @@ -340,7 +341,7 @@ void SwView::GetState(SfxItemSet &rSet) // enabled, see in sfx2. if ( m_bForceChangesToolbar && m_pWrtShell->GetLayout()->IsHideRedlines() ) { - bool isRecording = GetDocShell()->IsChangeRecording(this); + bool isRecording = GetDocShell()->IsChangeRecording(this, /*bRecordAllViews=*/false); bool hasRecorded = m_pWrtShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable().size(); if ( isRecording || hasRecorded ) @@ -359,10 +360,15 @@ void SwView::GetState(SfxItemSet &rSet) break; case FN_TRACK_CHANGES_IN_THIS_VIEW: { + // Enabled in this view, but not in all views. + bool bOn = GetDocShell()->IsChangeRecording(this, /*bRecordAllViews=*/false) && !GetDocShell()->IsChangeRecording(this); + rSet.Put(SfxBoolItem(nWhich, bOn)); } break; case FN_TRACK_CHANGES_IN_ALL_VIEWS: { + // Enabled in all views. + rSet.Put(SfxBoolItem(nWhich, GetDocShell()->IsChangeRecording(this))); } break; case FN_REDLINE_PROTECT : commit 0f0257a1175724c443aeb3055d00d5c27a088f43 Author: Miklos Vajna <[email protected]> AuthorDate: Tue Mar 4 08:59:28 2025 +0100 Commit: Miklos Vajna <[email protected]> CommitDate: Wed Mar 5 16:58:49 2025 +0100 cool#11226 sw per-view redline on: allow both per-view and per-doc Have two windows for a document, record changes in one view, and be surprised that now this is not turned on in the other view since commit ae6d396552cd3cebd7fba4942e6ca2fd5de579af (cool#11226 sw per-view redline on: add view-aware getter, 2025-03-03). Adding the ability to record changes per-view is intentional, but it was not a deliberate choice to also remove the old per-document recording. Fix this by turning the "is recording on" UI into a tristate, so the user can enable recording for all document windows or just the current document window -- similar to how showing changes can be off, inline and there are also 2 more on-margin options. The state of the new UNO commands still has to be implemented. Change-Id: I1e5271d4cc8900a28c7a8da8d34e00fec9e2e1b0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182527 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index a4ad3aa4816d..a7f076b86ebe 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -697,7 +697,7 @@ public: // slots used for Calc: FID_CHG_RECORD, SID_CHG_PROTECT virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr) const; virtual bool HasChangeRecordProtection() const; - virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false ); + virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false, bool bRecordAllViews = true ); virtual void SetProtectionPassword( const OUString &rPassword ); virtual bool GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > &rPasswordHash ); diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu index 2d99b67a7368..afda5d02e4f9 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu @@ -579,6 +579,20 @@ <value>statisticsmenu</value> </prop> </node> + <node oor:name="c46" oor:op="replace"> + <prop oor:name="Command"> + <value>.uno:RecordTrackedChangesMenu</value> + </prop> + <prop oor:name="Module"> + <value/> + </prop> + <prop oor:name="Controller"> + <value>com.sun.star.comp.framework.ResourceMenuController</value> + </prop> + <prop oor:name="Value"> + <value>recordtrackedchanges</value> + </prop> + </node> <node oor:name="WindowListMenu" oor:op="replace"> <prop oor:name="Command"> <value>.uno:WindowList</value> @@ -807,6 +821,20 @@ <value>.uno:ShowTrackedChangesMenu</value> </prop> </node> + <node oor:name="RecordTrackedChangesController" oor:op="replace"> + <prop oor:name="Command"> + <value>.uno:TrackChanges</value> + </prop> + <prop oor:name="Module"> + <value/> + </prop> + <prop oor:name="Controller"> + <value>com.sun.star.comp.framework.GenericPopupToolbarController</value> + </prop> + <prop oor:name="Value"> + <value>.uno:RecordTrackedChangesMenu</value> + </prop> + </node> <node oor:name="ConnectorToolBox" oor:op="replace"> <prop oor:name="Command"> <value>.uno:ConnectorToolbox</value> diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu index 0ec0712557da..da58e407556b 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu @@ -7010,6 +7010,17 @@ bit 3 (0x8): #define UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8 <value>1</value> </prop> </node> + <node oor:name=".uno:RecordTrackedChangesMenu" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Change record mode</value> + </prop> + <prop oor:name="ContextLabel" oor:type="xs:string"> + <value xml:lang="en-US">Record mode</value> + </prop> + <prop oor:name="Properties" oor:type="xs:int"> + <value>1</value> + </prop> + </node> <node oor:name=".uno:AVMediaPlayer" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">Me~dia Player</value> diff --git a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu index fe962fb4e067..e0a7a38db84d 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu @@ -925,6 +925,22 @@ <value xml:lang="en-US">~Insertions In Margin</value> </prop> </node> + <node oor:name=".uno:TrackChangesInThisView" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Record changes in this view</value> + </prop> + <prop oor:name="ContextLabel" oor:type="xs:string"> + <value xml:lang="en-US">~Changes in this view</value> + </prop> + </node> + <node oor:name=".uno:TrackChangesInAllViews" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Record changes in all views</value> + </prop> + <prop oor:name="ContextLabel" oor:type="xs:string"> + <value xml:lang="en-US">~Changes in all views</value> + </prop> + </node> <node oor:name=".uno:ToggleObjectLayer" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">Change Position</value> diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 2157fb18a5aa..fbacb2ea2dab 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -3409,7 +3409,7 @@ bool ScDocShell::HasChangeRecordProtection() const return bRes; } -void ScDocShell::SetChangeRecording( bool bActivate, bool /*bLockAllViews*/ ) +void ScDocShell::SetChangeRecording( bool bActivate, bool /*bLockAllViews*/, bool /*bRecordAllViews*/ ) { bool bOldChangeRecording = IsChangeRecording(); diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index cbab1f0d8c40..ffb276a7ae43 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -427,7 +427,7 @@ public: // see also: FID_CHG_RECORD, SID_CHG_PROTECT virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr) const override; virtual bool HasChangeRecordProtection() const override; - virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false ) override; + virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false, bool bRecordAllViews = true ) override; virtual void SetProtectionPassword( const OUString &rPassword ) override; virtual bool GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > &rPasswordHash ) override; diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx index 976cd48ce152..c0e2dfbb4c73 100644 --- a/sfx2/source/control/unoctitm.cxx +++ b/sfx2/source/control/unoctitm.cxx @@ -1198,6 +1198,8 @@ const std::map<std::u16string_view, KitUnoCommand>& GetKitUnoCommandList() { u"Underline", { PayloadType::IsActivePayload, true } }, { u"ModifiedStatus", { PayloadType::IsActivePayload, true } }, { u"TrackChanges", { PayloadType::IsActivePayload, true } }, + { u"TrackChangesInThisView", { PayloadType::IsActivePayload, true } }, + { u"TrackChangesInAllViews", { PayloadType::IsActivePayload, true } }, { u"ShowTrackedChanges", { PayloadType::IsActivePayload, true } }, { u"AlignLeft", { PayloadType::IsActivePayload, true } }, { u"AlignHorizontalCenter", { PayloadType::IsActivePayload, true } }, diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx index 106743ee1850..9cc61dbfb9fc 100644 --- a/sfx2/source/doc/objxtor.cxx +++ b/sfx2/source/doc/objxtor.cxx @@ -1140,7 +1140,7 @@ bool SfxObjectShell::HasChangeRecordProtection() const } -void SfxObjectShell::SetChangeRecording( bool /*bActivate*/, bool /*bLockAllViews*/ ) +void SfxObjectShell::SetChangeRecording( bool /*bActivate*/, bool /*bLockAllViews*/, bool /*bRecordAllViews*/ ) { // currently this function needs to be overwritten by Writer and Calc only SAL_WARN( "sfx.doc", "function not implemented" ); diff --git a/sw/UIConfig_swriter.mk b/sw/UIConfig_swriter.mk index d9df23bf27a4..062d95b1f1d8 100644 --- a/sw/UIConfig_swriter.mk +++ b/sw/UIConfig_swriter.mk @@ -31,6 +31,7 @@ $(eval $(call gb_UIConfig_add_popupmenufiles,modules/swriter,\ sw/uiconfig/swriter/popupmenu/table \ sw/uiconfig/swriter/popupmenu/text \ sw/uiconfig/swriter/popupmenu/showtrackedchanges \ + sw/uiconfig/swriter/popupmenu/recordtrackedchanges \ )) $(eval $(call gb_UIConfig_add_statusbarfiles,modules/swriter,\ diff --git a/sw/inc/IDocumentRedlineAccess.hxx b/sw/inc/IDocumentRedlineAccess.hxx index ede30c26d39e..c1147b000a36 100644 --- a/sw/inc/IDocumentRedlineAccess.hxx +++ b/sw/inc/IDocumentRedlineAccess.hxx @@ -107,14 +107,14 @@ public: @param eMode [in] the new redline mode. */ - virtual void SetRedlineFlags_intern(/*[in]*/RedlineFlags eMode) = 0; + virtual void SetRedlineFlags_intern(/*[in]*/RedlineFlags eMode, bool bRecordAllViews = true) = 0; /** Set a new redline mode. @param eMode [in] the new redline mode. */ - virtual void SetRedlineFlags(/*[in]*/RedlineFlags eMode) = 0; + virtual void SetRedlineFlags(/*[in]*/RedlineFlags eMode, bool bRecordAllViews = true) = 0; /** Query if redlining is on. diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h index f50754b6e274..e99bf4d7b1be 100644 --- a/sw/inc/cmdid.h +++ b/sw/inc/cmdid.h @@ -205,6 +205,9 @@ class SwUINumRuleItem; #define FN_SET_TRACKED_DELETIONS_IN_MARGIN (FN_VIEW + 68) /* Show final text (deletions in margin) */ #define FN_SET_TRACKED_INSERTIONS_IN_MARGIN (FN_VIEW + 69) /* Show original text (insertions in margin) */ #define FN_OUTLINE_LEVELS_SHOWN (FN_VIEW + 70) +#define FN_RECORD_TRACKED_CHANGES_MENU (FN_VIEW + 71) /* Menu for the track changes record modes */ +#define FN_TRACK_CHANGES_IN_THIS_VIEW (FN_VIEW + 72) /* Record track changes only in this view */ +#define FN_TRACK_CHANGES_IN_ALL_VIEWS (FN_VIEW + 73) /* Record track changes only in all views */ // Region: Insert #define FN_INSERT_BOOKMARK (FN_INSERT + 2 ) /* Bookmark */ diff --git a/sw/inc/docsh.hxx b/sw/inc/docsh.hxx index 8bbc54837363..d6d54f136335 100644 --- a/sw/inc/docsh.hxx +++ b/sw/inc/docsh.hxx @@ -323,7 +323,7 @@ public: see also: FN_REDLINE_ON, FN_REDLINE_ON */ virtual bool IsChangeRecording(SfxViewShell* pViewShell = nullptr) const override; virtual bool HasChangeRecordProtection() const override; - virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false ) override; + virtual void SetChangeRecording( bool bActivate, bool bLockAllViews = false, bool bRecordAllViews = true ) override; virtual void SetProtectionPassword( const OUString &rPassword ) override; virtual bool GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > &rPasswordHash ) override; diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx index 5a16812e89da..76678c7f3ae3 100644 --- a/sw/inc/editsh.hxx +++ b/sw/inc/editsh.hxx @@ -954,7 +954,7 @@ public: /// For Redlining. SW_DLLPUBLIC RedlineFlags GetRedlineFlags() const; - SW_DLLPUBLIC void SetRedlineFlags( RedlineFlags eMode ); + SW_DLLPUBLIC void SetRedlineFlags( RedlineFlags eMode, bool bRecordAllViews = true ); bool IsRedlineOn() const; SW_DLLPUBLIC SwRedlineTable::size_type GetRedlineCount() const; const SwRangeRedline& GetRedline( SwRedlineTable::size_type nPos ) const; diff --git a/sw/qa/extras/tiledrendering/tiledrendering2.cxx b/sw/qa/extras/tiledrendering/tiledrendering2.cxx index 826ce550556f..d1d75f2a2738 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering2.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering2.cxx @@ -363,7 +363,7 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerViewEnableOne) SfxLokHelper::setView(nView1); aView1.m_aStateChanges.clear(); aView2.m_aStateChanges.clear(); - comphelper::dispatchCommand(".uno:TrackChanges", {}); + dispatchCommand(mxComponent, ".uno:TrackChangesInThisView", {}); // Then make sure view1 gets a state track changes state change, but not view2: // Filter out .uno:ModifiedStatus=true, which is not interesting here. @@ -373,17 +373,22 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerViewEnableOne) CPPUNIT_ASSERT(aRecord2.empty()); // And given a reset state (both view1 and view2 recording is disabled): - comphelper::dispatchCommand(".uno:TrackChanges", {}); + uno::Sequence<beans::PropertyValue> aArgs = { + comphelper::makePropertyValue("TrackChanges", false), + }; + dispatchCommand(mxComponent, ".uno:TrackChanges", aArgs); // When recording changes in view2: SfxLokHelper::setView(nView2); aView1.m_aStateChanges.clear(); aView2.m_aStateChanges.clear(); - comphelper::dispatchCommand(".uno:TrackChanges", {}); + dispatchCommand(mxComponent, ".uno:TrackChangesInThisView", {}); - // Then make sure view2 gets a state track changes state change, but not view1: - CPPUNIT_ASSERT(aView1.m_aStateChanges.empty()); - CPPUNIT_ASSERT(!aView2.m_aStateChanges.empty()); + // Then make sure view2 gets a 'track changes is now on' state change, but not view1: + aRecord1 = FilterStateChanges(aView1.m_aStateChanges, ".uno:TrackChanges=true"); + CPPUNIT_ASSERT(aRecord1.empty()); + aRecord2 = FilterStateChanges(aView2.m_aStateChanges, ".uno:TrackChanges=true"); + CPPUNIT_ASSERT(!aRecord2.empty()); } CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerViewEnableBoth) @@ -399,13 +404,13 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerViewEnableBoth) int nView2 = SfxLokHelper::getView(); SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell(); SfxLokHelper::setView(nView1); - comphelper::dispatchCommand(".uno:TrackChanges", {}); + comphelper::dispatchCommand(".uno:TrackChangesInThisView", {}); SfxLokHelper::setView(nView2); CPPUNIT_ASSERT(pWrtShell1->GetViewOptions()->IsRedlineRecordingOn()); CPPUNIT_ASSERT(!pWrtShell2->GetViewOptions()->IsRedlineRecordingOn()); // When turning on track changes for view2: - comphelper::dispatchCommand(".uno:TrackChanges", {}); + comphelper::dispatchCommand(".uno:TrackChangesInThisView", {}); // Then make sure both views have track changes turned on: CPPUNIT_ASSERT(pWrtShell1->GetViewOptions()->IsRedlineRecordingOn()); @@ -428,7 +433,7 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerViewInsert) int nView2 = SfxLokHelper::getView(); SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell(); SfxLokHelper::setView(nView1); - comphelper::dispatchCommand(".uno:TrackChanges", {}); + comphelper::dispatchCommand(".uno:TrackChangesInThisView", {}); // When view 1 types: pWrtShell1->SttEndDoc(/*bStt=*/true); @@ -462,7 +467,7 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerViewDelete) int nView2 = SfxLokHelper::getView(); SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell(); SfxLokHelper::setView(nView1); - comphelper::dispatchCommand(".uno:TrackChanges", {}); + comphelper::dispatchCommand(".uno:TrackChangesInThisView", {}); // When view 1 deletes: pWrtShell1->SttEndDoc(/*bStt=*/true); @@ -483,6 +488,39 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerViewDelete) // i.e. the deletion in view 2 was recorded. CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pWrtShell2->GetRedlineCount()); } + +CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testTrackChangesPerDocInsert) +{ + // Given 2 views, view 1 turns on per-doc change recording: + SwXTextDocument* pXTextDocument = createDoc(); + CPPUNIT_ASSERT(pXTextDocument); + ViewCallback aView1; + int nView1 = SfxLokHelper::getView(); + SwWrtShell* pWrtShell1 = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell1->Insert(u"X"_ustr); + SfxLokHelper::createView(); + ViewCallback aView2; + int nView2 = SfxLokHelper::getView(); + SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell(); + SfxLokHelper::setView(nView1); + comphelper::dispatchCommand(".uno:TrackChanges", {}); + + // When view 1 types: + pWrtShell1->SttEndDoc(/*bStt=*/true); + pWrtShell1->Insert(u"A"_ustr); + // Then make sure a redline is created: + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pWrtShell1->GetRedlineCount()); + + // When view 2 types: + SfxLokHelper::setView(nView2); + pWrtShell2->SttEndDoc(/*bStt=*/false); + pWrtShell2->Insert(u"Z"_ustr); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 1 + // i.e. track changes recording was unconditionally per-view. + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pWrtShell2->GetRedlineCount()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/sdi/_viewsh.sdi b/sw/sdi/_viewsh.sdi index 71b2c08e0396..c98c2923eddd 100644 --- a/sw/sdi/_viewsh.sdi +++ b/sw/sdi/_viewsh.sdi @@ -168,6 +168,25 @@ interface BaseTextEditView StateMethod = GetState ; DisableFlags="SfxDisableFlags::SwOnMailboxEditor"; ] + FN_TRACK_CHANGES_IN_THIS_VIEW + [ + ExecMethod = Execute ; + StateMethod = GetState ; + DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; + ] + FN_TRACK_CHANGES_IN_ALL_VIEWS + [ + ExecMethod = Execute ; + StateMethod = GetState ; + DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; + ] + FN_RECORD_TRACKED_CHANGES_MENU + [ + ExecMethod = Execute ; + StateMethod = GetState ; + DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; + ] + FN_REDLINE_SHOW // status() [ ExecMethod = Execute; diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi index bba5111a7077..eed95411eed3 100644 --- a/sw/sdi/swriter.sdi +++ b/sw/sdi/swriter.sdi @@ -8504,6 +8504,57 @@ SfxBoolItem SetTrackedInsertionsInMargin FN_SET_TRACKED_INSERTIONS_IN_MARGIN GroupId = SfxGroupId::View; ] +SfxVoidItem RecordTrackedChangesMenu FN_RECORD_TRACKED_CHANGES_MENU +() +[ + AutoUpdate = FALSE, + FastCall = TRUE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::View; +] + +SfxBoolItem TrackChangesInThisView FN_TRACK_CHANGES_IN_THIS_VIEW +() +[ + AutoUpdate = TRUE, + FastCall = TRUE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::View; +] + +SfxBoolItem TrackChangesInAllViews FN_TRACK_CHANGES_IN_ALL_VIEWS +() +[ + AutoUpdate = TRUE, + FastCall = TRUE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::View; +] + SfxBoolItem UseHeaderFooterMenu FN_USE_HEADERFOOTERMENU () [ diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 168a43a7be22..10d35c1450d6 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -1172,7 +1172,7 @@ RedlineFlags DocumentRedlineManager::GetRedlineFlags(const SwViewShell* pViewShe return eRedlineFlags; } -void DocumentRedlineManager::SetRedlineFlags( RedlineFlags eMode ) +void DocumentRedlineManager::SetRedlineFlags( RedlineFlags eMode, bool bRecordAllViews ) { if( GetRedlineFlags() == eMode ) return; @@ -1245,7 +1245,7 @@ void DocumentRedlineManager::SetRedlineFlags( RedlineFlags eMode ) m_rDoc.SetInXMLImport( bSaveInXMLImportFlag ); } - SetRedlineFlags_intern(eMode); + SetRedlineFlags_intern(eMode, bRecordAllViews); m_rDoc.getIDocumentState().SetModified(); // #TODO - add 'SwExtraRedlineTable' also ? @@ -1261,19 +1261,27 @@ bool DocumentRedlineManager::IsIgnoreRedline() const return bool(RedlineFlags::Ignore & GetRedlineFlags()); } -void DocumentRedlineManager::SetRedlineFlags_intern(RedlineFlags eMode) +void DocumentRedlineManager::SetRedlineFlags_intern(RedlineFlags eMode, bool bRecordAllViews) { SwDocShell* pDocShell = m_rDoc.GetDocShell(); SwViewShell* pViewShell = pDocShell ? pDocShell->GetWrtShell() : nullptr; if (pViewShell) { - // Recording can be per-view, the rest is per-document. - auto bRedlineRecordingOn = bool(eMode & RedlineFlags::On); - SwViewOption aOpt(*pViewShell->GetViewOptions()); - if (aOpt.IsRedlineRecordingOn() != bRedlineRecordingOn) + // Recording may be per-view, the rest is per-document. + for(SwViewShell& rSh : pViewShell->GetRingContainer()) { - aOpt.SetRedlineRecordingOn(bRedlineRecordingOn); - pViewShell->ApplyViewOptions(aOpt); + if (!bRecordAllViews && &rSh != pViewShell) + { + continue; + } + + auto bRedlineRecordingOn = bool(eMode & RedlineFlags::On); + SwViewOption aOpt(*rSh.GetViewOptions()); + if (aOpt.IsRedlineRecordingOn() != bRedlineRecordingOn) + { + aOpt.SetRedlineRecordingOn(bRedlineRecordingOn); + rSh.ApplyViewOptions(aOpt); + } } } diff --git a/sw/source/core/edit/edredln.cxx b/sw/source/core/edit/edredln.cxx index 76f529dff7b0..3865fd94dcca 100644 --- a/sw/source/core/edit/edredln.cxx +++ b/sw/source/core/edit/edredln.cxx @@ -29,13 +29,13 @@ RedlineFlags SwEditShell::GetRedlineFlags() const return GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags(this); } -void SwEditShell::SetRedlineFlags( RedlineFlags eMode ) +void SwEditShell::SetRedlineFlags( RedlineFlags eMode, bool bRecordAllViews ) { if( eMode != GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags() ) { CurrShell aCurr( this ); StartAllAction(); - GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eMode ); + GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eMode, bRecordAllViews ); EndAllAction(); } } diff --git a/sw/source/core/inc/DocumentRedlineManager.hxx b/sw/source/core/inc/DocumentRedlineManager.hxx index 5476c34e5407..34d9bb31cd98 100644 --- a/sw/source/core/inc/DocumentRedlineManager.hxx +++ b/sw/source/core/inc/DocumentRedlineManager.hxx @@ -38,9 +38,9 @@ public: */ virtual RedlineFlags GetRedlineFlags(const SwViewShell* pViewShell = nullptr) const override; - virtual void SetRedlineFlags_intern(/*[in]*/RedlineFlags eMode) override; + virtual void SetRedlineFlags_intern(/*[in]*/RedlineFlags eMode, bool bRecordAllViews = true) override; - virtual void SetRedlineFlags(/*[in]*/RedlineFlags eMode) override; + virtual void SetRedlineFlags(/*[in]*/RedlineFlags eMode, bool bRecordAllViews = true) override; virtual bool IsRedlineOn() const override; diff --git a/sw/source/uibase/app/docsh.cxx b/sw/source/uibase/app/docsh.cxx index 15e4e6e79c84..ee91ca7c3f6f 100644 --- a/sw/source/uibase/app/docsh.cxx +++ b/sw/source/uibase/app/docsh.cxx @@ -1380,7 +1380,7 @@ bool SwDocShell::HasChangeRecordProtection() const return m_pWrtShell->getIDocumentRedlineAccess().GetRedlinePassword().hasElements(); } -void SwDocShell::SetChangeRecording( bool bActivate, bool bLockAllViews ) +void SwDocShell::SetChangeRecording( bool bActivate, bool bLockAllViews, bool bRecordAllViews ) { RedlineFlags nOn = bActivate ? RedlineFlags::On : RedlineFlags::NONE; RedlineFlags nMode = m_pWrtShell->GetRedlineFlags(); @@ -1388,11 +1388,11 @@ void SwDocShell::SetChangeRecording( bool bActivate, bool bLockAllViews ) { // tdf#107870: prevent jumping to cursor auto aViewGuard(LockAllViews()); - m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn ); + m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn, bRecordAllViews ); } else { - m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn ); + m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn, bRecordAllViews ); } } diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx index c0a2a8148081..1ff781591272 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -172,7 +172,7 @@ public: void SetInsMode( bool bOn = true ); void ToggleInsMode() { SetInsMode( !m_bIns ); } bool IsInsMode() const { return m_bIns; } - SW_DLLPUBLIC void SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode ); + SW_DLLPUBLIC void SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode, bool bRecordAllViews = true ); SW_DLLPUBLIC void EnterSelFrameMode(const Point *pStartDrag = nullptr); SW_DLLPUBLIC void LeaveSelFrameMode(); diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx index 7f6384050d6b..0dc9f18eb389 100644 --- a/sw/source/uibase/uiview/view2.cxx +++ b/sw/source/uibase/uiview/view2.cxx @@ -736,15 +736,27 @@ void SwView::Execute(SfxRequest &rReq) } break; case FN_REDLINE_ON: + case FN_TRACK_CHANGES_IN_THIS_VIEW: + case FN_TRACK_CHANGES_IN_ALL_VIEWS: { + std::optional<bool> oOn; if( pArgs && SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem )) + { + oOn = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + } + else if (nSlot == FN_TRACK_CHANGES_IN_THIS_VIEW || nSlot == FN_TRACK_CHANGES_IN_ALL_VIEWS) + { + oOn = true; + } + + if (oOn.has_value()) { IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess(); Sequence <sal_Int8> aPasswd = rIDRA.GetRedlinePassword(); if( aPasswd.hasElements() ) { - OSL_ENSURE( !static_cast<const SfxBoolItem*>(pItem)->GetValue(), "SwView::Execute(): password set and redlining off doesn't match!" ); + OSL_ENSURE( !oOn.value(), "SwView::Execute(): password set and redlining off doesn't match!" ); // xmlsec05: new password dialog SfxPasswordDialog aPasswdDlg(GetFrameWeld()); @@ -792,13 +804,18 @@ void SwView::Execute(SfxRequest &rReq) } SwDocShell* pDocShell = GetDocShell(); - pDocShell->SetChangeRecording( static_cast<const SfxBoolItem*>(pItem)->GetValue(), /*bLockAllViews=*/true ); + bool bRecordAllViews = nSlot != FN_TRACK_CHANGES_IN_THIS_VIEW; + pDocShell->SetChangeRecording( oOn.value(), /*bLockAllViews=*/true, bRecordAllViews ); // Notify all view shells of this document, as the track changes mode is document-global. for (SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(pDocShell); pViewFrame; pViewFrame = SfxViewFrame::GetNext(*pViewFrame, pDocShell)) { pViewFrame->GetBindings().Invalidate(FN_REDLINE_ON); pViewFrame->GetBindings().Update(FN_REDLINE_ON); + pViewFrame->GetBindings().Invalidate(FN_TRACK_CHANGES_IN_THIS_VIEW); + pViewFrame->GetBindings().Update(FN_TRACK_CHANGES_IN_THIS_VIEW); + pViewFrame->GetBindings().Invalidate(FN_TRACK_CHANGES_IN_ALL_VIEWS); + pViewFrame->GetBindings().Update(FN_TRACK_CHANGES_IN_ALL_VIEWS); } } } diff --git a/sw/source/uibase/uiview/viewstat.cxx b/sw/source/uibase/uiview/viewstat.cxx index fcc7c24d976b..c6846f15d486 100644 --- a/sw/source/uibase/uiview/viewstat.cxx +++ b/sw/source/uibase/uiview/viewstat.cxx @@ -357,6 +357,14 @@ void SwView::GetState(SfxItemSet &rSet) } m_bForceChangesToolbar = false; break; + case FN_TRACK_CHANGES_IN_THIS_VIEW: + { + } + break; + case FN_TRACK_CHANGES_IN_ALL_VIEWS: + { + } + break; case FN_REDLINE_PROTECT : rSet.Put( SfxBoolItem( nWhich, GetDocShell()->HasChangeRecordProtection() ) ); break; diff --git a/sw/source/uibase/wrtsh/select.cxx b/sw/source/uibase/wrtsh/select.cxx index fdac5dc57cb3..f13d678e4b9f 100644 --- a/sw/source/uibase/wrtsh/select.cxx +++ b/sw/source/uibase/wrtsh/select.cxx @@ -769,9 +769,9 @@ void SwWrtShell::SetInsMode( bool bOn ) } //Overwrite mode is incompatible with red-lining -void SwWrtShell::SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode ) +void SwWrtShell::SetRedlineFlagsAndCheckInsMode( RedlineFlags eMode, bool bRecordAllViews ) { - SetRedlineFlags( eMode ); + SetRedlineFlags( eMode, bRecordAllViews ); if (IsRedlineOn()) SetInsMode(); } diff --git a/sw/uiconfig/swriter/popupmenu/recordtrackedchanges.xml b/sw/uiconfig/swriter/popupmenu/recordtrackedchanges.xml new file mode 100644 index 000000000000..f3132df4661d --- /dev/null +++ b/sw/uiconfig/swriter/popupmenu/recordtrackedchanges.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * +--> +<menu:menupopup xmlns:menu="http://openoffice.org/2001/menu"> + <menu:menuitem menu:id=".uno:TrackChangesInAllViews" menu:style="radio"/> + <menu:menuitem menu:id=".uno:TrackChangesInThisView" menu:style="radio"/> +</menu:menupopup>
