comphelper/source/misc/sequenceashashmap.cxx           |    3 -
 include/comphelper/JsonToPropertyValues_with_boost.hxx |   28 +++++++++++
 include/sfx2/lokhelper.hxx                             |    4 +
 sd/qa/unit/uiimpress.cxx                               |   40 +++++++++++++++++
 sd/source/ui/view/drviews2.cxx                         |    4 +
 sfx2/source/view/lokhelper.cxx                         |   28 +++++++++++
 sw/qa/uibase/shells/shells.cxx                         |   39 ++++++++++++++++
 sw/source/uibase/shells/textsh1.cxx                    |    4 +
 8 files changed, 149 insertions(+), 1 deletion(-)

New commits:
commit 36df1925cd7a5c4c0da9fa10f965c492604b2a2e
Author:     Mike Kaganski <[email protected]>
AuthorDate: Mon Oct 6 18:10:53 2025 +0500
Commit:     Andras Timar <[email protected]>
CommitDate: Wed Oct 22 12:03:31 2025 +0200

    LOK Transform API: add unit tests for generic UnoCommand command
    
    Change-Id: I7cfbc1ff08cbd0e4089f9e4b9579ab22ec05d85d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192276
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>
    (cherry picked from commit ae465d8f4d291d0aa3d88881b90ada481d62586c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192825
    Reviewed-by: Andras Timar <[email protected]>
    Tested-by: Andras Timar <[email protected]>

diff --git a/sd/qa/unit/uiimpress.cxx b/sd/qa/unit/uiimpress.cxx
index edfaaaca6695..64d38fe23a2a 100644
--- a/sd/qa/unit/uiimpress.cxx
+++ b/sd/qa/unit/uiimpress.cxx
@@ -12,6 +12,7 @@
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/uno/Reference.hxx>
 #include <com/sun/star/drawing/FillStyle.hpp>
 #include <com/sun/star/drawing/XDrawView.hpp>
@@ -60,6 +61,7 @@
 #include <slideshow.hxx>
 #include <sdresid.hxx>
 #include <strings.hrc>
+#include <unopage.hxx>
 
 using namespace ::com::sun::star;
 
@@ -275,6 +277,44 @@ CPPUNIT_TEST_FIXTURE(SdUiImpressTest, 
testDocumentStructureTransformExtractSlide
     CPPUNIT_ASSERT_EQUAL(aExpectedStr, aJsonWriter.finishAndGetAsOString());
 }
 
+CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testDocumentStructureUnoCommand)
+{
+    // 1. Create a document;
+    // 2. Check that its first slide has two objects (the default title + 
content placeholders);
+    // 3. Perform a "TransformDocumentStructure" with a "UnoCommand" calling 
".uno:SelectAll" and
+    //    ".uno:Cut";
+    // 4. Check that the first slide has no objects now.
+
+    createSdImpressDoc();
+
+    // Let comphelper::dispatchCommand (in SfxLokHelper::dispatchUnoCommand) 
find the frame
+    auto xDesktop = 
frame::Desktop::create(comphelper::getProcessComponentContext());
+    auto pImpressDocument = 
static_cast<SdXImpressDocument*>(mxComponent.get());
+    auto pFrame = pImpressDocument->GetDocShell()->GetFrame();
+    CPPUNIT_ASSERT(pFrame);
+    xDesktop->setActiveFrame(pFrame->GetFrame().GetFrameInterface());
+
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
+                         
pImpressDocument->getSdDrawPages()->getDrawPageByIndex(0)->getCount());
+
+    static constexpr OUString aJson = uR"json(
+{
+    "UnoCommand": {
+        "name": ".uno:SelectAll"
+    },
+    "UnoCommand": {
+        "name": ".uno:Cut"
+    }
+}
+)json"_ustr;
+
+    dispatchCommand(mxComponent, u".uno:TransformDocumentStructure"_ustr,
+                    { comphelper::makePropertyValue(u"DataJson"_ustr, aJson) 
});
+
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
+                         
pImpressDocument->getSdDrawPages()->getDrawPageByIndex(0)->getCount());
+}
+
 CPPUNIT_TEST_FIXTURE(SdUiImpressTest, testTdf111522)
 {
     // Load the document and create two new windows.
diff --git a/sw/qa/uibase/shells/shells.cxx b/sw/qa/uibase/shells/shells.cxx
index 165eb7589379..a53c39663351 100644
--- a/sw/qa/uibase/shells/shells.cxx
+++ b/sw/qa/uibase/shells/shells.cxx
@@ -9,6 +9,7 @@
 
 #include <swmodeltestbase.hxx>
 
+#include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
 #include <com/sun/star/text/BibliographyDataType.hpp>
@@ -34,6 +35,7 @@
 #include <osl/thread.hxx>
 
 #include <IDocumentContentOperations.hxx>
+#include <IDocumentRedlineAccess.hxx>
 #include <cmdid.h>
 #include <fmtanchr.hxx>
 #include <view.hxx>
@@ -1123,6 +1125,43 @@ CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, 
testDocumentStructureExtractRedlines_te
     CPPUNIT_ASSERT(bool(it == docStructure.end()));
 }
 
+CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testDocumentStructureUnoCommand)
+{
+    // 1. Create a document;
+    // 2. Check that it's not in change tracking mode;
+    // 3. Perform a "TransformDocumentStructure" with a "UnoCommand" of 
".uno:TrackChanges";
+    // 4. Check that it's in change tracking mode now.
+
+    createSwDoc();
+
+    // Let comphelper::dispatchCommand (in SfxLokHelper::dispatchUnoCommand) 
find the frame
+    auto xDesktop = 
frame::Desktop::create(comphelper::getProcessComponentContext());
+    auto pFrame = getSwDocShell()->GetFrame();
+    CPPUNIT_ASSERT(pFrame);
+    xDesktop->setActiveFrame(pFrame->GetFrame().GetFrameInterface());
+
+    CPPUNIT_ASSERT(!getSwDoc()->getIDocumentRedlineAccess().IsRedlineOn());
+
+    static constexpr OUString aJson = uR"json(
+{
+    "UnoCommand": {
+        "name": ".uno:TrackChanges",
+        "arguments": {
+            "TrackChanges": {
+                "type": "boolean",
+                "value": "true"
+            }
+        }
+    }
+}
+)json"_ustr;
+
+    dispatchCommand(mxComponent, u".uno:TransformDocumentStructure"_ustr,
+                    { comphelper::makePropertyValue(u"DataJson"_ustr, aJson) 
});
+
+    CPPUNIT_ASSERT(getSwDoc()->getIDocumentRedlineAccess().IsRedlineOn());
+}
+
 CPPUNIT_TEST_FIXTURE(SwUibaseShellsTest, testUpdateRefmarks)
 {
     // Given a document with two refmarks, one is not interesting the other is 
a citation:
commit 54ccc2100b8fabbfbf9d8ae9a2dfe9bfc94326e8
Author:     Mike Kaganski <[email protected]>
AuthorDate: Mon Oct 6 18:10:53 2025 +0500
Commit:     Andras Timar <[email protected]>
CommitDate: Wed Oct 22 12:03:21 2025 +0200

    LOK Transform API: add generic UnoCommand command
    
    There already was UnoCommand support inside SlideCommands. This change
    introduces it at top level.
    
    The syntax of the command is:
    
    {"UnoCommand": {
        "name": ".uno:Foo",
        "arguments": {
            "Arg1": {
                "type": "long",
                "value": 0
            },
            "Arg2": {
                "type": "long",
                "value": 1
            }
        }
    }}
    
    Change-Id: I0015e937495ad1ae756c5366b555a3b0d5fb09ef
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192001
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>
    (cherry picked from commit 2f157a9eac2fab72af4b8019c9d10b4f3be1aa50)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192824
    Tested-by: Andras Timar <[email protected]>
    Reviewed-by: Andras Timar <[email protected]>

diff --git a/comphelper/source/misc/sequenceashashmap.cxx 
b/comphelper/source/misc/sequenceashashmap.cxx
index 46a23db43ba9..7c3c99016912 100644
--- a/comphelper/source/misc/sequenceashashmap.cxx
+++ b/comphelper/source/misc/sequenceashashmap.cxx
@@ -26,6 +26,7 @@
 #include <com/sun/star/lang/IllegalArgumentException.hpp>
 #include <com/sun/star/reflection/XIdlField.hpp>
 #include <com/sun/star/reflection/theCoreReflection.hpp>
+#include <comphelper/JsonToPropertyValues_with_boost.hxx>
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/propertysequence.hxx>
@@ -302,7 +303,7 @@ void SequenceAsHashMap::update(const SequenceAsHashMap& 
rUpdate)
     }
 }
 
-static std::vector<css::beans::PropertyValue> JsonToPropertyValues(const 
boost::property_tree::ptree& aTree)
+std::vector<css::beans::PropertyValue> JsonToPropertyValues(const 
boost::property_tree::ptree& aTree)
 {
     std::vector<beans::PropertyValue> aArguments;
     boost::property_tree::ptree aNodeNull, aNodeValue;
diff --git a/include/comphelper/JsonToPropertyValues_with_boost.hxx 
b/include/comphelper/JsonToPropertyValues_with_boost.hxx
new file mode 100644
index 000000000000..2c67cc8f3a77
--- /dev/null
+++ b/include/comphelper/JsonToPropertyValues_with_boost.hxx
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <vector>
+
+#include <boost/property_tree/ptree_fwd.hpp>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <comphelper/comphelperdllapi.h>
+
+namespace comphelper
+{
+COMPHELPER_DLLPUBLIC std::vector<css::beans::PropertyValue>
+JsonToPropertyValues(const boost::property_tree::ptree& rJson);
+} // namespace comphelper
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index 099c45025328..ab8dc309afa1 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -30,6 +30,8 @@
 #include <string_view>
 #include <unordered_map>
 
+#include <boost/property_tree/ptree_fwd.hpp>
+
 #define LOK_NOTIFY_LOG_TO_CLIENT 1
 
 #define LOK_LOG_STREAM(level, area, stream) \
@@ -270,6 +272,8 @@ public:
     /// Registers function pointers in comphelper/ to set/get of the current 
LOK view.
     static void registerViewCallbacks();
 
+    static void dispatchUnoCommand(const boost::property_tree::ptree& tree);
+
 private:
     static int createView(SfxViewFrame& rViewFrame, ViewShellDocId docId);
 };
diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx
index 1c64ad96806b..b2affde7eafe 100644
--- a/sd/source/ui/view/drviews2.cxx
+++ b/sd/source/ui/view/drviews2.cxx
@@ -1372,6 +1372,10 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq)
                         }
                     }
                 }
+                else if (aItem.first == "UnoCommand")
+                {
+                    SfxLokHelper::dispatchUnoCommand(aItem.second);
+                }
             }
             rReq.Done();
         }
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index f554ae32daad..4512b0ad4a57 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -16,13 +16,18 @@
 
 #include <sfx2/lokcomponenthelpers.hxx>
 #include <sfx2/lokhelper.hxx>
+#include <sfx2/lokunocmdlist.hxx>
 
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/ui/ContextChangeEventObject.hpp>
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
 #include <com/sun/star/xml/crypto/XCertificateCreator.hpp>
 
+#include <comphelper/dispatchcommand.hxx>
+#include <comphelper/JsonToPropertyValues_with_boost.hxx>
 #include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
 #include <o3tl/string_view.hxx>
 #include <rtl/strbuf.hxx>
 #include <vcl/lok.hxx>
@@ -1190,6 +1195,29 @@ void SfxLokHelper::registerViewCallbacks()
     });
 }
 
+void SfxLokHelper::dispatchUnoCommand(const boost::property_tree::ptree& tree)
+{
+    auto command = 
OStringToOUString(tree.get_child("name").get_value<std::string>(),
+                                     RTL_TEXTENCODING_UTF8);
+    // Check if the uno command is allowed
+    if (std::u16string_view rest;
+        !command.startsWith(".uno:", &rest) || 
!GetKitUnoCommandList().contains(rest))
+    {
+        LOK_WARN("lok.transform",
+                 "UnoCommand command is not recognized: '" << command << "'");
+        return;
+    }
+    std::vector<beans::PropertyValue> arguments;
+    if (auto args = tree.get_child_optional("arguments"))
+    {
+        arguments = comphelper::JsonToPropertyValues(*args);
+    }
+    // Make the uno command synchron
+    arguments.push_back(comphelper::makePropertyValue(u"SynchronMode"_ustr, 
true));
+
+    comphelper::dispatchCommand(command, 
comphelper::containerToSequence(arguments));
+}
+
 namespace
 {
     struct LOKAsyncEventData
diff --git a/sw/source/uibase/shells/textsh1.cxx 
b/sw/source/uibase/shells/textsh1.cxx
index d79da729e054..32d6127576ea 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -3552,6 +3552,10 @@ void SwTextShell::Execute(SfxRequest &rReq)
                         }
                     }
                 }
+                else if (aItem.first == "UnoCommand")
+                {
+                    SfxLokHelper::dispatchUnoCommand(aItem.second);
+                }
             }
         }
         break;

Reply via email to