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>
This commit is contained in:
Samuel Mehrbrodt 2023-09-21 16:00:40 +02:00
parent 560cb9c53e
commit db3078bd8c
12 changed files with 171 additions and 27 deletions

View file

@ -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),

View file

@ -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(

View file

@ -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));

View file

@ -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_;
};
}

View file

@ -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);
}

View file

@ -94,6 +94,8 @@ private:
State state_;
long ignoring_;
ElementStack elements_;
bool bIsParsingInfo_;
OUStringBuffer description_;
};
}

View file

@ -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);
}
}

View file

@ -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,

View file

@ -2083,6 +2083,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/configuration,\
InstallationIncompleteException \
InvalidBootstrapFileException \
MissingBootstrapFileException \
XDocumentation \
XReadWriteAccess \
XTemplateContainer \
XTemplateInstance \

View file

@ -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: */

View file

@ -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="."/>

View file

@ -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="@*">