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;
