From 3585d0414ffe08890856e5c09f453b9f566323df Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 3 Jan 2023 11:28:04 +0100 Subject: sw, lok: implement a getCommandValues(Fields) There was no LOK API to get a list of all fields of a given type where the name matches a certain prefix. This is useful in case the API cilent wants to know what previously inserted refmarks were deleted by the user as part of deleting text content. Add a new getCommandValues(".uno:Fields") that returns the names of matching refmarks. Do not return the refmark text, assuming that would be updated by the API client anyway. In practice this is needed by Zotero in case it wants to model its citations with refmarks. Change-Id: Ie469253891896aa8ab00d434c9ab116adbe3864b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144985 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- desktop/source/lib/init.cxx | 3 ++- sw/qa/uibase/uno/uno.cxx | 29 +++++++++++++++++++++ sw/source/uibase/uno/loktxdoc.cxx | 53 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index f805f4a73322..6cb0c9493516 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -5717,7 +5717,8 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo static const std::initializer_list vForward = { u"TextFormFields", u"SetDocumentProperties", - u"Bookmarks" + u"Bookmarks", + u"Fields" }; if (!strcmp(pCommand, ".uno:LanguageStatus")) diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx index 64d2a70fe4e2..12f6124ec1f8 100644 --- a/sw/qa/uibase/uno/uno.cxx +++ b/sw/qa/uibase/uno/uno.cxx @@ -318,6 +318,35 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetBookmarks) CPPUNIT_ASSERT_EQUAL(static_cast(2), aTree.get_child("bookmarks").count("")); } +CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields) +{ + // Given a document with a refmark: + createSwDoc(); + uno::Sequence 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); + + // When getting the refmarks: + tools::JsonWriter aJsonWriter; + std::string_view aCommand(".uno:Fields?typeName=SetRef&namePrefix=ZOTERO_ITEM%20CSL_CITATION"); + auto pXTextDocument = dynamic_cast(mxComponent.get()); + pXTextDocument->getCommandValues(aJsonWriter, aCommand); + + // Then make sure we get the 1 refmark: + std::unique_ptr pJSON(aJsonWriter.extractData()); + std::stringstream aStream(pJSON.get()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + // 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(1), aTree.get_child("setRefs").count("")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/loktxdoc.cxx b/sw/source/uibase/uno/loktxdoc.cxx index 5381fd5c1dfe..d82fc8388775 100644 --- a/sw/source/uibase/uno/loktxdoc.cxx +++ b/sw/source/uibase/uno/loktxdoc.cxx @@ -34,6 +34,7 @@ #include #include #include +#include using namespace ::com::sun::star; @@ -170,6 +171,53 @@ void GetBookmarks(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, rJsonWriter.put("name", pMark->GetName()); } } + +/// Implements getCommandValues(".uno:Fields"). +/// +/// Parameters: +/// +/// - typeName: field type condition to not return all fields +/// - namePrefix: field name prefix to not return all fields +void GetFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map& rArguments) +{ + OUString aTypeName; + { + auto it = rArguments.find("typeName"); + if (it != rArguments.end()) + { + aTypeName = it->second; + } + } + // See SwFieldTypeFromString(). + if (aTypeName != "SetRef") + { + return; + } + + OUString aNamePrefix; + { + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + } + + SwDoc* pDoc = pDocShell->GetDoc(); + tools::ScopedJsonWriterArray aBookmarks = rJsonWriter.startArray("setRefs"); + for (sal_uInt16 i = 0; i < pDoc->GetRefMarks(); ++i) + { + const SwFormatRefMark* pRefMark = pDoc->GetRefMark(i); + if (!pRefMark->GetRefName().startsWith(aNamePrefix)) + { + continue; + } + + tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct(); + rJsonWriter.put("name", pRefMark->GetRefName()); + } +} } void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand) @@ -179,6 +227,7 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::stri static constexpr OStringLiteral aTextFormFields(".uno:TextFormFields"); static constexpr OStringLiteral aSetDocumentProperties(".uno:SetDocumentProperties"); static constexpr OStringLiteral aBookmarks(".uno:Bookmarks"); + static constexpr OStringLiteral aFields(".uno:Fields"); INetURLObject aParser(OUString::fromUtf8(rCommand)); OUString aArguments = aParser.GetParam(); @@ -214,6 +263,10 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::stri { GetBookmarks(rJsonWriter, m_pDocShell, aMap); } + else if (o3tl::starts_with(rCommand, aFields)) + { + GetFields(rJsonWriter, m_pDocShell, aMap); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit