summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>2023-09-21 16:00:40 +0200
committerSamuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>2023-11-09 08:14:38 +0100
commitdb3078bd8c8e3ce3a99fc3987bb6e93b609990c1 (patch)
treeade902e5f81d719894b5072f6db6ac241b60fc50
parent560cb9c53e7c6d6b8164cdd92e897d3c99b850d2 (diff)
tdf#157431 Show description for expert config items
Change-Id: I7d0257c2e06ed384f90ca3b51a6d2549044f2cf3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157148 Tested-by: Jenkins Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
-rw-r--r--configmgr/source/access.cxx16
-rw-r--r--configmgr/source/access.hxx6
-rw-r--r--configmgr/source/node.cxx1
-rw-r--r--configmgr/source/node.hxx6
-rw-r--r--configmgr/source/xcsparser.cxx90
-rw-r--r--configmgr/source/xcsparser.hxx2
-rw-r--r--cui/source/options/optaboutconfig.cxx33
-rw-r--r--cui/source/options/optaboutconfig.hxx3
-rw-r--r--offapi/UnoApi_offapi.mk1
-rw-r--r--offapi/com/sun/star/configuration/XDocumentation.idl34
-rw-r--r--officecfg/util/schema_trim.xsl2
-rw-r--r--solenv/bin/packregistry.xslt4
12 files changed, 171 insertions, 27 deletions
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 <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/container/XContainer.hpp>
#include <com/sun/star/container/XHierarchicalName.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/configuration/XDocumentation.hpp>
#include <com/sun/star/container/XHierarchicalNameReplace.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/container/XNamed.hpp>
@@ -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 <rtl/ref.hxx>
#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
#include <salhelper/simplereferenceobject.hxx>
+#include <xmlreader/span.hxx>
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 <com/sun/star/beans/UnknownPropertyException.hpp>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <com/sun/star/configuration/ReadWriteAccess.hpp>
+#include <com/sun/star/configuration/XDocumentation.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/container/XHierarchicalName.hpp>
@@ -70,13 +71,15 @@ struct UserData
bool bIsPropertyPath;
bool bIsReadOnly;
OUString sPropertyPath;
+ OUString sTooltip;
int aLineage;
Reference<XNameAccess> 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<UserData*>(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<UserData>(rPropertyPath, bIsReadOnly));
+ m_vectorUserData.push_back(std::make_unique<UserData>(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<configuration::XDocumentation> 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<css::container::XNameAccess>& 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.
+
+ <p>This interface is still unpublished and unstable.</p>
+
+ @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 @@
<xsl:template match = "label[../deprecated]"/>
<!-- copy all other documentation with content -->
- <xsl:template match="desc|label">
+ <xsl:template match="info|desc|label">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:value-of select="."/>
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 @@
</xsl:template>
<xsl:template
match="oor:component-schema|oor:component-data|templates|component|group|
- set|node-ref|prop|item|value|it|unicode|node">
+ set|node-ref|prop|item|value|it|unicode|node|info">
<xsl:copy copy-namespaces="no">
<!-- prune oor:component-data xmlns:install="..." namespaces (would only
work in XSLT 2.0, however) -->
@@ -71,7 +71,7 @@
<!-- ignore text elements (which must be whitespace only) -->
</xsl:copy>
</xsl:template>
- <xsl:template match="info|import|uses|constraints"/>
+ <xsl:template match="import|uses|constraints"/>
<!-- TODO: no longer strip elements when they are eventually read by
configmgr implementation -->
<xsl:template match="@*">