desktop/source/lib/init.cxx | 44 ++++------------------- include/vcl/ITiledRenderable.hxx | 3 + sw/inc/unotxdoc.hxx | 3 + sw/qa/uibase/uno/uno.cxx | 38 ++++++++++++++++++++ sw/source/uibase/uno/loktxdoc.cxx | 71 +++++++++++++++++++++++++++++++++++++- 5 files changed, 122 insertions(+), 37 deletions(-)
New commits: commit bb20dee2ef1b0804065e1cda2c834d257fdd90ed Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Jan 5 08:13:21 2023 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Jan 5 08:33:16 2023 +0000 sw lok: expose field type & command of fieldmark under cursor It was possible to get the properties of all fieldmarks, but you could not get the properties of the fieldmark under the current cursor. Getting the properties of the current fieldmark is useful for Zotero: if we already have a citation and want to insert one more, then we should turn the current citation into a citation cluster. Fix the problem by adding API similar to what commit 24219cc1e9829f82a533667aef0f51b6a7df6fc2 (sw lok, .uno:TextFormFields: expose field code of fieldmarks, 2022-11-25), did: but here we return properties of the innermost fieldmark, not all fieldmarks. Also introduce a ITiledRenderable::supportsCommandValues(), this way next time a command value getter is added in sw/sc/sd, no need to touch desktop/ anymore. Change-Id: I7f1a7064307034a18527ab5e985d2eac56807cb7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145062 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 6cb0c9493516..8d191f7741da 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -5714,12 +5714,13 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo static constexpr OStringLiteral aSheetGeometryData(".uno:SheetGeometryData"); static constexpr OStringLiteral aCellCursor(".uno:CellCursor"); static constexpr OStringLiteral aFontSubset(".uno:FontSubset&name="); - static const std::initializer_list<std::u16string_view> vForward = { - u"TextFormFields", - u"SetDocumentProperties", - u"Bookmarks", - u"Fields" - }; + + ITiledRenderable* pDoc = getTiledRenderable(pThis); + if (!pDoc) + { + SetLastExceptionMsg("Document doesn't support tiled rendering"); + return nullptr; + } if (!strcmp(pCommand, ".uno:LanguageStatus")) { @@ -5763,13 +5764,6 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo } else if (o3tl::starts_with(aCommand, aViewRowColumnHeaders)) { - ITiledRenderable* pDoc = getTiledRenderable(pThis); - if (!pDoc) - { - SetLastExceptionMsg("Document doesn't support tiled rendering"); - return nullptr; - } - tools::Rectangle aRectangle; if (aCommand.size() > o3tl::make_unsigned(aViewRowColumnHeaders.getLength())) { @@ -5815,13 +5809,6 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo } else if (o3tl::starts_with(aCommand, aSheetGeometryData)) { - ITiledRenderable* pDoc = getTiledRenderable(pThis); - if (!pDoc) - { - SetLastExceptionMsg("Document doesn't support tiled rendering"); - return nullptr; - } - bool bColumns = true; bool bRows = true; bool bSizes = true; @@ -5881,12 +5868,6 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo } else if (o3tl::starts_with(aCommand, aCellCursor)) { - ITiledRenderable* pDoc = getTiledRenderable(pThis); - if (!pDoc) - { - SetLastExceptionMsg("Document doesn't support tiled rendering"); - return nullptr; - } // Ignore command's deprecated parameters. tools::JsonWriter aJsonWriter; pDoc->getCellCursor(aJsonWriter); @@ -5896,17 +5877,8 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo { return getFontSubset(aCommand.substr(aFontSubset.getLength())); } - else if (std::find(vForward.begin(), vForward.end(), - INetURLObject(OUString::fromUtf8(aCommand)).GetURLPath()) - != vForward.end()) + else if (pDoc->supportsCommandValues(INetURLObject(OUString::fromUtf8(aCommand)).GetURLPath())) { - ITiledRenderable* pDoc = getTiledRenderable(pThis); - if (!pDoc) - { - SetLastExceptionMsg("Document doesn't support tiled rendering"); - return nullptr; - } - tools::JsonWriter aJsonWriter; pDoc->getCommandValues(aJsonWriter, aCommand); return aJsonWriter.extractData(); diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx index 10d0ea87752c..7d3f4b7aaf33 100644 --- a/include/vcl/ITiledRenderable.hxx +++ b/include/vcl/ITiledRenderable.hxx @@ -369,6 +369,9 @@ public: */ virtual void setPaintTextEdit(bool) {} + /// Decides if it's OK to call getCommandValues(rCommand). + virtual bool supportsCommandValues(std::u16string_view /*rCommand*/) { return false; } + /// Returns a json mapping of the possible values for the given command. virtual void getCommandValues(tools::JsonWriter& /*rJsonWriter*/, std::string_view /*rCommand*/) { diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx index 150ea15af498..a7bbcb776f44 100644 --- a/sw/inc/unotxdoc.hxx +++ b/sw/inc/unotxdoc.hxx @@ -462,6 +462,9 @@ public: /// @see vcl::ITiledRenderable::getCommandValues(). void getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand) override; + /// @see vcl::ITiledRenderable::supportsCommandValues(). + bool supportsCommandValues(std::u16string_view rCommand) override; + void Invalidate(); void Reactivate(SwDocShell* pNewDocShell); SwXDocumentPropertyHelper * GetPropertyHelper (); diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx index 12f6124ec1f8..f15e2b654463 100644 --- a/sw/qa/uibase/uno/uno.cxx +++ b/sw/qa/uibase/uno/uno.cxx @@ -347,6 +347,44 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields) CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aTree.get_child("setRefs").count("")); } +CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetTextFormField) +{ + // Given a document with a fieldmark: + createSwDoc(); + uno::Sequence<css::beans::PropertyValue> aArgs = { + comphelper::makePropertyValue("FieldType", uno::Any(OUString(ODF_UNHANDLED))), + comphelper::makePropertyValue("FieldCommand", + uno::Any(OUString("ADDIN ZOTERO_ITEM foo bar"))), + comphelper::makePropertyValue("FieldResult", uno::Any(OUString("result"))), + }; + dispatchCommand(mxComponent, ".uno:TextFormField", aArgs); + + // When stepping into the fieldmark with the cursor and getting the command value for + // uno:TextFormField: + SwDoc* pDoc = getSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->SttEndDoc(/*bStt=*/false); + pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false); + tools::JsonWriter aJsonWriter; + std::string_view aCommand(".uno:TextFormField?type=vnd.oasis.opendocument.field.UNHANDLED&" + "commandPrefix=ADDIN%20ZOTERO_ITEM"); + auto pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + pXTextDocument->getCommandValues(aJsonWriter, aCommand); + + // Then make sure we find the inserted fieldmark: + std::unique_ptr<char[], o3tl::free_delete> 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 (type) + // i.e. the returned JSON was just an empty object. + CPPUNIT_ASSERT_EQUAL(std::string("vnd.oasis.opendocument.field.UNHANDLED"), + aTree.get<std::string>("type")); + CPPUNIT_ASSERT_EQUAL(std::string("ADDIN ZOTERO_ITEM foo bar"), + aTree.get<std::string>("command")); +} + 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 d82fc8388775..f0372b37438b 100644 --- a/sw/source/uibase/uno/loktxdoc.cxx +++ b/sw/source/uibase/uno/loktxdoc.cxx @@ -35,6 +35,7 @@ #include <doc.hxx> #include <docsh.hxx> #include <fmtrfmrk.hxx> +#include <wrtsh.hxx> using namespace ::com::sun::star; @@ -45,7 +46,7 @@ namespace /// Parameters: /// /// - type: e.g. ODF_UNHANDLED -/// - commandPrefix: field comment prefix not not return all fieldmarks +/// - commandPrefix: field command prefix to not return all fieldmarks void GetTextFormFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, const std::map<OUString, OUString>& rArguments) { @@ -96,6 +97,60 @@ void GetTextFormFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, } } +/// Implements getCommandValues(".uno:TextFormField"). +/// +/// Parameters: +/// +/// - type: e.g. ODF_UNHANDLED +/// - commandPrefix: field command prefix to not return all fieldmarks +void GetTextFormField(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aType; + OUString aCommandPrefix; + auto it = rArguments.find("type"); + if (it != rArguments.end()) + { + aType = it->second; + } + + it = rArguments.find("commandPrefix"); + if (it != rArguments.end()) + { + aCommandPrefix = it->second; + } + + IDocumentMarkAccess& rIDMA = *pDocShell->GetDoc()->getIDocumentMarkAccess(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwPosition& rCursor = *pWrtShell->GetCursor()->GetPoint(); + sw::mark::IFieldmark* pFieldmark = rIDMA.getFieldmarkFor(rCursor); + if (!pFieldmark) + { + return; + } + + if (pFieldmark->GetFieldname() != aType) + { + return; + } + + auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM); + if (itParam == pFieldmark->GetParameters()->end()) + { + return; + } + + OUString aCommand; + itParam->second >>= aCommand; + if (!aCommand.startsWith(aCommandPrefix)) + { + return; + } + + rJsonWriter.put("type", aType); + rJsonWriter.put("command", aCommand); +} + /// Implements getCommandValues(".uno:SetDocumentProperties"). /// /// Parameters: @@ -220,11 +275,21 @@ void GetFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, } } +bool SwXTextDocument::supportsCommandValues(std::u16string_view rCommand) +{ + static const std::initializer_list<std::u16string_view> vForward + = { u"TextFormFields", u"TextFormField", u"SetDocumentProperties", u"Bookmarks", + u"Fields" }; + + return std::find(vForward.begin(), vForward.end(), rCommand) != vForward.end(); +} + void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand) { std::map<OUString, OUString> aMap; static constexpr OStringLiteral aTextFormFields(".uno:TextFormFields"); + static constexpr OStringLiteral aTextFormField(".uno:TextFormField"); static constexpr OStringLiteral aSetDocumentProperties(".uno:SetDocumentProperties"); static constexpr OStringLiteral aBookmarks(".uno:Bookmarks"); static constexpr OStringLiteral aFields(".uno:Fields"); @@ -255,6 +320,10 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::stri { GetTextFormFields(rJsonWriter, m_pDocShell, aMap); } + if (o3tl::starts_with(rCommand, aTextFormField)) + { + GetTextFormField(rJsonWriter, m_pDocShell, aMap); + } else if (o3tl::starts_with(rCommand, aSetDocumentProperties)) { GetDocumentProperties(rJsonWriter, m_pDocShell, aMap);