diff --git a/configmgr/source/access.cxx b/configmgr/source/access.cxx index 668192fee63c..f2b0931b0beb 100644 --- a/configmgr/source/access.cxx +++ b/configmgr/source/access.cxx @@ -216,6 +216,8 @@ css::uno::Sequence< css::uno::Type > Access::getTypes() } else { types.push_back( cppu::UnoType< css::container::XHierarchicalNameAccess >::get()); + types.push_back( + cppu::UnoType< css::configuration::XDocumentation >::get()); } addTypes(&types); return comphelper::containerToSequence(types); @@ -440,6 +442,19 @@ css::uno::Any Access::getByHierarchicalName(OUString const & aName) return child->asValue(); } +OUString Access::getDescriptionByHierarchicalName(OUString const & aName) +{ + assert(thisIs(IS_ANY)); + osl::MutexGuard g(*lock_); + checkLocalizedPropertyAccess(); + rtl::Reference< ChildAccess > child(getSubChild(aName)); + if (!child.is()) { + throw css::container::NoSuchElementException( + aName, getXWeak()); + } + return child->getNode()->getDescription(); +} + sal_Bool Access::hasByHierarchicalName(OUString const & aName) { assert(thisIs(IS_ANY)); @@ -1300,6 +1315,7 @@ css::uno::Any Access::queryInterface(css::uno::Type const & aType) static_cast< css::lang::XServiceInfo * >(this), static_cast< css::lang::XComponent * >(this), static_cast< css::container::XHierarchicalNameAccess * >(this), + static_cast< css::configuration::XDocumentation * >(this), static_cast< css::container::XContainer * >(this), static_cast< css::beans::XExactName * >(this), static_cast< css::container::XHierarchicalName * >(this), diff --git a/configmgr/source/access.hxx b/configmgr/source/access.hxx index daa5f1d1f6be..4efa910b68c5 100644 --- a/configmgr/source/access.hxx +++ b/configmgr/source/access.hxx @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -82,6 +84,7 @@ class Access: public cppu::OWeakObject, public css::lang::XTypeProvider, public css::lang::XServiceInfo, public css::lang::XComponent, + public css::configuration::XDocumentation, public css::container::XHierarchicalNameReplace, public css::container::XContainer, public css::beans::XExactName, @@ -159,6 +162,9 @@ public: virtual css::uno::Any SAL_CALL getByHierarchicalName( OUString const & aName) override; + virtual OUString SAL_CALL getDescriptionByHierarchicalName( + OUString const & aName) override; + virtual sal_Bool SAL_CALL hasByHierarchicalName(OUString const & aName) override; virtual void SAL_CALL replaceByHierarchicalName( diff --git a/configmgr/source/node.cxx b/configmgr/source/node.cxx index 8f00d3887da3..2c8c697b5338 100644 --- a/configmgr/source/node.cxx +++ b/configmgr/source/node.cxx @@ -59,7 +59,6 @@ void Node::setFinalized(int layer) { finalized_ = layer; } - rtl::Reference< Node > Node::getMember(OUString const & name) { NodeMap const & members = getMembers(); NodeMap::const_iterator i(members.find(name)); diff --git a/configmgr/source/node.hxx b/configmgr/source/node.hxx index b858c9e42e95..cce8e3d4abb3 100644 --- a/configmgr/source/node.hxx +++ b/configmgr/source/node.hxx @@ -23,7 +23,9 @@ #include #include +#include #include +#include namespace configmgr { @@ -51,6 +53,9 @@ public: void setFinalized(int layer); int getFinalized() const { return finalized_;} + void setDescription(OUString const& description) { description_ = description; }; + OUString getDescription() { return description_; } + rtl::Reference< Node > getMember(OUString const & name); protected: @@ -61,6 +66,7 @@ protected: private: int layer_; int finalized_; + OUString description_; }; } diff --git a/configmgr/source/xcsparser.cxx b/configmgr/source/xcsparser.cxx index 947792c0a62e..4f9cf2ee2ddb 100644 --- a/configmgr/source/xcsparser.cxx +++ b/configmgr/source/xcsparser.cxx @@ -109,12 +109,14 @@ void merge( } XcsParser::XcsParser(int layer, Data & data): - valueParser_(layer), data_(data), state_(STATE_START), ignoring_() + valueParser_(layer), data_(data), state_(STATE_START), ignoring_(), bIsParsingInfo_(false) {} XcsParser::~XcsParser() {} xmlreader::XmlReader::Text XcsParser::getTextMode() { + if (bIsParsingInfo_) + return xmlreader::XmlReader::Text::Raw; return valueParser_.getTextMode(); } @@ -122,6 +124,20 @@ bool XcsParser::startElement( xmlreader::XmlReader & reader, int nsId, xmlreader::Span const & name, std::set< OUString > const * /*existingDependencies*/) { + //TODO: ignoring component-schema import, component-schema uses, and + // prop constraints; accepting all four at illegal places (and with + // illegal content): + if (ignoring_ > 0 + || (nsId == xmlreader::XmlReader::NAMESPACE_NONE + && (name == "import" || name == "uses" || name == "constraints" || name == "desc"))) + { + assert(ignoring_ < LONG_MAX); + ++ignoring_; + return true; + } + + if (bIsParsingInfo_) + return true; if (valueParser_.startElement(reader, nsId, name)) { return true; } @@ -135,18 +151,6 @@ bool XcsParser::startElement( return true; } } else { - //TODO: ignoring component-schema import, component-schema uses, and - // prop constraints; accepting all four at illegal places (and with - // illegal content): - if (ignoring_ > 0 || - (nsId == xmlreader::XmlReader::NAMESPACE_NONE && - (name == "info" || name == "import" || - name == "uses" || name == "constraints"))) - { - assert(ignoring_ < LONG_MAX); - ++ignoring_; - return true; - } switch (state_) { case STATE_COMPONENT_SCHEMA: if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && @@ -155,6 +159,12 @@ bool XcsParser::startElement( state_ = STATE_TEMPLATES; return true; } + if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name == "info") + { + bIsParsingInfo_ = true; + return true; + } [[fallthrough]]; case STATE_TEMPLATES_DONE: if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && @@ -170,6 +180,12 @@ bool XcsParser::startElement( } break; case STATE_TEMPLATES: + if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name == "info") + { + bIsParsingInfo_ = true; + return true; + } if (elements_.empty()) { if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && name == "group") @@ -183,6 +199,12 @@ bool XcsParser::startElement( handleSet(reader, true); return true; } + if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name == "info") + { + bIsParsingInfo_ = true; + return true; + } break; } [[fallthrough]]; @@ -197,6 +219,12 @@ bool XcsParser::startElement( handlePropValue(reader, elements_.top().node); return true; } + if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name == "info") + { + bIsParsingInfo_ = true; + return true; + } break; case Node::KIND_GROUP: if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && @@ -223,6 +251,12 @@ bool XcsParser::startElement( handleSet(reader, false); return true; } + if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name == "info") + { + bIsParsingInfo_ = true; + return true; + } break; case Node::KIND_SET: if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && @@ -233,6 +267,12 @@ bool XcsParser::startElement( static_cast< SetNode * >(elements_.top().node.get())); return true; } + if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name == "info") + { + bIsParsingInfo_ = true; + return true; + } break; default: // Node::KIND_LOCALIZED_VALUE assert(false); // this cannot happen @@ -251,15 +291,28 @@ bool XcsParser::startElement( } void XcsParser::endElement(xmlreader::XmlReader const & reader) { + if (ignoring_ > 0) { + --ignoring_; + return; + } + if (bIsParsingInfo_) + { + bIsParsingInfo_ = false; + return; + } if (valueParser_.endElement()) { return; } - if (ignoring_ > 0) { - --ignoring_; - } else if (!elements_.empty()) { + if (!elements_.empty()) { Element top(std::move(elements_.top())); elements_.pop(); if (top.node.is()) { + // Remove whitespace from description_ resulting from line breaks/indentation in xml files + OUString desc(description_.makeStringAndClear()); + desc = desc.trim(); + while (desc.indexOf(" ") != -1) + desc = desc.replaceAll(" ", " "); + top.node->setDescription(desc); if (elements_.empty()) { switch (state_) { case STATE_TEMPLATES: @@ -316,6 +369,11 @@ void XcsParser::endElement(xmlreader::XmlReader const & reader) { } void XcsParser::characters(xmlreader::Span const & text) { + if (bIsParsingInfo_) + { + description_.append(text.convertFromUtf8()); + return; + } valueParser_.characters(text); } diff --git a/configmgr/source/xcsparser.hxx b/configmgr/source/xcsparser.hxx index f2c5c77429d6..aedcccde1147 100644 --- a/configmgr/source/xcsparser.hxx +++ b/configmgr/source/xcsparser.hxx @@ -94,6 +94,8 @@ private: State state_; long ignoring_; ElementStack elements_; + bool bIsParsingInfo_; + OUStringBuffer description_; }; } diff --git a/cui/source/options/optaboutconfig.cxx b/cui/source/options/optaboutconfig.cxx index 4578bc027581..74bf672a3cf1 100644 --- a/cui/source/options/optaboutconfig.cxx +++ b/cui/source/options/optaboutconfig.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -70,13 +71,15 @@ struct UserData bool bIsPropertyPath; bool bIsReadOnly; OUString sPropertyPath; + OUString sTooltip; int aLineage; Reference aXNameAccess; - explicit UserData( OUString aPropertyPath, bool isReadOnly ) + explicit UserData( OUString aPropertyPath, OUString aTooltip, bool isReadOnly ) : bIsPropertyPath( true ) , bIsReadOnly( isReadOnly ) , sPropertyPath(std::move(aPropertyPath)) + , sTooltip(std::move(aTooltip)) , aLineage(0) {} @@ -186,12 +189,19 @@ CuiAboutConfigTabPage::CuiAboutConfigTabPage(weld::Window* pParent) IMPL_LINK(CuiAboutConfigTabPage, QueryTooltip, const weld::TreeIter&, rIter, OUString) { UserData *pUserData = weld::fromId(m_xPrefBox->get_id(rIter)); + OUStringBuffer ret; if (pUserData && pUserData->bIsReadOnly) { - return CuiResId(RID_CUISTR_OPT_READONLY); + ret.append(CuiResId(RID_CUISTR_OPT_READONLY)); + } + if (pUserData && !pUserData->sTooltip.isEmpty()) + { + if (pUserData->bIsReadOnly) + ret.append("\n\n"); + ret.append(pUserData->sTooltip); } - return OUString(); + return ret.makeStringAndClear(); } IMPL_LINK(CuiAboutConfigTabPage, HeaderBarClick, int, nColumn, void) @@ -230,10 +240,11 @@ CuiAboutConfigTabPage::~CuiAboutConfigTabPage() } void CuiAboutConfigTabPage::InsertEntry(const OUString& rPropertyPath, const OUString& rProp, const OUString& rStatus, - const OUString& rType, const OUString& rValue, const weld::TreeIter* pParentEntry, + const OUString& rType, const OUString& rValue, const OUString& rTooltip, + const weld::TreeIter* pParentEntry, bool bInsertToPrefBox, bool bIsReadOnly) { - m_vectorUserData.push_back(std::make_unique(rPropertyPath, bIsReadOnly)); + m_vectorUserData.push_back(std::make_unique(rPropertyPath, rTooltip, bIsReadOnly)); if (bInsertToPrefBox) { OUString sId(weld::toId(m_vectorUserData.back().get())); @@ -357,6 +368,16 @@ void CuiAboutConfigTabPage::FillItems(const Reference< XNameAccess >& xNameAcces SAL_WARN("cui.options", "unknown property: " << sPath + "/" + sPropertyName); } + OUString sTooltip; + try + { + Reference xObjProp(xNameAccess, UNO_QUERY_THROW); + sTooltip = xObjProp->getDescriptionByHierarchicalName(sPath + "/" + sPropertyName); + } + catch (css::container::NoSuchElementException) + { + } + OUString sType = aNode.getValueTypeName(); OUStringBuffer sValue; @@ -518,7 +539,7 @@ void CuiAboutConfigTabPage::FillItems(const Reference< XNameAccess >& xNameAcces for(int j = 1; j < lineage; ++j) index = sPath.indexOf("/", index + 1); - InsertEntry(sPath, sPath.copy(index + 1), item, sType, sValue.makeStringAndClear(), + InsertEntry(sPath, sPath.copy(index + 1), item, sType, sValue.makeStringAndClear(), sTooltip, pParentEntry, !bLoadAll, bReadOnly); } } diff --git a/cui/source/options/optaboutconfig.hxx b/cui/source/options/optaboutconfig.hxx index 6cbb76e4cbde..c7278be7b19b 100644 --- a/cui/source/options/optaboutconfig.hxx +++ b/cui/source/options/optaboutconfig.hxx @@ -66,7 +66,8 @@ private: public: explicit CuiAboutConfigTabPage(weld::Window* pParent); virtual ~CuiAboutConfigTabPage() override; - void InsertEntry(const OUString &rPropertyPath, const OUString& rProp, const OUString& rStatus, const OUString& rType, const OUString& rValue, + void InsertEntry(const OUString &rPropertyPath, const OUString& rProp, const OUString& rStatus, + const OUString& rType, const OUString& rValue, const OUString& rTooltip, const weld::TreeIter* pParentEntry, bool bInsertToPrefBox, bool bIsReadOnly); void Reset(); void FillItems(const css::uno::Reference& xNameAccess, diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index eba803973aa5..2e2ee40aa8b4 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -2083,6 +2083,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/configuration,\ InstallationIncompleteException \ InvalidBootstrapFileException \ MissingBootstrapFileException \ + XDocumentation \ XReadWriteAccess \ XTemplateContainer \ XTemplateInstance \ diff --git a/offapi/com/sun/star/configuration/XDocumentation.idl b/offapi/com/sun/star/configuration/XDocumentation.idl new file mode 100644 index 000000000000..3bf3c638b141 --- /dev/null +++ b/offapi/com/sun/star/configuration/XDocumentation.idl @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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/. + */ + +module com { module sun { module star { module configuration { + +/* Is used to deliver documentation for the configuration. + +

This interface is still unpublished and unstable.

+ + @since LibreOffice 24.2 +*/ +interface XDocumentation { + /** @returns + the description for the requested object + + @param aName + the hierarchical name of the object. + + @throws NoSuchElementException + if an element under aName does not exist. + */ + string getDescriptionByHierarchicalName( [in] string aName ) + raises( com::sun::star::container::NoSuchElementException ); +}; + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/officecfg/util/schema_trim.xsl b/officecfg/util/schema_trim.xsl index 41c25990719d..0e0f06fba75d 100644 --- a/officecfg/util/schema_trim.xsl +++ b/officecfg/util/schema_trim.xsl @@ -54,7 +54,7 @@ - + diff --git a/solenv/bin/packregistry.xslt b/solenv/bin/packregistry.xslt index 9079bbc6b43d..cf89c1a7dc30 100644 --- a/solenv/bin/packregistry.xslt +++ b/solenv/bin/packregistry.xslt @@ -56,7 +56,7 @@ + set|node-ref|prop|item|value|it|unicode|node|info"> @@ -71,7 +71,7 @@ - +