diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-11-29 16:18:16 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-11-30 08:13:28 +0100 |
commit | 5e8f6dcb8ce00d2d5e35b3cf5654187b3068276c (patch) | |
tree | 0d81eed04980c244163f064db63269f30dc077d3 /sw | |
parent | 1d9221ebc86f2696a65c12287ea19eea44d680cf (diff) |
sw lok, .uno:SetDocumentProperties: expose value of custom document properties
LOK API clients currently have no knowledge about document properties.
Clients like Zotero that want to store custom properties on documents
need a way to read and write such properties. This commit focuses on the
reading side.
Add a getter for .uno:SetDocumentProperties that allows filtering for a
certain prefix, this way the returned value can contain only the
relevant information.
Rework doc_getCommandValues() and SwXTextDocument::getCommandValues() a
bit, so adding new getters require less duplication.
Change-Id: I0c52cd2efcc8b1ea7307763c8252dd1e8ffdea2d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143468
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/qa/uibase/uno/uno.cxx | 37 | ||||
-rw-r--r-- | sw/source/uibase/uno/unotxdoc.cxx | 94 |
2 files changed, 107 insertions, 24 deletions
diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx index 02d95df370c4..8e6b06453d86 100644 --- a/sw/qa/uibase/uno/uno.cxx +++ b/sw/qa/uibase/uno/uno.cxx @@ -15,6 +15,7 @@ #include <com/sun/star/text/XTextViewTextRangeSupplier.hpp> #include <com/sun/star/util/XCloseable.hpp> #include <com/sun/star/text/XTextDocument.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> #include <vcl/scheduler.hxx> #include <tools/json_writer.hxx> @@ -195,12 +196,46 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetTextFormFields) std::stringstream aStream(pJSON.get()); boost::property_tree::ptree aTree; boost::property_tree::read_json(aStream, aTree); - // Without the needed PixelToLogic() call in place, this test would have failed with: + // Without the accompanying fix in place, this test would have failed with: // - No such node (fields) // i.e. the returned JSON was just empty. CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), aTree.get_child("fields").count("")); } +CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testGetDocumentProperties) +{ + // Given a document with 3 custom properties: 2 zotero ones and an other one: + createSwDoc(); + SwDoc* pDoc = getSwDoc(); + SwDocShell* pDocShell = pDoc->GetDocShell(); + uno::Reference<document::XDocumentPropertiesSupplier> xDPS(pDocShell->GetModel(), + uno::UNO_QUERY); + uno::Reference<document::XDocumentProperties> xDP = xDPS->getDocumentProperties(); + uno::Reference<beans::XPropertyContainer> xUDP = xDP->getUserDefinedProperties(); + xUDP->addProperty("ZOTERO_PREF_1", beans::PropertyAttribute::REMOVABLE, + uno::Any(OUString("foo"))); + xUDP->addProperty("ZOTERO_PREF_2", beans::PropertyAttribute::REMOVABLE, + uno::Any(OUString("bar"))); + xUDP->addProperty("OTHER", beans::PropertyAttribute::REMOVABLE, uno::Any(OUString("baz"))); + + // When getting the zotero properties: + tools::JsonWriter aJsonWriter; + std::string_view aCommand(".uno:SetDocumentProperties?namePrefix=ZOTERO_PREF_"); + auto pXTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + pXTextDocument->getCommandValues(aJsonWriter, aCommand); + + // Then make sure we find the 2 properties and ignore the other one: + 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 (userDefinedProperties) + // i.e. the returned JSON was just empty. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), + aTree.get_child("userDefinedProperties").count("")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx index 3405a1631727..8d8a7ca0f882 100644 --- a/sw/source/uibase/uno/unotxdoc.cxx +++ b/sw/source/uibase/uno/unotxdoc.cxx @@ -84,6 +84,7 @@ #include <com/sun/star/lang/NoSupportException.hpp> #include <com/sun/star/beans/PropertyAttribute.hpp> #include <com/sun/star/beans/XFastPropertySet.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> #include <com/sun/star/document/RedlineDisplayType.hpp> #include <com/sun/star/document/XDocumentEventBroadcaster.hpp> #include <com/sun/star/frame/XController.hpp> @@ -163,6 +164,7 @@ #include <svx/svdpage.hxx> #include <o3tl/string_view.hxx> +#include <comphelper/sequenceashashmap.hxx> #include <IDocumentOutlineNodes.hxx> #include <SearchResultLocator.hxx> @@ -3568,6 +3570,48 @@ void GetTextFormFields(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, rJsonWriter.put("command", aCommand); } } + +/// Implements getCommandValues(".uno:SetDocumentProperties"). +/// +/// Parameters: +/// +/// - namePrefix: field name prefix not not return all user-defined properties +void GetDocumentProperties(tools::JsonWriter& rJsonWriter, SwDocShell* pDocShell, + const std::map<OUString, OUString>& rArguments) +{ + OUString aNamePrefix; + auto it = rArguments.find("namePrefix"); + if (it != rArguments.end()) + { + aNamePrefix = it->second; + } + + uno::Reference<document::XDocumentPropertiesSupplier> xDPS(pDocShell->GetModel(), uno::UNO_QUERY); + uno::Reference<document::XDocumentProperties> xDP = xDPS->getDocumentProperties(); + uno::Reference<beans::XPropertyAccess> xUDP(xDP->getUserDefinedProperties(), uno::UNO_QUERY); + auto aUDPs = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(xUDP->getPropertyValues()); + tools::ScopedJsonWriterArray aProperties = rJsonWriter.startArray("userDefinedProperties"); + for (const auto& rUDP : aUDPs) + { + if (!rUDP.Name.startsWith(aNamePrefix)) + { + continue; + } + + if (rUDP.Value.getValueTypeClass() != TypeClass_STRING) + { + continue; + } + + OUString aValue; + rUDP.Value >>= aValue; + + tools::ScopedJsonWriterStruct aProperty = rJsonWriter.startStruct(); + rJsonWriter.put("name", rUDP.Name); + rJsonWriter.put("type", "string"); + rJsonWriter.put("value", aValue); + } +} } void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand) @@ -3575,34 +3619,38 @@ void SwXTextDocument::getCommandValues(tools::JsonWriter& rJsonWriter, std::stri std::map<OUString, OUString> aMap; static constexpr OStringLiteral aTextFormFields(".uno:TextFormFields"); + static constexpr OStringLiteral aSetDocumentProperties(".uno:SetDocumentProperties"); + + INetURLObject aParser(OUString::fromUtf8(rCommand)); + OUString aArguments = aParser.GetParam(); + sal_Int32 nParamIndex = 0; + do + { + std::u16string_view aParam = o3tl::getToken(aArguments, 0, '&', nParamIndex); + sal_Int32 nIndex = 0; + OUString aKey; + OUString aValue; + do + { + std::u16string_view aToken = o3tl::getToken(aParam, 0, '=', nIndex); + if (aKey.isEmpty()) + aKey = aToken; + else + aValue = aToken; + } while (nIndex >= 0); + OUString aDecodedValue + = INetURLObject::decode(aValue, INetURLObject::DecodeMechanism::WithCharset); + aMap[aKey] = aDecodedValue; + } while (nParamIndex >= 0); if (o3tl::starts_with(rCommand, aTextFormFields)) { - if (rCommand.size() > o3tl::make_unsigned(aTextFormFields.getLength())) - { - std::string_view aArguments = rCommand.substr(aTextFormFields.getLength() + 1); - sal_Int32 nParamIndex = 0; - do - { - std::string_view aParamToken = o3tl::getToken(aArguments, 0, '&', nParamIndex); - sal_Int32 nIndex = 0; - OUString aKey; - OUString aValue; - do - { - std::string_view aToken = o3tl::getToken(aParamToken, 0, '=', nIndex); - if (aKey.isEmpty()) - aKey = OUString::fromUtf8(aToken); - else - aValue = OUString::fromUtf8(aToken); - } while (nIndex >= 0); - OUString aDecodedValue - = INetURLObject::decode(aValue, INetURLObject::DecodeMechanism::WithCharset); - aMap[aKey] = aDecodedValue; - } while (nParamIndex >= 0); - } GetTextFormFields(rJsonWriter, m_pDocShell, aMap); } + if (o3tl::starts_with(rCommand, aSetDocumentProperties)) + { + GetDocumentProperties(rJsonWriter, m_pDocShell, aMap); + } } int SwXTextDocument::getPart() |