Doc: Support for meta-content in manifest XML files

This change makes qdoc support additional attributes and tags written
to example/demo manifest files. The goal is to enable highlighting of
selected items, as well as having additional content to make searching
for specific categories work better in Qt Creator welcome screen.

This meta-content is stored in manifest-meta.qdocconf, which is loaded
globally for all modules.

Tag handling is also changed to use a QSet to eliminate possible
duplicate tags.

Task-number: QTBUG-29354
Change-Id: I2c4b2dff6229172efbecc2bfc1c269017edc4d56
Reviewed-by: Martin Smith <martin.smith@digia.com>
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
This commit is contained in:
Topi Reinio 2013-02-14 10:39:37 +01:00 committed by The Qt Project
parent 57953e0fea
commit 284958c222
5 changed files with 99 additions and 5 deletions

View File

@ -0,0 +1,33 @@
# Additional meta information (attributes for matched entries, as well as tags)
# to be added to manifest.xml files.
#
# manifestmeta.filters = <filter1>,<filter2>,...
#
# manifestmeta.<filter>.names = <Module1>/<name1>,<Module2>/<name2>,..
# manifestmeta.<filter>.attributes = <attribute1:value1>,<attribute2:value2>,..
# manifestmeta.<filter>.tags = <tag1>,<tag2>,..
#
# <filter>.names specify all the module/name combinations to apply the
# attributes/tags to. You can use simple wildcard matching by appending
# '*' at the end of name.
#
# Note: You cannot use operators (+, =, -) in the names.
#
# Examples: add a 'isHighlighted' attribute for two 'Analog Clock' examples,
# add a 'database' tag for QtSql all examples, a 'webkit' tag for QtWebKit
# examples, and a 'qt5' tag for all examples
#
# manifestmeta.filters = highlighted sql webkit global
#
# manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example" \
# "QtWidgets/Analog Clock Example"
# manifestmeta.highlighted.attributes = isHighlighted:true
#
# manifestmeta.sql.names = "QtSql/*"
# manifestmeta.sql.tags = database
#
# manifestmeta.webkit.names = "QtWebKitExamples/*"
# manifestmeta.webkit.tags = webkit
#
# manifestmeta.global.names = *
# manifestmeta.global.tags = qt5

View File

@ -3,6 +3,7 @@ include(qt-cpp-ignore.qdocconf)
include(qt-defines.qdocconf)
include(qt-html-templates-offline.qdocconf)
include(compat.qdocconf)
include(manifest-meta.qdocconf)
dita.metadata.default.author = Qt Project
dita.metadata.default.permissions = all

View File

@ -188,6 +188,7 @@ private:
#define CONFIG_INDEXES "indexes"
#define CONFIG_LANGUAGE "language"
#define CONFIG_MACRO "macro"
#define CONFIG_MANIFESTMETA "manifestmeta"
#define CONFIG_NATURALLANGUAGE "naturallanguage"
#define CONFIG_NOLINKERRORS "nolinkerrors"
#define CONFIG_OBSOLETELINKS "obsoletelinks"

View File

@ -223,6 +223,7 @@ void HtmlGenerator::initializeGenerator(const Config &config)
QString prefix = CONFIG_QHP + Config::dot + project + Config::dot;
manifestDir = "qthelp://" + config.getString(prefix + "namespace");
manifestDir += QLatin1Char('/') + config.getString(prefix + "virtualFolder") + QLatin1Char('/');
readManifestMetaContent(config);
examplesPath = config.getString(CONFIG_EXAMPLESINSTALLPATH);
if (!examplesPath.isEmpty())
examplesPath += QLatin1Char('/');
@ -3991,10 +3992,11 @@ void HtmlGenerator::generateManifestFiles()
generateManifestFile("examples", "example");
generateManifestFile("demos", "demo");
ExampleNode::exampleNodeMap.clear();
manifestMetaContent.clear();
}
/*!
This function is called by generaqteManiferstFile(), once
This function is called by generateManifestFiles(), once
for each manifest file to be generated. \a manifest is the
type of manifest file.
*/
@ -4086,6 +4088,36 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
}
if (!en->imageFileName().isEmpty())
writer.writeAttribute("imageUrl", manifestDir + en->imageFileName());
QString fullName = project + QLatin1Char('/') + en->title();
QSet<QString> tags;
for (int idx=0; idx < manifestMetaContent.size(); ++idx) {
foreach (const QString &name, manifestMetaContent[idx].names) {
bool match = false;
int wildcard = name.indexOf(QChar('*'));
switch (wildcard) {
case -1: // no wildcard, exact match
match = (fullName == name);
break;
case 0: // '*' matches all
match = true;
break;
default: // match with wildcard at the end
match = fullName.startsWith(name.left(wildcard));
}
if (match) {
tags += manifestMetaContent[idx].tags;
foreach (const QString &attr, manifestMetaContent[idx].attributes) {
QStringList attrList = attr.split(QLatin1Char(':'), QString::SkipEmptyParts);
if (attrList.count() == 1)
attrList.append(QStringLiteral("true"));
if (attrList.count() == 2)
writer.writeAttribute(attrList[0], attrList[1]);
}
}
}
}
writer.writeStartElement("description");
Text brief = en->doc().briefText();
if (!brief.isEmpty())
@ -4093,12 +4125,11 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
else
writer.writeCDATA(QString("No description available"));
writer.writeEndElement(); // description
QStringList tags = en->title().toLower().split(QLatin1Char(' '));
tags += QSet<QString>::fromList(en->title().toLower().split(QLatin1Char(' ')));
if (!tags.isEmpty()) {
writer.writeStartElement("tags");
bool wrote_one = false;
for (int n=0; n<tags.size(); ++n) {
QString tag = tags.at(n);
foreach (QString tag, tags) {
if (tag.at(0).isDigit())
continue;
if (tag.at(0) == '-')
@ -4109,7 +4140,7 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
continue;
if (tag.endsWith(QLatin1Char(':')))
tag.chop(1);
if (n>0 && wrote_one)
if (wrote_one)
writer.writeCharacters(",");
writer.writeCharacters(tag);
wrote_one = true;
@ -4162,6 +4193,25 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
file.close();
}
/*!
Reads metacontent - additional attributes and tags to apply
when generating manifest files, read from config. Takes the
configuration class \a config as a parameter.
*/
void HtmlGenerator::readManifestMetaContent(const Config &config)
{
QStringList names = config.getStringList(CONFIG_MANIFESTMETA + Config::dot + QStringLiteral("filters"));
foreach (const QString &manifest, names) {
ManifestMetaFilter filter;
QString prefix = CONFIG_MANIFESTMETA + Config::dot + manifest + Config::dot;
filter.names = config.getStringSet(prefix + QStringLiteral("names"));
filter.attributes = config.getStringSet(prefix + QStringLiteral("attributes"));
filter.tags = config.getStringSet(prefix + QStringLiteral("tags"));
manifestMetaContent.append(filter);
}
}
/*!
Find global entities that have documentation but no
\e{relates} comand. Report these as errors if they

View File

@ -108,6 +108,7 @@ protected:
virtual QString linkForNode(const Node *node, const Node *relative);
void generateManifestFile(QString manifest, QString element);
void readManifestMetaContent(const Config &config);
private:
enum SubTitleSize { SmallSubTitle, LargeSubTitle };
@ -118,6 +119,13 @@ private:
EndMark
};
struct ManifestMetaFilter
{
QSet<QString> names;
QSet<QString> attributes;
QSet<QString> tags;
};
const QPair<QString,QString> anchorForNode(const Node *node);
void generateBreadCrumbs(const QString& title,
const Node *node,
@ -242,6 +250,7 @@ private:
bool obsoleteLinks;
QStack<QXmlStreamWriter*> xmlWriterStack;
static int id;
QList<ManifestMetaFilter> manifestMetaContent;
public:
static bool debugging_on;
static QString divNavTop;