tdf#144272 sw: track change of paragraph style
Modifying style of a paragraph, e.g. from "Standard"
or "Text body" to "Heading n" styles wasn't recorded
by change tracking.
Now it's possible to track and reject these changes
also after DOCX export/import.
Note: ODF track changes doesn't support format-only
changes, so likely it will need to export the paragraph
content two times, with the old and with the new
paragraph styles, too).
Note: selecting multiple paragraphs to modify their
styles at once doesn't record the changes, yet, because
multi-paragraph ParagraphFormat redline range hasn't
supported by AppendRedline().
Change-Id: I2d81fa23c59b7b75b3101dc3f2bb8c9eed8ab165
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122707
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 1a9cbdc..4a273af 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -3194,6 +3194,58 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf50447_keep_hints)
}
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf144272)
{
SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf50447.fodt");
SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
// turn on red-lining and show changes
pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete
| RedlineFlags::ShowInsert);
CPPUNIT_ASSERT_MESSAGE("redlining should be on",
pDoc->getIDocumentRedlineAccess().IsRedlineOn());
CPPUNIT_ASSERT_MESSAGE(
"redlines should be visible",
IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
// paragraph style of the first paragraph: Heading 1, second paragraph: Standard
CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
getProperty<OUString>(getParagraph(1), "ParaStyleName"));
CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
getProperty<OUString>(getParagraph(2), "ParaStyleName"));
// modify with track changes: Standard and Heading 2
uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({
{ "Style", uno::makeAny(OUString("Standard")) },
{ "FamilyName", uno::makeAny(OUString("ParagraphStyles")) },
});
dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues);
pWrtShell->Down(/*bSelect=*/false);
aPropertyValues = comphelper::InitPropertySequence({
{ "Style", uno::makeAny(OUString("Heading 2")) },
{ "FamilyName", uno::makeAny(OUString("ParagraphStyles")) },
});
dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues);
CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
getProperty<OUString>(getParagraph(1), "ParaStyleName"));
CPPUNIT_ASSERT_EQUAL(OUString("Heading 2"),
getProperty<OUString>(getParagraph(2), "ParaStyleName"));
// reject tracked changes
dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {});
// This was Standard (missing reject)
CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"),
getProperty<OUString>(getParagraph(1), "ParaStyleName"));
// This was Heading 2 (missing reject)
CPPUNIT_ASSERT_EQUAL(OUString("Standard"),
getProperty<OUString>(getParagraph(2), "ParaStyleName"));
}
CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf101873)
{
SwDoc* pDoc = createSwDoc();
diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx
index 6b76f14..dbed7a7 100644
--- a/sw/source/core/edit/edfcol.cxx
+++ b/sw/source/core/edit/edfcol.cxx
@@ -68,6 +68,8 @@
#include <vcl/weld.hxx>
#include <vcl/virdev.hxx>
#include <redline.hxx>
#include <poolfmt.hxx>
#include <hintids.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
@@ -2216,6 +2218,21 @@ void SwEditShell::SetTextFormatColl(SwTextFormatColl *pFormat,
GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eRedlMode );
}
// store previous paragraph style for track changes
OUString sParaStyleName;
sal_uInt16 nPoolId = USHRT_MAX;
SwContentNode * pCnt = rPaM.Start()->nNode.GetNode().GetContentNode();
if ( pCnt && pCnt->GetTextNode() && GetDoc()->getIDocumentRedlineAccess().IsRedlineOn() )
{
const SwTextFormatColl* pTextFormatColl = pCnt->GetTextNode()->GetTextColl();
sal_uInt16 nStylePoolId = pTextFormatColl->GetPoolFormatId();
// default paragraph style
if ( nStylePoolId == RES_POOLCOLL_STANDARD )
nPoolId = nStylePoolId;
else
sParaStyleName = pTextFormatColl->GetName();
}
// Change the paragraph style to pLocal and remove all direct paragraph formatting.
GetDoc()->SetTextFormatColl(rPaM, pLocal, true, bResetListAttrs, GetLayout());
@@ -2227,6 +2244,27 @@ void SwEditShell::SetTextFormatColl(SwTextFormatColl *pFormat,
aPaM.End()->nContent = pEndTextNode->GetText().getLength();
}
GetDoc()->RstTextAttrs(aPaM, /*bInclRefToxMark=*/false, /*bExactRange=*/true, GetLayout());
// add redline tracking the previous paragraph style
if ( GetDoc()->getIDocumentRedlineAccess().IsRedlineOn() &&
// multi-paragraph ParagraphFormat redline ranges
// haven't supported by AppendRedline(), yet
// TODO handle multi-paragraph selections, too,
// e.g. by breaking them to single paragraphs
aPaM.Start()->nNode == aPaM.End()->nNode )
{
SwRangeRedline * pRedline = new SwRangeRedline( RedlineType::ParagraphFormat, aPaM );
auto const result(GetDoc()->getIDocumentRedlineAccess().AppendRedline( pRedline, true));
// store original paragraph style to reject formatting change
if ( IDocumentRedlineAccess::AppendResult::IGNORED != result &&
( nPoolId == RES_POOLCOLL_STANDARD || !sParaStyleName.isEmpty() ) )
{
std::unique_ptr<SwRedlineExtraData_FormatColl> xExtra;
xExtra.reset(new SwRedlineExtraData_FormatColl(sParaStyleName, nPoolId, nullptr));
if (xExtra)
pRedline->SetExtraData( xExtra.get() );
}
}
}
}