tdf#166319 sw interdependent redlines: fix redo of direct reject for format

Open the bugdoc, select the format part of the insert-then-format
redline in the manage changes dialog, reject, undo, redo: the result is
<ins>AAA</ins>BBB<ins>CCC</ins> instead of one big insert redline.
Similarly, open the other bugdoc with a delete and a format redline in
it, select the format part of the delete-then-format redline in the
manage changes dialog, reject, undo, redo: the result is
<del>AAA</del><format>BBB</format><del>CCC</del> instead of one big
delete redline.

What happens is that the UI action uses
sw::DocumentRedlineManager::RejectRedlineRange(), while the redo uses
sw::DocumentRedlineManager::RejectRedline(), and while the first
supported direct accepts, the later did not.

Fix the problem by:
1) In sw::DocumentRedlineManager::RejectRedlineRange(), create the undo
   action with the correct depth & directness for direct rejects
2) In DocumentRedlineManager::RejectRedline(), use use
   lcl_RejectOuterFormat() to directly reject a format redline instead
   of the usual lcl_AcceptRejectRedl(), which gives us matching behavior
   for the UI action & the redo.

Writer's interdependent redlines are now in a reasonable state with
this: actions for the redline under cursor work with ins/del when
possible (looking "through" format); while the manage changes dialog
still allows working on the format redline directly if that's wanted.

Change-Id: Idb90dfbd86ac26ff51da8a34731ea75a48748bdf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192015
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
This commit is contained in:
Miklos Vajna
2025-10-07 12:37:39 +02:00
parent e644ec9527
commit 1e3b8177ae
6 changed files with 54 additions and 12 deletions
+2 -1
View File
@@ -217,7 +217,8 @@ public:
= 0;
virtual bool RejectRedline(/*[in]*/ const SwPaM& rPam, /*[in]*/ bool bCallDelete,
/*[in]*/ sal_Int8 nDepth = 0)
/*[in]*/ sal_Int8 nDepth = 0,
bool bDirect = false)
= 0;
virtual const SwRangeRedline* SelNextRedline(/*[in]*/SwPaM& rPam) const = 0;
+27
View File
@@ -248,6 +248,20 @@ CPPUNIT_TEST_FIXTURE(Test, testDelThenFormatDirect)
const SvxWeightItem& rWeightItem = aSet.Get(RES_CHRATR_WEIGHT);
CPPUNIT_ASSERT_EQUAL(WEIGHT_NORMAL, rWeightItem.GetValue());
}
// And given an undo:
pWrtShell->Undo();
// When redoing:
pWrtShell->Redo();
// Then make sure that we only get a single big delete redline:
// Without the accompanying fix in place, this test would have failed with:
// - Expected: 1
// - Actual : 3
// i.e. we got <del>AAA</del><format>BBB</format><del>CCC</del> instead of one big delete
// redline.
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
}
CPPUNIT_TEST_FIXTURE(Test, testInsThenFormatDirect)
@@ -325,6 +339,19 @@ CPPUNIT_TEST_FIXTURE(Test, testInsThenFormatDirect)
const SvxWeightItem& rWeightItem = aSet.Get(RES_CHRATR_WEIGHT);
CPPUNIT_ASSERT_EQUAL(WEIGHT_NORMAL, rWeightItem.GetValue());
}
// And given an undo:
pWrtShell->Undo();
// When redoing:
pWrtShell->Redo();
// Then make sure that we only get a single big insert redline:
// Without the accompanying fix in place, this test would have failed with:
// - Expected: 1
// - Actual : 2
// i.e. we got <ins>AAA</ins>BBB<ins>CCC</ins> instead of one big insert.
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
}
}
+19 -6
View File
@@ -3739,13 +3739,13 @@ bool DocumentRedlineManager::RejectRedlineRange(SwRedlineTable::size_type nPosOr
if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
{
sal_Int8 nDepth = 0;
if (bHierarchicalFormat && pTmp->GetType(1) == RedlineType::Delete)
if (bHierarchicalFormat && pTmp->GetType(1) == RedlineType::Delete && !bDirect)
{
// Only work with the underlying delete, so the undo action matches the UI
// action below.
nDepth = 1;
}
auto pUndoRdl = std::make_unique<SwUndoRejectRedline>(*pTmp, nDepth, bHierarchical);
auto pUndoRdl = std::make_unique<SwUndoRejectRedline>(*pTmp, nDepth, bHierarchical, bDirect);
#if OSL_DEBUG_LEVEL > 0
pUndoRdl->SetRedlineCountDontCheck(true);
#endif
@@ -3982,7 +3982,7 @@ bool DocumentRedlineManager::RejectRedline(SwRedlineTable::size_type nPos,
// #TODO - add 'SwExtraRedlineTable' also ?
}
bool DocumentRedlineManager::RejectRedline( const SwPaM& rPam, bool bCallDelete, sal_Int8 nDepth )
bool DocumentRedlineManager::RejectRedline( const SwPaM& rPam, bool bCallDelete, sal_Int8 nDepth, bool bDirect )
{
// Switch to visible in any case
if( (RedlineFlags::ShowInsert | RedlineFlags::ShowDelete) !=
@@ -4002,14 +4002,27 @@ bool DocumentRedlineManager::RejectRedline( const SwPaM& rPam, bool bCallDelete,
}
int nRet = 0;
SwRedlineTable::size_type nRdlIdx = 0;
const SwRangeRedline* pRedline = maRedlineTable.FindAtPosition(*rPam.Start(), nRdlIdx);
if (nDepth == 0)
{
nRet = lcl_AcceptRejectRedl(lcl_RejectRedline, maRedlineTable, bCallDelete, aPam);
bool bHierarchicalFormat = pRedline && pRedline->GetType() == RedlineType::Format && pRedline->GetStackCount() > 1;
if (bHierarchicalFormat && bDirect && (pRedline->GetType(1) == RedlineType::Insert || pRedline->GetType(1) == RedlineType::Delete))
{
// Direct reject: work with the format redline on top.
if (lcl_RejectOuterFormat(maRedlineTable, nRdlIdx))
{
nRet = 1;
}
}
else
{
// Non-direct reject: work with all redlines under aPam.
nRet = lcl_AcceptRejectRedl(lcl_RejectRedline, maRedlineTable, bCallDelete, aPam);
}
}
else
{
SwRedlineTable::size_type nRdlIdx = 0;
const SwRangeRedline* pRedline = maRedlineTable.FindAtPosition(*rPam.Start(), nRdlIdx);
if (nDepth == 1 && pRedline && pRedline->GetType(0) == RedlineType::Format
&& pRedline->GetType(1) == RedlineType::Delete)
{
@@ -118,7 +118,8 @@ public:
bool bDirect = false) override;
virtual bool RejectRedline(/*[in]*/ const SwPaM& rPam, /*[in]*/ bool bCallDelete,
/*[in]*/ sal_Int8 nDepth = 0) override;
/*[in]*/ sal_Int8 nDepth = 0,
bool bDirect = false) override;
virtual void AcceptAllRedline(/*[in]*/bool bAcceptReject) override;
+1 -1
View File
@@ -129,7 +129,7 @@ private:
virtual void RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam) override;
public:
SwUndoRejectRedline( const SwPaM& rRange, sal_Int8 nDepth = 0, bool bHierarchical = false );
SwUndoRejectRedline( const SwPaM& rRange, sal_Int8 nDepth = 0, bool bHierarchical = false, bool bDirect = false );
virtual void RepeatImpl( ::sw::RepeatContext & ) override;
};
+3 -3
View File
@@ -482,14 +482,14 @@ void SwUndoAcceptRedline::RepeatImpl(::sw::RepeatContext & rContext)
rContext.GetDoc().getIDocumentRedlineAccess().AcceptRedline(rContext.GetRepeatPaM(), true);
}
SwUndoRejectRedline::SwUndoRejectRedline( const SwPaM& rRange, sal_Int8 nDepth /* = 0 */, bool bHierarchical /*= false*/ )
: SwUndoRedline( SwUndoId::REJECT_REDLINE, rRange, nDepth, bHierarchical )
SwUndoRejectRedline::SwUndoRejectRedline( const SwPaM& rRange, sal_Int8 nDepth /* = 0 */, bool bHierarchical /*= false*/, bool bDirect /*= false*/ )
: SwUndoRedline( SwUndoId::REJECT_REDLINE, rRange, nDepth, bHierarchical, bDirect )
{
}
void SwUndoRejectRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
rDoc.getIDocumentRedlineAccess().RejectRedline(rPam, false, mnDepth);
rDoc.getIDocumentRedlineAccess().RejectRedline(rPam, false, mnDepth, mbDirect);
}
void SwUndoRejectRedline::RepeatImpl(::sw::RepeatContext & rContext)