sw/qa/uibase/shells/shells.cxx | 67 ++++++++++++++++++++++++++++++++++---- sw/source/uibase/uno/loktxdoc.cxx | 31 ++++++++++++++--- 2 files changed, 86 insertions(+), 12 deletions(-)
New commits: commit 55a132e59ac1b4fa2e7fc6776928ba12eec13442 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Mon Jun 30 13:38:51 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Jun 30 17:54:48 2025 +0200 LOK Extract API: add contextLen filter argument to redline data extraction Allows to specify the length of returned textBefore / textAfter fields. Change-Id: I17abd72fa063d8033e552e55844bf6b7fc1780d0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187189 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/uibase/shells/shells.cxx b/sw/qa/uibase/shells/shells.cxx index 9a467cd89ab0..22da30260421 100644 --- a/sw/qa/uibase/shells/shells.cxx +++ b/sw/qa/uibase/shells/shells.cxx @@ -892,14 +892,18 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) { createSwDoc("three-changes.fodt"); - // extract - tools::JsonWriter aJsonWriter; - std::string_view aCommand(".uno:ExtractDocumentStructure?filter=trackchanges"); - getSwTextDoc()->getCommandValues(aJsonWriter, aCommand); - boost::property_tree::ptree tree; - std::stringstream aStream(std::string(aJsonWriter.finishAndGetAsOString())); - boost::property_tree::read_json(aStream, tree); + + // 1. No filter arguments + { + // extract + tools::JsonWriter aJsonWriter; + std::string_view aCommand(".uno:ExtractDocumentStructure?filter=trackchanges"); + getSwTextDoc()->getCommandValues(aJsonWriter, aCommand); + + std::stringstream aStream(std::string(aJsonWriter.finishAndGetAsOString())); + boost::property_tree::read_json(aStream, tree); + } CPPUNIT_ASSERT_EQUAL(size_t(1), tree.size()); boost::property_tree::ptree docStructure = tree.get_child("DocStructure"); @@ -969,6 +973,55 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureExtractRedlines) } CPPUNIT_ASSERT(bool(it == docStructure.end())); + + // 2. Test contextLen filter argument + { + // extract + tools::JsonWriter aJsonWriter; + std::string_view aCommand( + ".uno:ExtractDocumentStructure?filter=trackchanges,foo:bar, contextLen: 15,,"); + getSwTextDoc()->getCommandValues(aJsonWriter, aCommand); + + std::stringstream aStream(std::string(aJsonWriter.finishAndGetAsOString())); + boost::property_tree::read_json(aStream, tree); + } + + CPPUNIT_ASSERT_EQUAL(size_t(1), tree.size()); + docStructure = tree.get_child("DocStructure"); + CPPUNIT_ASSERT_EQUAL(size_t(3), docStructure.size()); + it = docStructure.begin(); + + { + // First change + CPPUNIT_ASSERT(it != docStructure.end()); + const auto & [ name, change ] = *it; + CPPUNIT_ASSERT_EQUAL("TrackChanges.ByIndex.0"s, name); + CPPUNIT_ASSERT_EQUAL("ursus egestas. "s, change.get<std::string>("textBefore")); + CPPUNIT_ASSERT_EQUAL(" blandit auctor"s, change.get<std::string>("textAfter")); + ++it; + } + + { + // Second change + CPPUNIT_ASSERT(it != docStructure.end()); + const auto & [ name, change ] = *it; + CPPUNIT_ASSERT_EQUAL("TrackChanges.ByIndex.1"s, name); + CPPUNIT_ASSERT_EQUAL("ctor arcu, nec "s, change.get<std::string>("textBefore")); + CPPUNIT_ASSERT_EQUAL(" eros molestie "s, change.get<std::string>("textAfter")); + ++it; + } + + { + // Third change + CPPUNIT_ASSERT(it != docStructure.end()); + const auto & [ name, change ] = *it; + CPPUNIT_ASSERT_EQUAL("TrackChanges.ByIndex.2"s, name); + CPPUNIT_ASSERT_EQUAL("esque est orci."s, change.get<std::string>("textBefore")); + CPPUNIT_ASSERT_EQUAL(""s, change.get<std::string>("textAfter")); + ++it; + } + + CPPUNIT_ASSERT(bool(it == docStructure.end())); } CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testUpdateRefmarks) diff --git a/sw/source/uibase/uno/loktxdoc.cxx b/sw/source/uibase/uno/loktxdoc.cxx index c1a905368e34..e638a8142c60 100644 --- a/sw/source/uibase/uno/loktxdoc.cxx +++ b/sw/source/uibase/uno/loktxdoc.cxx @@ -855,8 +855,29 @@ void GetDocStructureDocProps(tools::JsonWriter& rJsonWriter, const SwDocShell* p } /// Implements getCommandValues(".uno:ExtractDocumentStructures") for redlines -void GetDocStructureTrackChanges(tools::JsonWriter& rJsonWriter, const SwDocShell* pDocShell) +void GetDocStructureTrackChanges(tools::JsonWriter& rJsonWriter, const SwDocShell* pDocShell, + std::u16string_view filterArguments) { + // filter arguments are separated from the filter name by comma, and are name:value pairs + // separated by commas + if (!filterArguments.empty() && !filterArguments.starts_with(u",")) + return; // not a correct filter + sal_Int16 nContextLen = 200; + for (size_t paramPos = 1; paramPos < filterArguments.size();) + { + std::u16string_view param = o3tl::getToken(filterArguments, u',', paramPos); + sal_Int32 nIndex = 0; + std::u16string_view token = o3tl::trim(o3tl::getToken(param, 0, u':', nIndex)); + std::u16string_view value + = nIndex > 0 ? o3tl::trim(param.substr(nIndex)) : std::u16string_view{}; + if (token == u"contextLen") + { + if (!value.empty()) + nContextLen = o3tl::toInt32(value); + } + // else unknown filter argument (maybe from a newer API?) - ignore + } + auto xRedlinesEnum = pDocShell->GetBaseModel()->getRedlines()->createEnumeration(); for (sal_Int32 i = 0; xRedlinesEnum->hasMoreElements(); ++i) { @@ -881,13 +902,13 @@ void GetDocStructureTrackChanges(tools::JsonWriter& rJsonWriter, const SwDocShel if (xStart) { auto xCursor = xStart->getText()->createTextCursorByRange(xStart); - xCursor->goLeft(200, /*bExpand*/ true); + xCursor->goLeft(nContextLen, /*bExpand*/ true); rJsonWriter.put("textBefore", xCursor->getString()); } if (xEnd) { auto xCursor = xEnd->getText()->createTextCursorByRange(xEnd); - xCursor->goRight(200, /*bExpand*/ true); + xCursor->goRight(nContextLen, /*bExpand*/ true); rJsonWriter.put("textAfter", xCursor->getString()); } OUString changeText; @@ -938,8 +959,8 @@ void GetDocStructure(tools::JsonWriter& rJsonWriter, const SwDocShell* pDocShell if (filter.isEmpty() || filter == "docprops") GetDocStructureDocProps(rJsonWriter, pDocShell); - if (filter.isEmpty() || filter == "trackchanges") - GetDocStructureTrackChanges(rJsonWriter, pDocShell); + if (std::u16string_view rest; filter.isEmpty() || filter.startsWith("trackchanges", &rest)) + GetDocStructureTrackChanges(rJsonWriter, pDocShell, o3tl::trim(rest)); } /// Implements getCommandValues(".uno:Sections").