sw/qa/uibase/shells/data/three-changes.fodt | 6 ++++- sw/qa/uibase/shells/shells.cxx | 12 ++++++++--- sw/source/uibase/uno/loktxdoc.cxx | 30 ++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-)
New commits: commit 7b5b9a5f08a69029594c45ba06edb249d0a11ba1 Author: Mike Kaganski <[email protected]> AuthorDate: Fri Sep 19 12:18:39 2025 +0500 Commit: Mike Kaganski <[email protected]> CommitDate: Mon Sep 22 08:55:33 2025 +0200 LOK Extract API: add startPageNumber argument to redline data extraction Allows to obtain page number of starting points of redlines, returned in new startPageNumber field. Since this information requires manipulations with XTextViewCursor, which is expensive, this is made optional, and is off by default. The argument must get "true" value to enable the functionality. Change-Id: I6180eb8789f44cd20d8da277452987df6ebce055 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191175 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/sw/qa/uibase/shells/data/three-changes.fodt b/sw/qa/uibase/shells/data/three-changes.fodt index 0c7072b244a0..ba13bcb58f41 100644 --- a/sw/qa/uibase/shells/data/three-changes.fodt +++ b/sw/qa/uibase/shells/data/three-changes.fodt @@ -2,6 +2,9 @@ <office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text"> <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> <style:style style:name="T1" style:family="text"> <style:text-properties fo:font-weight="bold"/> </style:style> @@ -34,7 +37,8 @@ </text:insertion> </text:changed-region> </text:tracked-changes> - <text:p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus egestas. <text:change-start text:change-id="ct2412392131792"/>Donec<text:change-end text:change-id="ct2412392131792"/> blandit auctor arcu, nec <text:change-start text:change-id="ct2412428113776"/><text:span text:style-name="T1">pellentesque</text:span><text:change-end text:change-id="ct2412428113776"/> eros molestie eget. In consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est orci.<text:change-start text:change-id="ct2412428117232"/> Sapienti sat.<text:change-end text:change-id="ct2412428117232"/></text:p> + <text:p/> + <text:p text:style-name="P1">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus egestas. <text:change-start text:change-id="ct2412392131792"/>Donec<text:change-end text:change-id="ct2412392131792"/> blandit auctor arcu, nec <text:change-start text:change-id="ct2412428113776"/><text:span text:style-name="T1">pellentesque</text:span><text:change-end text:change-id="ct2412428113776"/> eros molestie eget. In consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est orci.<text:change-start text:change-id="ct2412428117232"/> Sapienti sat.<text:change-end text:change-id="ct2412428117232"/></text:p> </office:text> </office:body> </office:document> \ No newline at end of file diff --git a/sw/qa/uibase/shells/shells.cxx b/sw/qa/uibase/shells/shells.cxx index 117928917de9..5838de9c4e73 100644 --- a/sw/qa/uibase/shells/shells.cxx +++ b/sw/qa/uibase/shells/shells.cxx @@ -921,6 +921,7 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) CPPUNIT_ASSERT_EQUAL("Mike"s, change.get<std::string>("author")); CPPUNIT_ASSERT_EQUAL("Delete “Donec”"s, change.get<std::string>("description")); CPPUNIT_ASSERT_EQUAL(""s, change.get<std::string>("comment")); + CPPUNIT_ASSERT(bool(change.find("startPageNumber") == change.not_found())); auto text_before = change.get<std::string>("textBefore"); CPPUNIT_ASSERT_EQUAL(size_t(200), text_before.size()); CPPUNIT_ASSERT(text_before.ends_with(" egestas. ")); @@ -942,6 +943,7 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) CPPUNIT_ASSERT_EQUAL("Mike"s, change.get<std::string>("author")); CPPUNIT_ASSERT_EQUAL("Attributes changed"s, change.get<std::string>("description")); CPPUNIT_ASSERT_EQUAL(""s, change.get<std::string>("comment")); + CPPUNIT_ASSERT(bool(change.find("startPageNumber") == change.not_found())); auto text_before = change.get<std::string>("textBefore"); CPPUNIT_ASSERT_EQUAL(size_t(200), text_before.size()); CPPUNIT_ASSERT(text_before.ends_with(" arcu, nec ")); @@ -963,6 +965,7 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) CPPUNIT_ASSERT_EQUAL("Mike"s, change.get<std::string>("author")); CPPUNIT_ASSERT_EQUAL("Insert “ Sapienti sat.”"s, change.get<std::string>("description")); CPPUNIT_ASSERT_EQUAL(""s, change.get<std::string>("comment")); + CPPUNIT_ASSERT(bool(change.find("startPageNumber") == change.not_found())); auto text_before = change.get<std::string>("textBefore"); CPPUNIT_ASSERT_EQUAL(size_t(200), text_before.size()); CPPUNIT_ASSERT(text_before.ends_with(" est orci.")); @@ -974,12 +977,12 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) CPPUNIT_ASSERT(bool(it == docStructure.end())); - // 2. Test contextLen filter argument + // 2. Test contextLen and startPageNumber filter arguments { // extract tools::JsonWriter aJsonWriter; - std::string_view aCommand( - ".uno:ExtractDocumentStructure?filter=trackchanges,foo:bar, contextLen: 15,,"); + std::string_view aCommand(".uno:ExtractDocumentStructure?filter=trackchanges,foo:bar, " + "contextLen: 15, startPageNumber :true ,,"); getSwTextDoc()->getCommandValues(aJsonWriter, aCommand); std::stringstream aStream(std::string(aJsonWriter.finishAndGetAsOString())); @@ -996,6 +999,7 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) CPPUNIT_ASSERT(it != docStructure.end()); const auto & [ name, change ] = *it; CPPUNIT_ASSERT_EQUAL("TrackChanges.ByIndex.0"s, name); + CPPUNIT_ASSERT_EQUAL("2"s, change.get<std::string>("startPageNumber")); CPPUNIT_ASSERT_EQUAL("ursus egestas. "s, change.get<std::string>("textBefore")); CPPUNIT_ASSERT_EQUAL(" blandit auctor"s, change.get<std::string>("textAfter")); ++it; @@ -1006,6 +1010,7 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) CPPUNIT_ASSERT(it != docStructure.end()); const auto & [ name, change ] = *it; CPPUNIT_ASSERT_EQUAL("TrackChanges.ByIndex.1"s, name); + CPPUNIT_ASSERT_EQUAL("2"s, change.get<std::string>("startPageNumber")); CPPUNIT_ASSERT_EQUAL("ctor arcu, nec "s, change.get<std::string>("textBefore")); CPPUNIT_ASSERT_EQUAL(" eros molestie "s, change.get<std::string>("textAfter")); ++it; @@ -1016,6 +1021,7 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) CPPUNIT_ASSERT(it != docStructure.end()); const auto & [ name, change ] = *it; CPPUNIT_ASSERT_EQUAL("TrackChanges.ByIndex.2"s, name); + CPPUNIT_ASSERT_EQUAL("2"s, change.get<std::string>("startPageNumber")); CPPUNIT_ASSERT_EQUAL("esque est orci."s, change.get<std::string>("textBefore")); CPPUNIT_ASSERT_EQUAL(""s, change.get<std::string>("textAfter")); ++it; diff --git a/sw/source/uibase/uno/loktxdoc.cxx b/sw/source/uibase/uno/loktxdoc.cxx index 2906920b712e..1e13e8846bc4 100644 --- a/sw/source/uibase/uno/loktxdoc.cxx +++ b/sw/source/uibase/uno/loktxdoc.cxx @@ -25,6 +25,7 @@ #include <com/sun/star/beans/XPropertyAccess.hpp> +#include <comphelper/diagnose_ex.hxx> #include <comphelper/sequence.hxx> #include <o3tl/string_view.hxx> #include <tools/json_writer.hxx> @@ -51,7 +52,9 @@ #include <pagefrm.hxx> #include <com/sun/star/text/XTextContent.hpp> +#include <com/sun/star/text/XPageCursor.hpp> #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp> +#include <com/sun/star/text/XTextViewCursorSupplier.hpp> #include <com/sun/star/chart2/XInternalDataProvider.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart/XChartDocument.hpp> @@ -957,6 +960,7 @@ void GetDocStructureTrackChanges(tools::JsonWriter& rJsonWriter, SwDocShell* pDo if (!filterArguments.empty() && !filterArguments.starts_with(u",")) return; // not a correct filter sal_Int16 nContextLen = 200; + bool bPageNumbers = false; for (size_t paramPos = 1; paramPos < filterArguments.size();) { std::u16string_view param = o3tl::getToken(filterArguments, u',', paramPos); @@ -969,11 +973,25 @@ void GetDocStructureTrackChanges(tools::JsonWriter& rJsonWriter, SwDocShell* pDo if (!value.empty()) nContextLen = o3tl::toInt32(value); } + else if (token == u"startPageNumber") + { + bPageNumbers = value == u"true"; + } // else unknown filter argument (maybe from a newer API?) - ignore } SwDoc& rDoc = *pDocShell->GetDoc(); const SwRedlineTable& rTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable(); + uno::Reference<text::XTextCursor> xTextViewCursor; + uno::Reference<text::XPageCursor> xTextPageCursor; + if (bPageNumbers) + { + if (auto xSupplier = pDocShell->GetController().query<text::XTextViewCursorSupplier>()) + { + xTextViewCursor.set(xSupplier->getViewCursor()); + xTextPageCursor.set(xTextViewCursor, uno::UNO_QUERY); + } + } for (size_t i = 0; i < rTable.size(); ++i) { @@ -1002,6 +1020,18 @@ void GetDocStructureTrackChanges(tools::JsonWriter& rJsonWriter, SwDocShell* pDo { auto xCursor = xStart->getText()->createTextCursorByRange(xStart); xCursor->goLeft(nContextLen, /*bExpand*/ true); + if (xTextPageCursor) + { + try + { + xTextViewCursor->gotoRange(xStart, false); + rJsonWriter.put("startPageNumber", xTextPageCursor->getPage()); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("sw.ui"); + } + } rJsonWriter.put("textBefore", xCursor->getString()); } if (xEnd)
