desktop/source/lib/init.cxx       |   44 ++++-------------------
 include/vcl/ITiledRenderable.hxx  |    3 +
 sw/inc/unotxdoc.hxx               |    3 +
 sw/qa/uibase/uno/uno.cxx          |   37 ++++++++++++++++++++
 sw/source/uibase/uno/loktxdoc.cxx |   70 +++++++++++++++++++++++++++++++++++++-
 5 files changed, 120 insertions(+), 37 deletions(-)

New commits:
commit 707b8dc3c034e798513faf3ede22e71438b8d0f5
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Jan 5 08:13:21 2023 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Jan 9 12:54:27 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.
    
    (cherry picked from commit bb20dee2ef1b0804065e1cda2c834d257fdd90ed)
    
    Conflicts:
            sw/source/uibase/uno/loktxdoc.cxx
    
    Change-Id: I7f1a7064307034a18527ab5e985d2eac56807cb7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145082
    Tested-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index edaf0ad75477..c4aa15270fa3 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -5727,12 +5727,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"))
     {
@@ -5776,13 +5777,6 @@ static char* 
doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
     }
     else if (aCommand.startsWith(aViewRowColumnHeaders))
     {
-        ITiledRenderable* pDoc = getTiledRenderable(pThis);
-        if (!pDoc)
-        {
-            SetLastExceptionMsg("Document doesn't support tiled rendering");
-            return nullptr;
-        }
-
         tools::Rectangle aRectangle;
         if (aCommand.getLength() > aViewRowColumnHeaders.getLength())
         {
@@ -5828,13 +5822,6 @@ static char* 
doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
     }
     else if (aCommand.startsWith(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;
@@ -5894,12 +5881,6 @@ static char* 
doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
     }
     else if (aCommand.startsWith(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);
@@ -5909,17 +5890,8 @@ static char* 
doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
     {
         return getFontSubset(std::string_view(pCommand + 
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 3ce1b9042908..d0ce32d2753f 100644
--- a/include/vcl/ITiledRenderable.hxx
+++ b/include/vcl/ITiledRenderable.hxx
@@ -370,6 +370,9 @@ public:
      */
     virtual void setPaintTextEdit(bool) {}
 
+    /// Decides if it's OK to call getCommandValues(rCommand).
+    virtual bool supportsCommandValues(const OUString& /*rCommand*/) { return 
false; }
+
     /// Returns a json mapping of the possible values for the given command.
     virtual void getCommandValues(tools::JsonWriter& /*rJsonWriter*/, const 
OString& /*rCommand*/)
     {
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index fabab635edda..07c3f5b6e6e0 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -461,6 +461,9 @@ public:
     /// @see vcl::ITiledRenderable::getCommandValues().
     void getCommandValues(tools::JsonWriter& rJsonWriter, const OString& 
rCommand) override;
 
+    /// @see vcl::ITiledRenderable::supportsCommandValues().
+    bool supportsCommandValues(const OUString& 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 02bacf5b02f1..f24137e482a2 100644
--- a/sw/qa/uibase/uno/uno.cxx
+++ b/sw/qa/uibase/uno/uno.cxx
@@ -270,6 +270,43 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetFields)
                          aRef.get<std::string>("name"));
 }
 
+CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetTextFormField)
+{
+    // Given a document with a fieldmark:
+    SwDoc* pDoc = 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:
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->SttEndDoc(/*bStt=*/false);
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    tools::JsonWriter aJsonWriter;
+    OString 
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 7f8898309ded..c8e50206e55a 100644
--- a/sw/source/uibase/uno/loktxdoc.cxx
+++ b/sw/source/uibase/uno/loktxdoc.cxx
@@ -48,7 +48,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)
 {
@@ -99,6 +99,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:
@@ -239,11 +293,21 @@ void GetFields(tools::JsonWriter& rJsonWriter, 
SwDocShell* pDocShell,
 }
 }
 
+bool SwXTextDocument::supportsCommandValues(const OUString& 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, const 
OString& 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");
@@ -274,6 +338,10 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& 
rJsonWriter, const OSt
     {
         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