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);

Reply via email to