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 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(1), aTree.get_child("setRefs").count("")); } +CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetTextFormField) +{ + // Given a document with a fieldmark: + createSwDoc(); + uno::Sequence 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(mxComponent.get()); + pXTextDocument->getCommandValues(aJsonWriter, aCommand); + + // Then make sure we find the inserted fieldmark: + 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 (type) + // i.e. the returned JSON was just an empty object. + CPPUNIT_ASSERT_EQUAL(std::string("vnd.oasis.opendocument.field.UNHANDLED"), + aTree.get("type")); + CPPUNIT_ASSERT_EQUAL(std::string("ADDIN ZOTERO_ITEM foo bar"), + aTree.get("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 #include #include +#include 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& 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& 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 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 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);