sw/qa/uibase/uno/uno.cxx | 45 +++++++++++++++++++++++++++++-------- sw/source/uibase/shells/basesh.cxx | 23 +++++++++++++++++- sw/source/uibase/uno/loktxdoc.cxx | 21 ++++++++++++++++- 3 files changed, 77 insertions(+), 12 deletions(-)
New commits: commit 8eae44879532f6448b5cce93d4d060197604eed5 Author: Pranam Lashkari <[email protected]> AuthorDate: Sat Jan 7 02:39:38 2023 +0530 Commit: Andras Timar <[email protected]> CommitDate: Sun Jan 8 12:16:03 2023 +0000 sw, UpdateFields: update in sorted order This was using the order used by GetItemSurrogates() which can be hard to predict So it used to update field in uncertain ways Now it updates field in order of the fields in file Change-Id: I7fc39b476cae6ed6a7fb7186803d4205832d7a73 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145167 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Andras Timar <[email protected]> diff --git a/sw/source/uibase/shells/basesh.cxx b/sw/source/uibase/shells/basesh.cxx index 0e2f6769167c..b5f3eab9e60a 100644 --- a/sw/source/uibase/shells/basesh.cxx +++ b/sw/source/uibase/shells/basesh.cxx @@ -799,10 +799,29 @@ bool UpdateFieldContents(SfxRequest& rReq, SwWrtShell& rWrtSh) SwDoc* pDoc = rWrtSh.GetDoc(); pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSBOOKMARK, nullptr); rWrtSh.StartAction(); + + std::vector<const SwFormatRefMark*> aRefMarks; + + for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i) + { + aRefMarks.push_back(pDoc->GetRefMark(i)); + } + + std::sort(aRefMarks.begin(), aRefMarks.end(), + [](const SwFormatRefMark* pMark1, const SwFormatRefMark* pMark2) -> bool { + const SwTextRefMark* pTextRefMark1 = pMark1->GetTextRefMark(); + const SwTextRefMark* pTextRefMark2 = pMark2->GetTextRefMark(); + SwPosition aPos1(const_cast<SwTextNode&>(pTextRefMark1->GetTextNode()), + pTextRefMark1->GetStart()); + SwPosition aPos2(const_cast<SwTextNode&>(pTextRefMark2->GetTextNode()), + pTextRefMark2->GetStart()); + return aPos1 < aPos2; + }); + sal_uInt16 nFieldIndex = 0; - for (sal_uInt16 nRefMark = 0; nRefMark < pDoc->GetRefMarks(); ++nRefMark) + for (auto& pIntermediateRefMark : aRefMarks) { - auto pRefMark = const_cast<SwFormatRefMark*>(pDoc->GetRefMark(nRefMark)); + auto pRefMark = const_cast<SwFormatRefMark*>(pIntermediateRefMark); if (!pRefMark->GetRefName().startsWith(rNamePrefix)) { continue; commit 2eb4e5852db9a756809fe2dda9849a9423b66d1b Author: Miklos Vajna <[email protected]> AuthorDate: Fri Jan 6 13:35:21 2023 +0100 Commit: Andras Timar <[email protected]> CommitDate: Sun Jan 8 12:15:48 2023 +0000 sw lok: get all refmarks: sort the refmarks array This was using the order used by GetItemSurrogates(), which is mostly by pointer address. We know that these pool items have a text attribute, which have a node and a content index, sort by that. In theory two refmark may start at the same doc model position, but that's never the case when using Zotero, so don't worry about that for now. For a document with 5 refmarks, the original order I got was 2-3-5-4-1, now it's properly 1-2-3-4-5. (cherry picked from commit 5a2ee5ba893b6b8f4e7fd6623b7f10faf0bda509) Change-Id: I2768845414bd36afca91ec02a0f3364c246ddfd9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145149 Reviewed-by: Andras Timar <[email protected]> Tested-by: Andras Timar <[email protected]> diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx index 41866636a969..02bacf5b02f1 100644 --- a/sw/qa/uibase/uno/uno.cxx +++ b/sw/qa/uibase/uno/uno.cxx @@ -217,14 +217,21 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetBookmarks) CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields) { // Given a document with a refmark: - createSwDoc(); - uno::Sequence<css::beans::PropertyValue> aArgs = { - comphelper::makePropertyValue("TypeName", uno::Any(OUString("SetRef"))), - comphelper::makePropertyValue( - "Name", uno::Any(OUString("ZOTERO_ITEM CSL_CITATION {} RNDpyJknp173F"))), - comphelper::makePropertyValue("Content", uno::Any(OUString("mycontent"))), - }; - dispatchCommand(mxComponent, ".uno:InsertField", aArgs); + SwDoc* pDoc = createSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + OUString aName("ZOTERO_ITEM CSL_CITATION {} "); + for (int i = 0; i < 5; ++i) + { + uno::Sequence<css::beans::PropertyValue> aArgs = { + comphelper::makePropertyValue("TypeName", uno::Any(OUString("SetRef"))), + comphelper::makePropertyValue("Name", uno::Any(aName + OUString::number(i + 1))), + comphelper::makePropertyValue("Content", uno::Any(OUString("mycontent"))), + }; + dispatchCommand(mxComponent, ".uno:InsertField", aArgs); + pWrtShell->SttEndDoc(/*bStt=*/false); + pWrtShell->SplitNode(); + pWrtShell->SttEndDoc(/*bStt=*/false); + } // When getting the refmarks: tools::JsonWriter aJsonWriter; @@ -240,7 +247,27 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields) // Without the accompanying fix in place, this test would have failed with: // - No such node (setRefs) // i.e. the returned JSON was just empty. - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aTree.get_child("setRefs").count("")); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), aTree.get_child("setRefs").count("")); + auto it = aTree.get_child("setRefs").begin(); + boost::property_tree::ptree aRef = (it++)->second; + CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 1"), + aRef.get<std::string>("name")); + aRef = (it++)->second; + CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 2"), + aRef.get<std::string>("name")); + aRef = (it++)->second; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: ZOTERO_ITEM CSL_CITATION {} 3 + // - Actual : ZOTERO_ITEM CSL_CITATION {} 4 + // i.e. the output was unsorted. + CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 3"), + aRef.get<std::string>("name")); + aRef = (it++)->second; + CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 4"), + aRef.get<std::string>("name")); + aRef = (it++)->second; + CPPUNIT_ASSERT_EQUAL(std::string("ZOTERO_ITEM CSL_CITATION {} 5"), + aRef.get<std::string>("name")); } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/uibase/uno/loktxdoc.cxx b/sw/source/uibase/uno/loktxdoc.cxx index ffcd967a6496..7f8898309ded 100644 --- a/sw/source/uibase/uno/loktxdoc.cxx +++ b/sw/source/uibase/uno/loktxdoc.cxx @@ -35,6 +35,9 @@ #include <doc.hxx> #include <docsh.hxx> #include <fmtrfmrk.hxx> +#include <wrtsh.hxx> +#include <txtrfmrk.hxx> +#include <ndtxt.hxx> using namespace ::com::sun::star; @@ -206,9 +209,25 @@ void GetFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, SwDoc* pDoc = pDocShell->GetDoc(); tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("setRefs"); + std::vector<const SwFormatRefMark*> aRefMarks; for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i) { - const SwFormatRefMark* pRefMark = pDoc->GetRefMark(i); + aRefMarks.push_back(pDoc->GetRefMark(i)); + } + // Sort the refmarks based on their start position. + std::sort(aRefMarks.begin(), aRefMarks.end(), + [](const SwFormatRefMark* pMark1, const SwFormatRefMark* pMark2) -> bool { + const SwTextRefMark* pTextRefMark1 = pMark1->GetTextRefMark(); + const SwTextRefMark* pTextRefMark2 = pMark2->GetTextRefMark(); + SwPosition aPos1(const_cast<SwTextNode&>(pTextRefMark1->GetTextNode()), + pTextRefMark1->GetStart()); + SwPosition aPos2(const_cast<SwTextNode&>(pTextRefMark2->GetTextNode()), + pTextRefMark2->GetStart()); + return aPos1 < aPos2; + }); + + for (const auto& pRefMark : aRefMarks) + { if (!pRefMark->GetRefName().startsWith(aNamePrefix)) { continue;
