summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
authorCasper van Donderen <casper.vandonderen@nokia.com>2012-03-17 19:44:49 +0100
committerQt by Nokia <qt-info@nokia.com>2012-03-20 08:20:46 +0100
commit5939cd33af5e43308e533a85444da073add8f05a (patch)
tree844a7c0b9c3bdd5f157c2d88d3a2cf8e5a3dce36 /src/tools
parentc2e8db58413207315474232697f12ddceb8310e7 (diff)
qdoc: Merge PageGenerator into Generator class.
This change also sorts all functions in Generator by alphabet and moves the implementation of the GenerateQmlInheritedBy function to the Generator class, since the implementation in both the DITA and HTML generators was the same. Task-number: QTBUG-24833 Change-Id: I44588079159e03b7ff7549e5478babb1aabdaf1b Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.cpp42
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.h5
-rw-r--r--src/tools/qdoc/generator.cpp1909
-rw-r--r--src/tools/qdoc/generator.h176
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp35
-rw-r--r--src/tools/qdoc/htmlgenerator.h9
-rw-r--r--src/tools/qdoc/pagegenerator.cpp389
-rw-r--r--src/tools/qdoc/pagegenerator.h99
-rw-r--r--src/tools/qdoc/qdoc.pro2
9 files changed, 1237 insertions, 1429 deletions
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp
index f19f902c6b..9cb50a44f7 100644
--- a/src/tools/qdoc/ditaxmlgenerator.cpp
+++ b/src/tools/qdoc/ditaxmlgenerator.cpp
@@ -43,6 +43,11 @@
ditaxmlgenerator.cpp
*/
+#include <QDebug>
+#include <QList>
+#include <qiterator.h>
+#include <QTextCodec>
+#include <QUuid>
#include "codemarker.h"
#include "codeparser.h"
#include "ditaxmlgenerator.h"
@@ -51,11 +56,6 @@
#include "separator.h"
#include "tree.h"
#include <ctype.h>
-#include <qdebug.h>
-#include <qlist.h>
-#include <qiterator.h>
-#include <qtextcodec.h>
-#include <QUuid>
QT_BEGIN_NAMESPACE
@@ -636,7 +636,7 @@ void DitaXmlGenerator::generateTree(const Tree *tree)
findAllNamespaces(tree->root());
findAllSince(tree->root());
- PageGenerator::generateTree(tree);
+ Generator::generateTree(tree);
writeDitaMap(tree);
}
@@ -3816,7 +3816,7 @@ QString DitaXmlGenerator::protect(const QString& string, const QString& ) //outp
QString DitaXmlGenerator::fileBase(const Node* node) const
{
QString result;
- result = PageGenerator::fileBase(node);
+ result = Generator::fileBase(node);
#if 0
if (!node->isInnerNode()) {
switch (node->status()) {
@@ -3898,7 +3898,7 @@ QString DitaXmlGenerator::fileName(const Node* node)
if (static_cast<const FakeNode*>(node)->subType() == Node::Image)
return node->name();
}
- return PageGenerator::fileName(node);
+ return Generator::fileName(node);
}
QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative)
@@ -4162,7 +4162,7 @@ const Node* DitaXmlGenerator::findNodeForTarget(const QString& target,
const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node* node)
{
QPair<QString,QString> anchorPair;
- anchorPair.first = PageGenerator::fileName(node);
+ anchorPair.first = Generator::fileName(node);
if (node->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
anchorPair.second = fakeNode->title();
@@ -4594,26 +4594,6 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker*
}
/*!
- Output the "Inherit by" list for the QML element,
- if it is inherited by any other elements.
- */
-void DitaXmlGenerator::generateQmlInheritedBy(const QmlClassNode* qcn,
- CodeMarker* marker)
-{
- if (qcn) {
- NodeList subs;
- QmlClassNode::subclasses(qcn->name(),subs);
- if (!subs.isEmpty()) {
- Text text;
- text << Atom::ParaLeft << "Inherited by ";
- appendSortedQmlNames(text,qcn,subs,marker);
- text << Atom::ParaRight;
- generateText(text, qcn, marker);
- }
- }
-}
-
-/*!
Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]"
line for the QML element, if there should be one.
@@ -5559,7 +5539,7 @@ void DitaXmlGenerator::writePropertyParameter(const QString& tag, const NodeList
void DitaXmlGenerator::beginSubPage(const InnerNode* node,
const QString& fileName)
{
- PageGenerator::beginSubPage(node,fileName);
+ Generator::beginSubPage(node,fileName);
(void) lookupGuidMap(fileName);
QXmlStreamWriter* writer = new QXmlStreamWriter(out().device());
xmlWriterStack.push(writer);
@@ -5580,7 +5560,7 @@ void DitaXmlGenerator::endSubPage()
qDebug() << "Missing </section> in" << outFileName() << sectionNestingLevel;
xmlWriter().writeEndDocument();
delete xmlWriterStack.pop();
- PageGenerator::endSubPage();
+ Generator::endSubPage();
}
/*!
diff --git a/src/tools/qdoc/ditaxmlgenerator.h b/src/tools/qdoc/ditaxmlgenerator.h
index b3da02bce1..c2bd309200 100644
--- a/src/tools/qdoc/ditaxmlgenerator.h
+++ b/src/tools/qdoc/ditaxmlgenerator.h
@@ -47,14 +47,14 @@
#include <QXmlStreamWriter>
#include "codemarker.h"
#include "config.h"
-#include "pagegenerator.h"
+#include "generator.h"
QT_BEGIN_NAMESPACE
typedef QMap<QString, QString> GuidMap;
typedef QMap<QString, GuidMap*> GuidMaps;
-class DitaXmlGenerator : public PageGenerator
+class DitaXmlGenerator : public Generator
{
public:
enum SinceType {
@@ -381,7 +381,6 @@ private:
const InnerNode* relative,
CodeMarker* marker);
void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
- void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker);
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index c990413234..04624a5813 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -42,13 +42,11 @@
/*
generator.cpp
*/
-#include <qdir.h>
-#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
-#include <qdebug.h>
-#endif
-#include <qdebug.h>
+#include <QDir>
+#include <QDebug>
#include "codemarker.h"
#include "config.h"
+#include "ditaxmlgenerator.h"
#include "doc.h"
#include "editdistance.h"
#include "generator.h"
@@ -57,28 +55,25 @@
#include "quoter.h"
#include "separator.h"
#include "tokenizer.h"
-#include "ditaxmlgenerator.h"
+#include "tree.h"
QT_BEGIN_NAMESPACE
-QList<Generator *> Generator::generators;
+QString Generator::baseDir_;
+QStringList Generator::exampleDirs;
+QStringList Generator::exampleImgExts;
QMap<QString, QMap<QString, QString> > Generator::fmtLeftMaps;
QMap<QString, QMap<QString, QString> > Generator::fmtRightMaps;
-QMap<QString, QStringList> Generator::imgFileExts;
-QSet<QString> Generator::outputFormats;
-QStringList Generator::imageFiles;
+QList<Generator *> Generator::generators;
QStringList Generator::imageDirs;
-QStringList Generator::exampleDirs;
-QStringList Generator::exampleImgExts;
-QStringList Generator::scriptFiles;
-QStringList Generator::scriptDirs;
-QStringList Generator::styleFiles;
-QStringList Generator::styleDirs;
+QStringList Generator::imageFiles;
+QMap<QString, QStringList> Generator::imgFileExts;
QString Generator::outDir_;
-QString Generator::baseDir_;
-QString Generator::project;
+QSet<QString> Generator::outputFormats;
QHash<QString, QString> Generator::outputPrefixes;
-
+QString Generator::project;
+QStringList Generator::scriptDirs;
+QStringList Generator::scriptFiles;
QString Generator::sinceTitles[] =
{
" New Namespaces",
@@ -98,19 +93,14 @@ QString Generator::sinceTitles[] =
" New QML Methods",
""
};
+QStringList Generator::styleDirs;
+QStringList Generator::styleFiles;
-static void singularPlural(Text& text, const NodeList& nodes)
-{
- if (nodes.count() == 1)
- text << " is";
- else
- text << " are";
-}
Generator::Generator()
: amp("&amp;"),
- lt("&lt;"),
gt("&gt;"),
+ lt("&lt;"),
quot("&quot;"),
tag("</?@[^>]*>")
{
@@ -122,233 +112,371 @@ Generator::~Generator()
generators.removeAll(this);
}
-void Generator::initializeGenerator(const Config & /* config */)
+void Generator::appendFullName(Text& text,
+ const Node *apparentNode,
+ const Node *relative,
+ CodeMarker *marker,
+ const Node *actualNode)
{
+ if (actualNode == 0)
+ actualNode = apparentNode;
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, marker->plainFullName(apparentNode, relative))
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
-void Generator::terminateGenerator()
+void Generator::appendFullName(Text& text,
+ const Node *apparentNode,
+ const QString& fullName,
+ const Node *actualNode)
{
+ if (actualNode == 0)
+ actualNode = apparentNode;
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, fullName)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
-void Generator::initialize(const Config &config)
+void Generator::appendFullNames(Text& text,
+ const NodeList& nodes,
+ const Node* relative,
+ CodeMarker* marker)
{
- outputFormats = config.getOutputFormats();
- if (!outputFormats.isEmpty()) {
- outDir_ = config.getOutputDir();
- baseDir_ = config.getString(CONFIG_BASEDIR);
- if (!baseDir_.isEmpty())
- config.location().warning(tr("\"basedir\" specified in config file. "
- "All output will be in module directories of the output directory"));
- if (outDir_.isEmpty())
- config.lastLocation().fatal(tr("No output directory specified in configuration file or on the command line"));
+ NodeList::ConstIterator n = nodes.begin();
+ int index = 0;
+ while (n != nodes.end()) {
+ appendFullName(text,*n,relative,marker);
+ text << comma(index++,nodes.count());
+ ++n;
+ }
+}
- QDir dirInfo;
- if (dirInfo.exists(outDir_)) {
- if (!Config::removeDirContents(outDir_))
- config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir_));
- }
- else {
- if (!dirInfo.mkpath(outDir_))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_));
+void Generator::appendSortedNames(Text& text,
+ const ClassNode *classe,
+ const QList<RelatedClass> &classes,
+ CodeMarker *marker)
+{
+ QList<RelatedClass>::ConstIterator r;
+ QMap<QString,Text> classMap;
+ int index = 0;
+
+ r = classes.begin();
+ while (r != classes.end()) {
+ if ((*r).node->access() == Node::Public &&
+ (*r).node->status() != Node::Internal
+ && !(*r).node->doc().isEmpty()) {
+ Text className;
+ appendFullName(className, (*r).node, classe, marker);
+ classMap[className.toString().toLower()] = className;
}
+ ++r;
+ }
- if (!dirInfo.mkdir(outDir_ + "/images"))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'")
- .arg(outDir_ + "/images"));
- if (!dirInfo.mkdir(outDir_ + "/images/used-in-examples"))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'")
- .arg(outDir_ + "/images/used-in-examples"));
- if (!dirInfo.mkdir(outDir_ + "/scripts"))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'")
- .arg(outDir_ + "/scripts"));
- if (!dirInfo.mkdir(outDir_ + "/style"))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'")
- .arg(outDir_ + "/style"));
+ QStringList classNames = classMap.keys();
+ classNames.sort();
+
+ foreach (const QString &className, classNames) {
+ text << classMap[className];
+ text << separator(index++, classNames.count());
}
+}
- imageFiles = config.getCleanPathList(CONFIG_IMAGES);
- imageDirs = config.getCleanPathList(CONFIG_IMAGEDIRS);
- scriptFiles = config.getCleanPathList(CONFIG_SCRIPTS);
- scriptDirs = config.getCleanPathList(CONFIG_SCRIPTDIRS);
- styleFiles = config.getCleanPathList(CONFIG_STYLES);
- styleDirs = config.getCleanPathList(CONFIG_STYLEDIRS);
- exampleDirs = config.getCleanPathList(CONFIG_EXAMPLEDIRS);
- exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot +
- CONFIG_IMAGEEXTENSIONS);
+void Generator::appendSortedQmlNames(Text& text,
+ const Node* base,
+ const NodeList& subs,
+ CodeMarker *marker)
+{
+ QMap<QString,Text> classMap;
+ int index = 0;
- QString imagesDotFileExtensions =
- CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS;
- QSet<QString> formats = config.subVars(imagesDotFileExtensions);
- QSet<QString>::ConstIterator f = formats.begin();
- while (f != formats.end()) {
- imgFileExts[*f] = config.getStringList(imagesDotFileExtensions +
- Config::dot + *f);
- ++f;
+ for (int i = 0; i < subs.size(); ++i) {
+ Text t;
+ if (!base->isQtQuickNode() || !subs[i]->isQtQuickNode() ||
+ (base->qmlModuleIdentifier() == subs[i]->qmlModuleIdentifier())) {
+ appendFullName(t, subs[i], base, marker);
+ classMap[t.toString().toLower()] = t;
+ }
}
- QList<Generator *>::ConstIterator g = generators.begin();
- while (g != generators.end()) {
- if (outputFormats.contains((*g)->format())) {
- (*g)->initializeGenerator(config);
- QStringList extraImages =
- config.getCleanPathList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format());
- QStringList::ConstIterator e = extraImages.begin();
- while (e != extraImages.end()) {
- QString userFriendlyFilePath;
- QString filePath = Config::findFile(config.lastLocation(),
- imageFiles,
- imageDirs,
- *e,
- imgFileExts[(*g)->format()],
- userFriendlyFilePath);
- if (!filePath.isEmpty())
- Config::copyFile(config.lastLocation(),
- filePath,
- userFriendlyFilePath,
- (*g)->outputDir() +
- "/images");
- ++e;
- }
+ QStringList names = classMap.keys();
+ names.sort();
- // Documentation template handling
- QString templateDir = config.getString(
- (*g)->format() + Config::dot + CONFIG_TEMPLATEDIR);
+ foreach (const QString &name, names) {
+ text << classMap[name];
+ text << separator(index++, names.count());
+ }
+}
- if (!templateDir.isEmpty()) {
- QStringList noExts;
- QStringList searchDirs = QStringList() << templateDir;
- QStringList scripts =
- config.getCleanPathList((*g)->format()+Config::dot+CONFIG_SCRIPTS);
- e = scripts.begin();
- while (e != scripts.end()) {
- QString userFriendlyFilePath;
- QString filePath = Config::findFile(config.lastLocation(),
- scriptFiles,
- searchDirs,
- *e,
- noExts,
- userFriendlyFilePath);
- if (!filePath.isEmpty())
- Config::copyFile(config.lastLocation(),
- filePath,
- userFriendlyFilePath,
- (*g)->outputDir() +
- "/scripts");
- ++e;
- }
+/*!
+ Creates the file named \a fileName in the output directory.
+ Attaches a QTextStream to the created file, which is written
+ to all over the place using out().
+ */
+void Generator::beginSubPage(const InnerNode* node, const QString& fileName)
+{
+ QString path = outputDir() + QLatin1Char('/');
+ if (!node->outputSubdirectory().isEmpty())
+ path += node->outputSubdirectory() + QLatin1Char('/');
+ path += fileName;
+ QFile* outFile = new QFile(path);
+ if (!outFile->open(QFile::WriteOnly))
+ node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
+ QTextStream* out = new QTextStream(outFile);
+
+ if (outputCodec)
+ out->setCodec(outputCodec);
+ outStreamStack.push(out);
+ const_cast<InnerNode*>(node)->setOutputFileName(fileName);
+}
- QStringList styles =
- config.getCleanPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS);
- e = styles.begin();
- while (e != styles.end()) {
- QString userFriendlyFilePath;
- QString filePath = Config::findFile(config.lastLocation(),
- styleFiles,
- searchDirs,
- *e,
- noExts,
- userFriendlyFilePath);
- if (!filePath.isEmpty())
- Config::copyFile(config.lastLocation(),
- filePath,
- userFriendlyFilePath,
- (*g)->outputDir() +
- "/style");
- ++e;
- }
- }
+/*!
+ Flush the text stream associated with the subpage, and
+ then pop it off the text stream stack and delete it.
+ This terminates output of the subpage.
+ */
+void Generator::endSubPage()
+{
+ outStreamStack.top()->flush();
+ delete outStreamStack.top()->device();
+ delete outStreamStack.pop();
+}
+
+void Generator::endText(const Node * /* relative */,
+ CodeMarker * /* marker */)
+{
+}
+
+QString Generator::fileBase(const Node *node) const
+{
+ if (node->relates())
+ node = node->relates();
+ else if (!node->isInnerNode())
+ node = node->parent();
+ if (node->subType() == Node::QmlPropertyGroup) {
+ node = node->parent();
+ }
+
+ QString base = node->doc().baseName();
+ if (!base.isEmpty())
+ return base;
+
+ const Node *p = node;
+
+ forever {
+ const Node *pp = p->parent();
+ base.prepend(p->name());
+ if (!p->qmlModuleIdentifier().isEmpty())
+ base.prepend(p->qmlModuleIdentifier()+QChar('-'));
+ /*
+ To avoid file name conflicts in the html directory,
+ we prepend a prefix (by default, "qml-") to the file name of QML
+ element doc files.
+ */
+ if ((p->subType() == Node::QmlClass) ||
+ (p->subType() == Node::QmlBasicType)) {
+ base.prepend(outputPrefix(QLatin1String("QML")));
}
- ++g;
+ if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake)
+ break;
+ base.prepend(QLatin1Char('-'));
+ p = pp;
+ }
+ if (node->type() == Node::Fake) {
+ if (node->subType() == Node::Collision) {
+ const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
+ if (ncn->currentChild())
+ return fileBase(ncn->currentChild());
+ base.prepend("collision-");
+ }
+ //Was QDOC2_COMPAT, required for index.html
+ if (base.endsWith(".html"))
+ base.truncate(base.length() - 5);
}
- QRegExp secondParamAndAbove("[\2-\7]");
- QSet<QString> formattingNames = config.subVars(CONFIG_FORMATTING);
- QSet<QString>::ConstIterator n = formattingNames.begin();
- while (n != formattingNames.end()) {
- QString formattingDotName = CONFIG_FORMATTING + Config::dot + *n;
+ // the code below is effectively equivalent to:
+ // base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
+ // base = base.trimmed();
+ // base.replace(QLatin1Char(' '), QLatin1Char('-'));
+ // base = base.toLower();
+ // as this function accounted for ~8% of total running time
+ // we optimize a bit...
+
+ QString res;
+ // +5 prevents realloc in fileName() below
+ res.reserve(base.size() + 5);
+ bool begun = false;
+ for (int i = 0; i != base.size(); ++i) {
+ QChar c = base.at(i);
+ uint u = c.unicode();
+ if (u >= 'A' && u <= 'Z')
+ u -= 'A' - 'a';
+ if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) {
+ res += QLatin1Char(u);
+ begun = true;
+ }
+ else if (begun) {
+ res += QLatin1Char('-');
+ begun = false;
+ }
+ }
+ while (res.endsWith(QLatin1Char('-')))
+ res.chop(1);
+ return res;
+}
- QSet<QString> formats = config.subVars(formattingDotName);
- QSet<QString>::ConstIterator f = formats.begin();
- while (f != formats.end()) {
- QString def = config.getString(formattingDotName +
- Config::dot + *f);
- if (!def.isEmpty()) {
- int numParams = Config::numParams(def);
- int numOccs = def.count("\1");
+/*!
+ If the \a node has a URL, return the URL as the file name.
+ Otherwise, construct the file name from the fileBase() and
+ the fileExtension(), and return the constructed name.
+ */
+QString Generator::fileName(const Node* node) const
+{
+ if (!node->url().isEmpty())
+ return node->url();
- if (numParams != 1) {
- config.lastLocation().warning(tr("Formatting '%1' must "
- "have exactly one "
- "parameter (found %2)")
- .arg(*n).arg(numParams));
+ QString name = fileBase(node);
+ name += QLatin1Char('.');
+ name += fileExtension(node);
+ return name;
+}
+
+/*!
+ For generating the "New Classes... in x.y" section on the
+ What's New in Qt x.y" page.
+ */
+void Generator::findAllSince(const InnerNode *node)
+{
+ NodeList::const_iterator child = node->childNodes().constBegin();
+
+ // Traverse the tree, starting at the node supplied.
+
+ while (child != node->childNodes().constEnd()) {
+
+ QString sinceString = (*child)->since();
+
+ if (((*child)->access() != Node::Private) && !sinceString.isEmpty()) {
+
+ // Insert a new entry into each map for each new since string found.
+ NewSinceMaps::iterator nsmap = newSinceMaps.find(sinceString);
+ if (nsmap == newSinceMaps.end())
+ nsmap = newSinceMaps.insert(sinceString,NodeMultiMap());
+
+ NewClassMaps::iterator ncmap = newClassMaps.find(sinceString);
+ if (ncmap == newClassMaps.end())
+ ncmap = newClassMaps.insert(sinceString,NodeMap());
+
+ NewClassMaps::iterator nqcmap = newQmlClassMaps.find(sinceString);
+ if (nqcmap == newQmlClassMaps.end())
+ nqcmap = newQmlClassMaps.insert(sinceString,NodeMap());
+
+ if ((*child)->type() == Node::Function) {
+ // Insert functions into the general since map.
+ FunctionNode *func = static_cast<FunctionNode *>(*child);
+ if ((func->status() > Node::Obsolete) &&
+ (func->metaness() != FunctionNode::Ctor) &&
+ (func->metaness() != FunctionNode::Dtor)) {
+ nsmap.value().insert(func->name(),(*child));
}
- else if (numOccs > 1) {
- config.lastLocation().fatal(tr("Formatting '%1' must "
- "contain exactly one "
- "occurrence of '\\1' "
- "(found %2)")
- .arg(*n).arg(numOccs));
+ }
+ else if ((*child)->url().isEmpty()) {
+ if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) {
+ // Insert classes into the since and class maps.
+ QString className = (*child)->name();
+ if ((*child)->parent() &&
+ (*child)->parent()->type() == Node::Namespace &&
+ !(*child)->parent()->name().isEmpty())
+ className = (*child)->parent()->name()+"::"+className;
+
+ nsmap.value().insert(className,(*child));
+ ncmap.value().insert(className,(*child));
}
- else {
- int paramPos = def.indexOf("\1");
- fmtLeftMaps[*f].insert(*n, def.left(paramPos));
- fmtRightMaps[*f].insert(*n, def.mid(paramPos + 1));
+ else if ((*child)->subType() == Node::QmlClass) {
+ // Insert QML elements into the since and element maps.
+ QString className = (*child)->name();
+ if ((*child)->parent() &&
+ (*child)->parent()->type() == Node::Namespace &&
+ !(*child)->parent()->name().isEmpty())
+ className = (*child)->parent()->name()+"::"+className;
+
+ nsmap.value().insert(className,(*child));
+ nqcmap.value().insert(className,(*child));
+ }
+ else if ((*child)->type() == Node::QmlProperty) {
+ // Insert QML properties into the since map.
+ QString propertyName = (*child)->name();
+ nsmap.value().insert(propertyName,(*child));
}
}
- ++f;
- }
- ++n;
- }
+ else {
+ // Insert external documents into the general since map.
+ QString name = (*child)->name();
+ if ((*child)->parent() &&
+ (*child)->parent()->type() == Node::Namespace &&
+ !(*child)->parent()->name().isEmpty())
+ name = (*child)->parent()->name()+"::"+name;
- project = config.getString(CONFIG_PROJECT);
+ nsmap.value().insert(name,(*child));
+ }
- QStringList prefixes = config.getStringList(CONFIG_OUTPUTPREFIXES);
- if (!prefixes.isEmpty()) {
- foreach (QString prefix, prefixes)
- outputPrefixes[prefix] = config.getString(
- CONFIG_OUTPUTPREFIXES + Config::dot + prefix);
- } else
- outputPrefixes[QLatin1String("QML")] = QLatin1String("qml-");
+ // Find child nodes with since commands.
+ if ((*child)->isInnerNode()) {
+ findAllSince(static_cast<InnerNode *>(*child));
+ }
+ }
+ ++child;
+ }
}
-void Generator::terminate()
+QMap<QString, QString>& Generator::formattingLeftMap()
{
- QList<Generator *>::ConstIterator g = generators.begin();
- while (g != generators.end()) {
- if (outputFormats.contains((*g)->format()))
- (*g)->terminateGenerator();
- ++g;
- }
-
- fmtLeftMaps.clear();
- fmtRightMaps.clear();
- imgFileExts.clear();
- imageFiles.clear();
- imageDirs.clear();
- outDir_ = "";
- QmlClassNode::terminate();
- ExampleNode::terminate();
+ return fmtLeftMaps[format()];
}
-Generator *Generator::generatorForFormat(const QString& format)
+QMap<QString, QString>& Generator::formattingRightMap()
{
- QList<Generator *>::ConstIterator g = generators.begin();
- while (g != generators.end()) {
- if ((*g)->format() == format)
- return *g;
- ++g;
- }
- return 0;
+ return fmtRightMaps[format()];
}
-void Generator::startText(const Node * /* relative */,
- CodeMarker * /* marker */)
+QString Generator::fullName(const Node *node,
+ const Node *relative,
+ CodeMarker *marker) const
{
+ if (node->type() == Node::Fake) {
+ const FakeNode* fn = static_cast<const FakeNode *>(node);
+#if 0
+ // Removed for QTBUG-22870
+ if (!fn->qmlModuleIdentifier().isEmpty())
+ return fn->qmlModuleIdentifier() + QLatin1Char(' ') + fn->title();
+#endif
+ return fn->title();
+ }
+ else if (node->type() == Node::Class &&
+ !(static_cast<const ClassNode *>(node))->serviceName().isEmpty())
+ return (static_cast<const ClassNode *>(node))->serviceName();
+ else
+ return marker->plainFullName(node, relative);
}
-void Generator::endText(const Node * /* relative */,
- CodeMarker * /* marker */)
+void Generator::generateAlsoList(const Node *node, CodeMarker *marker)
{
+ QList<Text> alsoList = node->doc().alsoList();
+ supplementAlsoList(node, alsoList);
+
+ if (!alsoList.isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
+ << "See also "
+ << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
+
+ for (int i = 0; i < alsoList.size(); ++i)
+ text << alsoList.at(i) << separator(i, alsoList.size());
+
+ text << Atom::ParaRight;
+ generateText(text, node, marker);
+ }
}
int Generator::generateAtom(const Atom * /* atom */,
@@ -358,68 +486,65 @@ int Generator::generateAtom(const Atom * /* atom */,
return 0;
}
-void Generator::generateClassLikeNode(const InnerNode * /* classe */,
- CodeMarker * /* marker */)
-{
-}
-
-void Generator::generateFakeNode(const FakeNode * /* fake */,
- CodeMarker * /* marker */)
-{
-}
-
-bool Generator::generateText(const Text& text,
- const Node *relative,
- CodeMarker *marker)
+const Atom *Generator::generateAtomList(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker,
+ bool generate,
+ int &numAtoms)
{
- bool result = false;
- if (text.firstAtom() != 0) {
- int numAtoms = 0;
- startText(relative, marker);
- generateAtomList(text.firstAtom(),
- relative,
- marker,
- true,
- numAtoms);
- endText(relative, marker);
- result = true;
- }
- return result;
-}
+ while (atom) {
+ if (atom->type() == Atom::FormatIf) {
+ int numAtoms0 = numAtoms;
+ bool rightFormat = canHandleFormat(atom->string());
+ atom = generateAtomList(atom->next(),
+ relative,
+ marker,
+ generate && rightFormat,
+ numAtoms);
+ if (!atom)
+ return 0;
-#ifdef QDOC_QML
-/*!
- Extract sections of markup text surrounded by \e qmltext
- and \e endqmltext and output them.
- */
-bool Generator::generateQmlText(const Text& text,
- const Node *relative,
- CodeMarker *marker,
- const QString& /* qmlName */ )
-{
- const Atom* atom = text.firstAtom();
- bool result = false;
+ if (atom->type() == Atom::FormatElse) {
+ ++numAtoms;
+ atom = generateAtomList(atom->next(),
+ relative,
+ marker,
+ generate && !rightFormat,
+ numAtoms);
+ if (!atom)
+ return 0;
+ }
- if (atom != 0) {
- startText(relative, marker);
- while (atom) {
- if (atom->type() != Atom::QmlText)
- atom = atom->next();
- else {
- atom = atom->next();
- while (atom && (atom->type() != Atom::EndQmlText)) {
- int n = 1 + generateAtom(atom, relative, marker);
- while (n-- > 0)
- atom = atom->next();
+ if (atom->type() == Atom::FormatEndif) {
+ if (generate && numAtoms0 == numAtoms) {
+ relative->location().warning(tr("Output format %1 not handled %2")
+ .arg(format()).arg(outFileName()));
+ Atom unhandledFormatAtom(Atom::UnhandledFormat, format());
+ generateAtomList(&unhandledFormatAtom,
+ relative,
+ marker,
+ generate,
+ numAtoms);
}
+ atom = atom->next();
}
}
- endText(relative, marker);
- result = true;
+ else if (atom->type() == Atom::FormatElse ||
+ atom->type() == Atom::FormatEndif) {
+ return atom;
+ }
+ else {
+ int n = 1;
+ if (generate) {
+ n += generateAtom(atom, relative, marker);
+ numAtoms += n;
+ }
+ while (n-- > 0)
+ atom = atom->next();
+ }
}
- return result;
+ return 0;
}
-#endif
void Generator::generateBody(const Node *node, CodeMarker *marker)
{
@@ -568,105 +693,22 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
}
}
-void Generator::generateAlsoList(const Node *node, CodeMarker *marker)
-{
- QList<Text> alsoList = node->doc().alsoList();
- supplementAlsoList(node, alsoList);
-
- if (!alsoList.isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "See also "
- << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
-
- for (int i = 0; i < alsoList.size(); ++i)
- text << alsoList.at(i) << separator(i, alsoList.size());
-
- text << Atom::ParaRight;
- generateText(text, node, marker);
- }
-}
-
-/*!
- Generate a list of maintainers in the output
- */
-void Generator::generateMaintainerList(const InnerNode* node, CodeMarker* marker)
-{
- QStringList sl = getMetadataElements(node,"maintainer");
-
- if (!sl.isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "Maintained by: "
- << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
-
- for (int i = 0; i < sl.size(); ++i)
- text << sl.at(i) << separator(i, sl.size());
-
- text << Atom::ParaRight;
- generateText(text, node, marker);
- }
-}
-
-void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
+void Generator::generateClassLikeNode(const InnerNode * /* classe */,
+ CodeMarker * /* marker */)
{
- QList<RelatedClass>::ConstIterator r;
- int index;
-
- if (!classe->baseClasses().isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "Inherits: "
- << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
-
- r = classe->baseClasses().begin();
- index = 0;
- while (r != classe->baseClasses().end()) {
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
-
- if ((*r).access == Node::Protected) {
- text << " (protected)";
- }
- else if ((*r).access == Node::Private) {
- text << " (private)";
- }
- text << separator(index++, classe->baseClasses().count());
- ++r;
- }
- text << Atom::ParaRight;
- generateText(text, classe, marker);
- }
}
-#ifdef QDOC_QML
-/*!
- */
-void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* )
+void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker)
{
- // stub.
+ if (fake->childNodes().isEmpty())
+ return;
+ generateFileList(fake, marker, Node::File, QString("Files:"));
+ generateFileList(fake, marker, Node::Image, QString("Images:"));
}
-#endif
-void Generator::generateInheritedBy(const ClassNode *classe,
- CodeMarker *marker)
+void Generator::generateFakeNode(const FakeNode * /* fake */,
+ CodeMarker * /* marker */)
{
- if (!classe->derivedClasses().isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "Inherited by: "
- << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
-
- appendSortedNames(text, classe, classe->derivedClasses(), marker);
- text << Atom::ParaRight;
- generateText(text, classe, marker);
- }
}
/*!
@@ -734,193 +776,250 @@ void Generator::generateFileList(const FakeNode* fake,
generateText(text, fake, marker);
}
-void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker)
+void Generator::generateInheritedBy(const ClassNode *classe,
+ CodeMarker *marker)
{
- if (fake->childNodes().isEmpty())
- return;
- generateFileList(fake, marker, Node::File, QString("Files:"));
- generateFileList(fake, marker, Node::Image, QString("Images:"));
+ if (!classe->derivedClasses().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
+ << "Inherited by: "
+ << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
+
+ appendSortedNames(text, classe, classe->derivedClasses(), marker);
+ text << Atom::ParaRight;
+ generateText(text, classe, marker);
+ }
}
-QString Generator::indent(int level, const QString& markedCode)
+void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
{
- if (level == 0)
- return markedCode;
+ QList<RelatedClass>::ConstIterator r;
+ int index;
- QString t;
- int column = 0;
+ if (!classe->baseClasses().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
+ << "Inherits: "
+ << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
- int i = 0;
- while (i < (int) markedCode.length()) {
- if (markedCode.at(i) == QLatin1Char('\n')) {
- column = 0;
- }
- else {
- if (column == 0) {
- for (int j = 0; j < level; j++)
- t += QLatin1Char(' ');
+ r = classe->baseClasses().begin();
+ index = 0;
+ while (r != classe->baseClasses().end()) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access == Node::Protected) {
+ text << " (protected)";
}
- column++;
+ else if ((*r).access == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
+ ++r;
}
- t += markedCode.at(i++);
+ text << Atom::ParaRight;
+ generateText(text, classe, marker);
}
- return t;
}
-QString Generator::plainCode(const QString& markedCode)
-{
- QString t = markedCode;
- t.replace(tag, QString());
- t.replace(quot, QLatin1String("\""));
- t.replace(gt, QLatin1String(">"));
- t.replace(lt, QLatin1String("<"));
- t.replace(amp, QLatin1String("&"));
- return t;
-}
+/*!
+ Recursive writing of HTML files from the root \a node.
-QString Generator::typeString(const Node *node)
+ \note NameCollisionNodes are skipped here and processed
+ later. See HtmlGenerator::generateDisambiguationPages()
+ for more on this.
+ */
+void Generator::generateInnerNode(const InnerNode* node)
{
- switch (node->type()) {
- case Node::Namespace:
- return "namespace";
- case Node::Class:
- return "class";
- case Node::Fake:
- {
- switch (node->subType()) {
- case Node::QmlClass:
- return "element";
- case Node::QmlPropertyGroup:
- return "property group";
- case Node::QmlBasicType:
- return "type";
- default:
- return "documentation";
+ if (!node->url().isNull())
+ return;
+
+ if (node->type() == Node::Fake) {
+ const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
+ if (fakeNode->subType() == Node::ExternalPage)
+ return;
+ if (fakeNode->subType() == Node::Image)
+ return;
+ if (fakeNode->subType() == Node::QmlPropertyGroup)
+ return;
+ if (fakeNode->subType() == Node::Page) {
+ if (node->count() > 0)
+ qDebug("PAGE %s HAS CHILDREN", qPrintable(fakeNode->title()));
}
}
- case Node::Enum:
- return "enum";
- case Node::Typedef:
- return "typedef";
- case Node::Function:
- return "function";
- case Node::Property:
- return "property";
- default:
- return "documentation";
+
+ /*
+ Obtain a code marker for the source file.
+ */
+ CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
+
+ if (node->parent() != 0) {
+ /*
+ Skip name collision nodes here and process them
+ later in generateDisambiguationPages(). Each one
+ is appended to a list for later.
+ */
+ if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) {
+ const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
+ collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
+ }
+ else {
+ beginSubPage(node, fileName(node));
+ if (node->type() == Node::Namespace || node->type() == Node::Class) {
+ generateClassLikeNode(node, marker);
+ }
+ else if (node->type() == Node::Fake) {
+ generateFakeNode(static_cast<const FakeNode *>(node), marker);
+ }
+ endSubPage();
+ }
+ }
+
+ NodeList::ConstIterator c = node->childNodes().begin();
+ while (c != node->childNodes().end()) {
+ if ((*c)->isInnerNode() && (*c)->access() != Node::Private) {
+ generateInnerNode((const InnerNode *) *c);
+ }
+ ++c;
}
}
/*!
- Returns a relative path name for an image.
+ Generate a list of maintainers in the output
*/
-QString Generator::imageFileName(const Node *relative, const QString& fileBase)
+void Generator::generateMaintainerList(const InnerNode* node, CodeMarker* marker)
{
- QString userFriendlyFilePath;
- QString filePath = Config::findFile(
- relative->doc().location(), imageFiles, imageDirs, fileBase,
- imgFileExts[format()], userFriendlyFilePath);
+ QStringList sl = getMetadataElements(node,"maintainer");
- if (filePath.isEmpty())
- return QString();
+ if (!sl.isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
+ << "Maintained by: "
+ << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
- QString path = Config::copyFile(relative->doc().location(),
- filePath,
- userFriendlyFilePath,
- outputDir() + QLatin1String("/images"));
- QString images = "images";
- if (path[0] != '/')
- images.append(QLatin1Char('/'));
- return images + path;
-}
+ for (int i = 0; i < sl.size(); ++i)
+ text << sl.at(i) << separator(i, sl.size());
-void Generator::setImageFileExtensions(const QStringList& extensions)
-{
- imgFileExts[format()] = extensions;
+ text << Atom::ParaRight;
+ generateText(text, node, marker);
+ }
}
-void Generator::unknownAtom(const Atom *atom)
+#ifdef QDOC_QML
+/*!
+ Output the "Inherit by" list for the QML element,
+ if it is inherited by any other elements.
+ */
+void Generator::generateQmlInheritedBy(const QmlClassNode* qcn,
+ CodeMarker* marker)
{
- Location::internalError(tr("unknown atom type '%1' in %2 generator")
- .arg(atom->typeString()).arg(format()));
+ if (qcn) {
+ NodeList subs;
+ QmlClassNode::subclasses(qcn->name(),subs);
+ if (!subs.isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft << "Inherited by ";
+ appendSortedQmlNames(text,qcn,subs,marker);
+ text << Atom::ParaRight;
+ generateText(text, qcn, marker);
+ }
+ }
}
+#endif
-bool Generator::matchAhead(const Atom *atom, Atom::Type expectedAtomType)
+#ifdef QDOC_QML
+/*!
+ */
+void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* )
{
- return atom->next() != 0 && atom->next()->type() == expectedAtomType;
+ // stub.
}
+#endif
-void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)
+#ifdef QDOC_QML
+/*!
+ Extract sections of markup text surrounded by \e qmltext
+ and \e endqmltext and output them.
+ */
+bool Generator::generateQmlText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker,
+ const QString& /* qmlName */ )
{
- if (node->type() == Node::Function) {
- const FunctionNode *func = static_cast<const FunctionNode *>(node);
- if (func->overloadNumber() == 1) {
- QString alternateName;
- const FunctionNode *alternateFunc = 0;
-
- if (func->name().startsWith("set") && func->name().size() >= 4) {
- alternateName = func->name()[3].toLower();
- alternateName += func->name().mid(4);
- alternateFunc = func->parent()->findFunctionNode(alternateName);
-
- if (!alternateFunc) {
- alternateName = "is" + func->name().mid(3);
- alternateFunc = func->parent()->findFunctionNode(alternateName);
- if (!alternateFunc) {
- alternateName = "has" + func->name().mid(3);
- alternateFunc = func->parent()->findFunctionNode(alternateName);
- }
- }
- }
- else if (!func->name().isEmpty()) {
- alternateName = "set";
- alternateName += func->name()[0].toUpper();
- alternateName += func->name().mid(1);
- alternateFunc = func->parent()->findFunctionNode(alternateName);
- }
-
- if (alternateFunc && alternateFunc->access() != Node::Private) {
- int i;
- for (i = 0; i < alsoList.size(); ++i) {
- if (alsoList.at(i).toString().contains(alternateName))
- break;
- }
-
- if (i == alsoList.size()) {
- alternateName += "()";
+ const Atom* atom = text.firstAtom();
+ bool result = false;
- Text also;
- also << Atom(Atom::Link, alternateName)
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << alternateName
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
- alsoList.prepend(also);
+ if (atom != 0) {
+ startText(relative, marker);
+ while (atom) {
+ if (atom->type() != Atom::QmlText)
+ atom = atom->next();
+ else {
+ atom = atom->next();
+ while (atom && (atom->type() != Atom::EndQmlText)) {
+ int n = 1 + generateAtom(atom, relative, marker);
+ while (n-- > 0)
+ atom = atom->next();
}
}
}
+ endText(relative, marker);
+ result = true;
}
+ return result;
}
+#endif
-QMap<QString, QString>& Generator::formattingLeftMap()
+void Generator::generateReimplementedFrom(const FunctionNode *func,
+ CodeMarker *marker)
{
- return fmtLeftMaps[format()];
+ if (func->reimplementedFrom() != 0) {
+ const FunctionNode *from = func->reimplementedFrom();
+ if (from->access() != Node::Private &&
+ from->parent()->access() != Node::Private) {
+ Text text;
+ text << Atom::ParaLeft << "Reimplemented from ";
+ QString fullName = from->parent()->name() + "::" + from->name() + "()";
+ appendFullName(text, from->parent(), fullName, from);
+ text << "." << Atom::ParaRight;
+ generateText(text, func, marker);
+ }
+ }
}
-QMap<QString, QString>& Generator::formattingRightMap()
+void Generator::generateSince(const Node *node, CodeMarker *marker)
{
- return fmtRightMaps[format()];
-}
+ if (!node->since().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << "This "
+ << typeString(node);
+ if (node->type() == Node::Enum)
+ text << " was introduced or modified in ";
+ else
+ text << " was introduced in ";
-/*
- Trims trailimng whitespace off the \a string and returns
- the trimmed string.
- */
-QString Generator::trimmedTrailing(const QString& string)
-{
- QString trimmed = string;
- while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace())
- trimmed.truncate(trimmed.length() - 1);
- return trimmed;
+ QStringList since = node->since().split(QLatin1Char(' '));
+ if (since.count() == 1) {
+ // Handle legacy use of \since <version>.
+ if (project.isEmpty())
+ text << "version";
+ else
+ text << project;
+ text << " " << since[0];
+ } else {
+ // Reconstruct the <project> <version> string.
+ text << " " << since.join(" ");
+ }
+
+ text << "." << Atom::ParaRight;
+ generateText(text, node, marker);
+ }
}
void Generator::generateStatus(const Node *node, CodeMarker *marker)
@@ -984,10 +1083,28 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker)
generateText(text, node, marker);
}
+bool Generator::generateText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker)
+{
+ bool result = false;
+ if (text.firstAtom() != 0) {
+ int numAtoms = 0;
+ startText(relative, marker);
+ generateAtomList(text.firstAtom(),
+ relative,
+ marker,
+ true,
+ numAtoms);
+ endText(relative, marker);
+ result = true;
+ }
+ return result;
+}
+
void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
{
Text text;
- Text theStockLink;
Node::ThreadSafeness threadSafeness = node->threadSafeness();
Text rlink;
@@ -1125,208 +1242,438 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
generateText(text,node,marker);
}
-void Generator::generateSince(const Node *node, CodeMarker *marker)
+/*!
+ This function is recursive.
+ */
+void Generator::generateTree(const Tree *tree)
{
- if (!node->since().isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << "This "
- << typeString(node);
- if (node->type() == Node::Enum)
- text << " was introduced or modified in ";
- else
- text << " was introduced in ";
+ generateInnerNode(tree->root());
+}
- QStringList since = node->since().split(QLatin1Char(' '));
- if (since.count() == 1) {
- // Handle legacy use of \since <version>.
- if (project.isEmpty())
- text << "version";
- else
- text << project;
- text << " " << since[0];
- } else {
- // Reconstruct the <project> <version> string.
- text << " " << since.join(" ");
- }
+Generator *Generator::generatorForFormat(const QString& format)
+{
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if ((*g)->format() == format)
+ return *g;
+ ++g;
+ }
+ return 0;
+}
- text << "." << Atom::ParaRight;
- generateText(text, node, marker);
+/*!
+ Looks up the tag \a t in the map of metadata values for the
+ current topic in \a inner. If a value for the tag is found,
+ the value is returned.
+
+ \note If \a t is found in the metadata map, it is erased.
+ i.e. Once you call this function for a particular \a t,
+ you consume \a t.
+ */
+QString Generator::getMetadataElement(const InnerNode* inner, const QString& t)
+{
+ QString s;
+ QStringMultiMap& metaTagMap = const_cast<QStringMultiMap&>(inner->doc().metaTagMap());
+ QStringMultiMap::iterator i = metaTagMap.find(t);
+ if (i != metaTagMap.end()) {
+ s = i.value();
+ metaTagMap.erase(i);
}
+ return s;
}
-void Generator::generateReimplementedFrom(const FunctionNode *func,
- CodeMarker *marker)
+/*!
+ Looks up the tag \a t in the map of metadata values for the
+ current topic in \a inner. If values for the tag are found,
+ they are returned in a string list.
+
+ \note If \a t is found in the metadata map, all the pairs
+ having the key \a t are erased. i.e. Once you call this
+ function for a particular \a t, you consume \a t.
+ */
+QStringList Generator::getMetadataElements(const InnerNode* inner, const QString& t)
{
- if (func->reimplementedFrom() != 0) {
- const FunctionNode *from = func->reimplementedFrom();
- if (from->access() != Node::Private &&
- from->parent()->access() != Node::Private) {
- Text text;
- text << Atom::ParaLeft << "Reimplemented from ";
- QString fullName = from->parent()->name() + "::" + from->name() + "()";
- appendFullName(text, from->parent(), fullName, from);
- text << "." << Atom::ParaRight;
- generateText(text, func, marker);
+ QStringList s;
+ QStringMultiMap& metaTagMap = const_cast<QStringMultiMap&>(inner->doc().metaTagMap());
+ s = metaTagMap.values(t);
+ if (!s.isEmpty())
+ metaTagMap.remove(t);
+ return s;
+}
+
+/*!
+ Returns a relative path name for an image.
+ */
+QString Generator::imageFileName(const Node *relative, const QString& fileBase)
+{
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(
+ relative->doc().location(), imageFiles, imageDirs, fileBase,
+ imgFileExts[format()], userFriendlyFilePath);
+
+ if (filePath.isEmpty())
+ return QString();
+
+ QString path = Config::copyFile(relative->doc().location(),
+ filePath,
+ userFriendlyFilePath,
+ outputDir() + QLatin1String("/images"));
+ QString images = "images";
+ if (path[0] != '/')
+ images.append(QLatin1Char('/'));
+ return images + path;
+}
+
+QString Generator::indent(int level, const QString& markedCode)
+{
+ if (level == 0)
+ return markedCode;
+
+ QString t;
+ int column = 0;
+
+ int i = 0;
+ while (i < (int) markedCode.length()) {
+ if (markedCode.at(i) == QLatin1Char('\n')) {
+ column = 0;
}
+ else {
+ if (column == 0) {
+ for (int j = 0; j < level; j++)
+ t += QLatin1Char(' ');
+ }
+ column++;
+ }
+ t += markedCode.at(i++);
}
+ return t;
}
-const Atom *Generator::generateAtomList(const Atom *atom,
- const Node *relative,
- CodeMarker *marker,
- bool generate,
- int &numAtoms)
+void Generator::initialize(const Config &config)
{
- while (atom) {
- if (atom->type() == Atom::FormatIf) {
- int numAtoms0 = numAtoms;
- bool rightFormat = canHandleFormat(atom->string());
- atom = generateAtomList(atom->next(),
- relative,
- marker,
- generate && rightFormat,
- numAtoms);
- if (!atom)
- return 0;
+ outputFormats = config.getOutputFormats();
+ if (!outputFormats.isEmpty()) {
+ outDir_ = config.getOutputDir();
+ baseDir_ = config.getString(CONFIG_BASEDIR);
+ if (!baseDir_.isEmpty())
+ config.location().warning(tr("\"basedir\" specified in config file. "
+ "All output will be in module directories of the output directory"));
+ if (outDir_.isEmpty())
+ config.lastLocation().fatal(tr("No output directory specified in configuration file or on the command line"));
- if (atom->type() == Atom::FormatElse) {
- ++numAtoms;
- atom = generateAtomList(atom->next(),
- relative,
- marker,
- generate && !rightFormat,
- numAtoms);
- if (!atom)
- return 0;
+ QDir dirInfo;
+ if (dirInfo.exists(outDir_)) {
+ if (!Config::removeDirContents(outDir_))
+ config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir_));
+ }
+ else {
+ if (!dirInfo.mkpath(outDir_))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_));
+ }
+
+ if (!dirInfo.mkdir(outDir_ + "/images"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir_ + "/images"));
+ if (!dirInfo.mkdir(outDir_ + "/images/used-in-examples"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir_ + "/images/used-in-examples"));
+ if (!dirInfo.mkdir(outDir_ + "/scripts"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir_ + "/scripts"));
+ if (!dirInfo.mkdir(outDir_ + "/style"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir_ + "/style"));
+ }
+
+ imageFiles = config.getCleanPathList(CONFIG_IMAGES);
+ imageDirs = config.getCleanPathList(CONFIG_IMAGEDIRS);
+ scriptFiles = config.getCleanPathList(CONFIG_SCRIPTS);
+ scriptDirs = config.getCleanPathList(CONFIG_SCRIPTDIRS);
+ styleFiles = config.getCleanPathList(CONFIG_STYLES);
+ styleDirs = config.getCleanPathList(CONFIG_STYLEDIRS);
+ exampleDirs = config.getCleanPathList(CONFIG_EXAMPLEDIRS);
+ exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot +
+ CONFIG_IMAGEEXTENSIONS);
+
+ QString imagesDotFileExtensions =
+ CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS;
+ QSet<QString> formats = config.subVars(imagesDotFileExtensions);
+ QSet<QString>::ConstIterator f = formats.begin();
+ while (f != formats.end()) {
+ imgFileExts[*f] = config.getStringList(imagesDotFileExtensions +
+ Config::dot + *f);
+ ++f;
+ }
+
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if (outputFormats.contains((*g)->format())) {
+ (*g)->initializeGenerator(config);
+ QStringList extraImages =
+ config.getCleanPathList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format());
+ QStringList::ConstIterator e = extraImages.begin();
+ while (e != extraImages.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(),
+ imageFiles,
+ imageDirs,
+ *e,
+ imgFileExts[(*g)->format()],
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/images");
+ ++e;
}
- if (atom->type() == Atom::FormatEndif) {
- if (generate && numAtoms0 == numAtoms) {
- relative->location().warning(tr("Output format %1 not handled %2")
- .arg(format()).arg(outFileName()));
- Atom unhandledFormatAtom(Atom::UnhandledFormat, format());
- generateAtomList(&unhandledFormatAtom,
- relative,
- marker,
- generate,
- numAtoms);
+ // Documentation template handling
+ QString templateDir = config.getString(
+ (*g)->format() + Config::dot + CONFIG_TEMPLATEDIR);
+
+ if (!templateDir.isEmpty()) {
+ QStringList noExts;
+ QStringList searchDirs = QStringList() << templateDir;
+ QStringList scripts =
+ config.getCleanPathList((*g)->format()+Config::dot+CONFIG_SCRIPTS);
+ e = scripts.begin();
+ while (e != scripts.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(),
+ scriptFiles,
+ searchDirs,
+ *e,
+ noExts,
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/scripts");
+ ++e;
+ }
+
+ QStringList styles =
+ config.getCleanPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS);
+ e = styles.begin();
+ while (e != styles.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(),
+ styleFiles,
+ searchDirs,
+ *e,
+ noExts,
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/style");
+ ++e;
}
- atom = atom->next();
}
}
- else if (atom->type() == Atom::FormatElse ||
- atom->type() == Atom::FormatEndif) {
- return atom;
- }
- else {
- int n = 1;
- if (generate) {
- n += generateAtom(atom, relative, marker);
- numAtoms += n;
+ ++g;
+ }
+
+ QRegExp secondParamAndAbove("[\2-\7]");
+ QSet<QString> formattingNames = config.subVars(CONFIG_FORMATTING);
+ QSet<QString>::ConstIterator n = formattingNames.begin();
+ while (n != formattingNames.end()) {
+ QString formattingDotName = CONFIG_FORMATTING + Config::dot + *n;
+
+ QSet<QString> formats = config.subVars(formattingDotName);
+ QSet<QString>::ConstIterator f = formats.begin();
+ while (f != formats.end()) {
+ QString def = config.getString(formattingDotName +
+ Config::dot + *f);
+ if (!def.isEmpty()) {
+ int numParams = Config::numParams(def);
+ int numOccs = def.count("\1");
+
+ if (numParams != 1) {
+ config.lastLocation().warning(tr("Formatting '%1' must "
+ "have exactly one "
+ "parameter (found %2)")
+ .arg(*n).arg(numParams));
+ }
+ else if (numOccs > 1) {
+ config.lastLocation().fatal(tr("Formatting '%1' must "
+ "contain exactly one "
+ "occurrence of '\\1' "
+ "(found %2)")
+ .arg(*n).arg(numOccs));
+ }
+ else {
+ int paramPos = def.indexOf("\1");
+ fmtLeftMaps[*f].insert(*n, def.left(paramPos));
+ fmtRightMaps[*f].insert(*n, def.mid(paramPos + 1));
+ }
}
- while (n-- > 0)
- atom = atom->next();
+ ++f;
}
+ ++n;
}
- return 0;
+
+ project = config.getString(CONFIG_PROJECT);
+
+ QStringList prefixes = config.getStringList(CONFIG_OUTPUTPREFIXES);
+ if (!prefixes.isEmpty()) {
+ foreach (QString prefix, prefixes)
+ outputPrefixes[prefix] = config.getString(
+ CONFIG_OUTPUTPREFIXES + Config::dot + prefix);
+ } else
+ outputPrefixes[QLatin1String("QML")] = QLatin1String("qml-");
}
-void Generator::appendFullName(Text& text,
- const Node *apparentNode,
- const Node *relative,
- CodeMarker *marker,
- const Node *actualNode)
+void Generator::initializeGenerator(const Config & /* config */)
{
- if (actualNode == 0)
- actualNode = apparentNode;
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, marker->plainFullName(apparentNode, relative))
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
-void Generator::appendFullName(Text& text,
- const Node *apparentNode,
- const QString& fullName,
- const Node *actualNode)
+bool Generator::matchAhead(const Atom *atom, Atom::Type expectedAtomType)
{
- if (actualNode == 0)
- actualNode = apparentNode;
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, fullName)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ return atom->next() != 0 && atom->next()->type() == expectedAtomType;
}
-void Generator::appendFullNames(Text& text,
- const NodeList& nodes,
- const Node* relative,
- CodeMarker* marker)
+/*!
+ Used for writing to the current output stream. Returns a
+ reference to the current output stream, which is then used
+ with the \c {<<} operator for writing.
+ */
+QTextStream &Generator::out()
{
- NodeList::ConstIterator n = nodes.begin();
- int index = 0;
- while (n != nodes.end()) {
- appendFullName(text,*n,relative,marker);
- text << comma(index++,nodes.count());
- ++n;
- }
+ return *outStreamStack.top();
}
-void Generator::appendSortedNames(Text& text,
- const ClassNode *classe,
- const QList<RelatedClass> &classes,
- CodeMarker *marker)
+QString Generator::outputPrefix(const QString &nodeType)
{
- QList<RelatedClass>::ConstIterator r;
- QMap<QString,Text> classMap;
- int index = 0;
+ return outputPrefixes[nodeType];
+}
- r = classes.begin();
- while (r != classes.end()) {
- if ((*r).node->access() == Node::Public &&
- (*r).node->status() != Node::Internal
- && !(*r).node->doc().isEmpty()) {
- Text className;
- appendFullName(className, (*r).node, classe, marker);
- classMap[className.toString().toLower()] = className;
+bool Generator::parseArg(const QString& src,
+ const QString& tag,
+ int* pos,
+ int n,
+ QStringRef* contents,
+ QStringRef* par1,
+ bool debug)
+{
+#define SKIP_CHAR(c) \
+ if (debug) \
+ qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \
+ if (i >= n || src[i] != c) { \
+ if (debug) \
+ qDebug() << " char '" << c << "' not found"; \
+ return false; \
+} \
+ ++i;
+
+
+#define SKIP_SPACE \
+ while (i < n && src[i] == ' ') \
+ ++i;
+
+ int i = *pos;
+ int j = i;
+
+ // assume "<@" has been parsed outside
+ //SKIP_CHAR('<');
+ //SKIP_CHAR('@');
+
+ if (tag != QStringRef(&src, i, tag.length())) {
+ if (0 && debug)
+ qDebug() << "tag " << tag << " not found at " << i;
+ return false;
+ }
+
+ if (debug)
+ qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i;
+
+ // skip tag
+ i += tag.length();
+
+ // parse stuff like: linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
+ if (par1) {
+ SKIP_SPACE;
+ // read parameter name
+ j = i;
+ while (i < n && src[i].isLetter())
+ ++i;
+ if (src[i] == '=') {
+ if (debug)
+ qDebug() << "read parameter" << QString(src.data() + j, i - j);
+ SKIP_CHAR('=');
+ SKIP_CHAR('"');
+ // skip parameter name
+ j = i;
+ while (i < n && src[i] != '"')
+ ++i;
+ *par1 = QStringRef(&src, j, i - j);
+ SKIP_CHAR('"');
+ SKIP_SPACE;
+ } else {
+ if (debug)
+ qDebug() << "no optional parameter found";
}
- ++r;
+ }
+ SKIP_SPACE;
+ SKIP_CHAR('>');
+
+ // find contents up to closing "</@tag>
+ j = i;
+ for (; true; ++i) {
+ if (i + 4 + tag.length() > n)
+ return false;
+ if (src[i] != '<')
+ continue;
+ if (src[i + 1] != '/')
+ continue;
+ if (src[i + 2] != '@')
+ continue;
+ if (tag != QStringRef(&src, i + 3, tag.length()))
+ continue;
+ if (src[i + 3 + tag.length()] != '>')
+ continue;
+ break;
}
- QStringList classNames = classMap.keys();
- classNames.sort();
+ *contents = QStringRef(&src, j, i - j);
- foreach (const QString &className, classNames) {
- text << classMap[className];
- text << separator(index++, classNames.count());
- }
+ i += tag.length() + 4;
+
+ *pos = i;
+ if (debug)
+ qDebug() << " tag " << tag << " found: pos now: " << i;
+ return true;
+#undef SKIP_CHAR
}
-void Generator::appendSortedQmlNames(Text& text,
- const Node* base,
- const NodeList& subs,
- CodeMarker *marker)
+QString Generator::plainCode(const QString& markedCode)
{
- QMap<QString,Text> classMap;
- int index = 0;
-
- for (int i = 0; i < subs.size(); ++i) {
- Text t;
- if (!base->isQtQuickNode() || !subs[i]->isQtQuickNode() ||
- (base->qmlModuleIdentifier() == subs[i]->qmlModuleIdentifier())) {
- appendFullName(t, subs[i], base, marker);
- classMap[t.toString().toLower()] = t;
- }
- }
+ QString t = markedCode;
+ t.replace(tag, QString());
+ t.replace(quot, QLatin1String("\""));
+ t.replace(gt, QLatin1String(">"));
+ t.replace(lt, QLatin1String("<"));
+ t.replace(amp, QLatin1String("&"));
+ return t;
+}
- QStringList names = classMap.keys();
- names.sort();
+void Generator::setImageFileExtensions(const QStringList& extensions)
+{
+ imgFileExts[format()] = extensions;
+}
- foreach (const QString &name, names) {
- text << classMap[name];
- text << separator(index++, names.count());
- }
+void Generator::singularPlural(Text& text, const NodeList& nodes)
+{
+ if (nodes.count() == 1)
+ text << " is";
+ else
+ text << " are";
}
int Generator::skipAtoms(const Atom *atom, Atom::Type type) const
@@ -1340,156 +1687,134 @@ int Generator::skipAtoms(const Atom *atom, Atom::Type type) const
return skipAhead;
}
-QString Generator::fullName(const Node *node,
- const Node *relative,
- CodeMarker *marker) const
+void Generator::startText(const Node * /* relative */,
+ CodeMarker * /* marker */)
{
- if (node->type() == Node::Fake) {
- const FakeNode* fn = static_cast<const FakeNode *>(node);
-#if 0
- // Removed for QTBUG-22870
- if (!fn->qmlModuleIdentifier().isEmpty())
- return fn->qmlModuleIdentifier() + QLatin1Char(' ') + fn->title();
-#endif
- return fn->title();
- }
- else if (node->type() == Node::Class &&
- !(static_cast<const ClassNode *>(node))->serviceName().isEmpty())
- return (static_cast<const ClassNode *>(node))->serviceName();
- else
- return marker->plainFullName(node, relative);
}
-QString Generator::outputPrefix(const QString &nodeType)
+void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)
{
- return outputPrefixes[nodeType];
-}
+ if (node->type() == Node::Function) {
+ const FunctionNode *func = static_cast<const FunctionNode *>(node);
+ if (func->overloadNumber() == 1) {
+ QString alternateName;
+ const FunctionNode *alternateFunc = 0;
-/*!
- Looks up the tag \a t in the map of metadata values for the
- current topic in \a inner. If a value for the tag is found,
- the value is returned.
+ if (func->name().startsWith("set") && func->name().size() >= 4) {
+ alternateName = func->name()[3].toLower();
+ alternateName += func->name().mid(4);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
- \note If \a t is found in the metadata map, it is erased.
- i.e. Once you call this function for a particular \a t,
- you consume \a t.
- */
-QString Generator::getMetadataElement(const InnerNode* inner, const QString& t)
-{
- QString s;
- QStringMultiMap& metaTagMap = const_cast<QStringMultiMap&>(inner->doc().metaTagMap());
- QStringMultiMap::iterator i = metaTagMap.find(t);
- if (i != metaTagMap.end()) {
- s = i.value();
- metaTagMap.erase(i);
+ if (!alternateFunc) {
+ alternateName = "is" + func->name().mid(3);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ if (!alternateFunc) {
+ alternateName = "has" + func->name().mid(3);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ }
+ }
+ }
+ else if (!func->name().isEmpty()) {
+ alternateName = "set";
+ alternateName += func->name()[0].toUpper();
+ alternateName += func->name().mid(1);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ }
+
+ if (alternateFunc && alternateFunc->access() != Node::Private) {
+ int i;
+ for (i = 0; i < alsoList.size(); ++i) {
+ if (alsoList.at(i).toString().contains(alternateName))
+ break;
+ }
+
+ if (i == alsoList.size()) {
+ alternateName += "()";
+
+ Text also;
+ also << Atom(Atom::Link, alternateName)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << alternateName
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ alsoList.prepend(also);
+ }
+ }
+ }
}
- return s;
}
-/*!
- Looks up the tag \a t in the map of metadata values for the
- current topic in \a inner. If values for the tag are found,
- they are returned in a string list.
+void Generator::terminate()
+{
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if (outputFormats.contains((*g)->format()))
+ (*g)->terminateGenerator();
+ ++g;
+ }
- \note If \a t is found in the metadata map, all the pairs
- having the key \a t are erased. i.e. Once you call this
- function for a particular \a t, you consume \a t.
- */
-QStringList Generator::getMetadataElements(const InnerNode* inner, const QString& t)
+ fmtLeftMaps.clear();
+ fmtRightMaps.clear();
+ imgFileExts.clear();
+ imageFiles.clear();
+ imageDirs.clear();
+ outDir_ = "";
+ QmlClassNode::terminate();
+ ExampleNode::terminate();
+}
+
+void Generator::terminateGenerator()
{
- QStringList s;
- QStringMultiMap& metaTagMap = const_cast<QStringMultiMap&>(inner->doc().metaTagMap());
- s = metaTagMap.values(t);
- if (!s.isEmpty())
- metaTagMap.remove(t);
- return s;
}
/*!
- For generating the "New Classes... in 4.6" section on the
- What's New in 4.6" page.
+ Trims trailing whitespace off the \a string and returns
+ the trimmed string.
*/
-void Generator::findAllSince(const InnerNode *node)
+QString Generator::trimmedTrailing(const QString& string)
{
- NodeList::const_iterator child = node->childNodes().constBegin();
-
- // Traverse the tree, starting at the node supplied.
-
- while (child != node->childNodes().constEnd()) {
-
- QString sinceString = (*child)->since();
-
- if (((*child)->access() != Node::Private) && !sinceString.isEmpty()) {
-
- // Insert a new entry into each map for each new since string found.
- NewSinceMaps::iterator nsmap = newSinceMaps.find(sinceString);
- if (nsmap == newSinceMaps.end())
- nsmap = newSinceMaps.insert(sinceString,NodeMultiMap());
-
- NewClassMaps::iterator ncmap = newClassMaps.find(sinceString);
- if (ncmap == newClassMaps.end())
- ncmap = newClassMaps.insert(sinceString,NodeMap());
-
- NewClassMaps::iterator nqcmap = newQmlClassMaps.find(sinceString);
- if (nqcmap == newQmlClassMaps.end())
- nqcmap = newQmlClassMaps.insert(sinceString,NodeMap());
-
- if ((*child)->type() == Node::Function) {
- // Insert functions into the general since map.
- FunctionNode *func = static_cast<FunctionNode *>(*child);
- if ((func->status() > Node::Obsolete) &&
- (func->metaness() != FunctionNode::Ctor) &&
- (func->metaness() != FunctionNode::Dtor)) {
- nsmap.value().insert(func->name(),(*child));
- }
- }
- else if ((*child)->url().isEmpty()) {
- if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) {
- // Insert classes into the since and class maps.
- QString className = (*child)->name();
- if ((*child)->parent() &&
- (*child)->parent()->type() == Node::Namespace &&
- !(*child)->parent()->name().isEmpty())
- className = (*child)->parent()->name()+"::"+className;
-
- nsmap.value().insert(className,(*child));
- ncmap.value().insert(className,(*child));
- }
- else if ((*child)->subType() == Node::QmlClass) {
- // Insert QML elements into the since and element maps.
- QString className = (*child)->name();
- if ((*child)->parent() &&
- (*child)->parent()->type() == Node::Namespace &&
- !(*child)->parent()->name().isEmpty())
- className = (*child)->parent()->name()+"::"+className;
-
- nsmap.value().insert(className,(*child));
- nqcmap.value().insert(className,(*child));
- }
- else if ((*child)->type() == Node::QmlProperty) {
- // Insert QML properties into the since map.
- QString propertyName = (*child)->name();
- nsmap.value().insert(propertyName,(*child));
- }
- }
- else {
- // Insert external documents into the general since map.
- QString name = (*child)->name();
- if ((*child)->parent() &&
- (*child)->parent()->type() == Node::Namespace &&
- !(*child)->parent()->name().isEmpty())
- name = (*child)->parent()->name()+"::"+name;
-
- nsmap.value().insert(name,(*child));
- }
+ QString trimmed = string;
+ while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace())
+ trimmed.truncate(trimmed.length() - 1);
+ return trimmed;
+}
- // Find child nodes with since commands.
- if ((*child)->isInnerNode()) {
- findAllSince(static_cast<InnerNode *>(*child));
- }
+QString Generator::typeString(const Node *node)
+{
+ switch (node->type()) {
+ case Node::Namespace:
+ return "namespace";
+ case Node::Class:
+ return "class";
+ case Node::Fake:
+ {
+ switch (node->subType()) {
+ case Node::QmlClass:
+ return "element";
+ case Node::QmlPropertyGroup:
+ return "property group";
+ case Node::QmlBasicType:
+ return "type";
+ default:
+ return "documentation";
}
- ++child;
}
+ case Node::Enum:
+ return "enum";
+ case Node::Typedef:
+ return "typedef";
+ case Node::Function:
+ return "function";
+ case Node::Property:
+ return "property";
+ default:
+ return "documentation";
+ }
+}
+
+void Generator::unknownAtom(const Atom *atom)
+{
+ Location::internalError(tr("unknown atom type '%1' in %2 generator")
+ .arg(atom->typeString()).arg(format()));
}
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h
index 4021a85f61..bc1b12b958 100644
--- a/src/tools/qdoc/generator.h
+++ b/src/tools/qdoc/generator.h
@@ -46,22 +46,23 @@
#ifndef GENERATOR_H
#define GENERATOR_H
-#include <qlist.h>
-#include <qmap.h>
-#include <qregexp.h>
-#include <qstring.h>
-#include <qstringlist.h>
+#include <QList>
+#include <QMap>
+#include <QRegExp>
+#include <QString>
+#include <QStringList>
+#include <QTextStream>
#include "node.h"
#include "text.h"
QT_BEGIN_NAMESPACE
+typedef QMap<QString, NodeMap> NewClassMaps;
+typedef QMap<QString, NodeMultiMap> NewSinceMaps;
typedef QMap<QString, const Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap;
-typedef QMap<QString, NodeMultiMap> NewSinceMaps;
typedef QMap<Node*, NodeMultiMap> ParentMaps;
-typedef QMap<QString, NodeMap> NewClassMaps;
class ClassNode;
class Config;
@@ -80,87 +81,124 @@ public:
Generator();
virtual ~Generator();
+ virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
+ virtual QString format() = 0;
+ virtual void generateTree(const Tree *tree);
virtual void initializeGenerator(const Config &config);
virtual void terminateGenerator();
- virtual QString format() = 0;
- virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
- virtual void generateTree(const Tree *tree) = 0;
- static void initialize(const Config& config);
- static void terminate();
+ static const QString& baseDir() { return baseDir_; }
static Generator *generatorForFormat(const QString& format);
+ static void initialize(const Config& config);
static const QString& outputDir() { return outDir_; }
- static const QString& baseDir() { return baseDir_; }
+ static void terminate();
protected:
- virtual void startText(const Node *relative, CodeMarker *marker);
+ virtual void beginSubPage(const InnerNode* node, const QString& fileName);
+ virtual void endSubPage();
virtual void endText(const Node *relative, CodeMarker *marker);
+ virtual QString fileBase(const Node* node) const;
+ virtual QString fileExtension(const Node* node) const = 0;
+ virtual QString fullName(const Node *node,
+ const Node *relative,
+ CodeMarker *marker) const;
+ virtual void generateAlsoList(const Node *node, CodeMarker *marker);
virtual int generateAtom(const Atom *atom,
const Node *relative,
CodeMarker *marker);
+ virtual void generateBody(const Node *node, CodeMarker *marker);
virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker);
virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker);
-
- virtual bool generateText(const Text& text,
- const Node *relative,
- CodeMarker *marker);
+ virtual void generateInheritedBy(const ClassNode *classe,
+ CodeMarker *marker);
+ virtual void generateInherits(const ClassNode *classe,
+ CodeMarker *marker);
+ virtual void generateInnerNode(const InnerNode *node);
+ virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
+ virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
+ virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
virtual bool generateQmlText(const Text& text,
const Node *relative,
CodeMarker *marker,
const QString& qmlName);
- virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
- virtual void generateBody(const Node *node, CodeMarker *marker);
- virtual void generateAlsoList(const Node *node, CodeMarker *marker);
- virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
- virtual void generateInherits(const ClassNode *classe,
- CodeMarker *marker);
- virtual void generateInheritedBy(const ClassNode *classe,
- CodeMarker *marker);
+ virtual bool generateText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker);
+ virtual QString imageFileName(const Node *relative, const QString& fileBase);
+ virtual QString outFileName() { return QString(); }
+ virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
+ virtual void startText(const Node *relative, CodeMarker *marker);
+ virtual QString typeString(const Node *node);
- void generateThreadSafeness(const Node *node, CodeMarker *marker);
- void generateSince(const Node *node, CodeMarker *marker);
- void generateStatus(const Node *node, CodeMarker *marker);
+ static bool matchAhead(const Atom *atom, Atom::Type expectedAtomType);
+ static QString outputPrefix(const QString &nodeType);
+ static void singularPlural(Text& text, const NodeList& nodes);
+ static void supplementAlsoList(const Node *node, QList<Text> &alsoList);
+ static QString trimmedTrailing(const QString &string);
+ static QString sinceTitles[];
+
+ QString fileName(const Node* node) const;
+ void findAllSince(const InnerNode *node);
+ QMap<QString, QString> &formattingLeftMap();
+ QMap<QString, QString> &formattingRightMap();
const Atom* generateAtomList(const Atom *atom,
const Node *relative,
CodeMarker *marker,
bool generate,
int& numGeneratedAtoms);
+ void generateExampleFiles(const FakeNode *fake, CodeMarker *marker);
void generateFileList(const FakeNode* fake,
CodeMarker* marker,
Node::SubType subtype,
const QString& tag);
- void generateExampleFiles(const FakeNode *fake, CodeMarker *marker);
-
- virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
- virtual QString fullName(const Node *node,
- const Node *relative,
- CodeMarker *marker) const;
-
- virtual QString outFileName() { return QString(); }
-
+ void generateSince(const Node *node, CodeMarker *marker);
+ void generateStatus(const Node *node, CodeMarker *marker);
+ void generateThreadSafeness(const Node *node, CodeMarker *marker);
+ QString getMetadataElement(const InnerNode* inner, const QString& t);
+ QStringList getMetadataElements(const InnerNode* inner, const QString& t);
QString indent(int level, const QString& markedCode);
+ QTextStream& out();
+ bool parseArg(const QString& src,
+ const QString& tag,
+ int* pos,
+ int n,
+ QStringRef* contents,
+ QStringRef* par1 = 0,
+ bool debug = false);
QString plainCode(const QString& markedCode);
- virtual QString typeString(const Node *node);
- virtual QString imageFileName(const Node *relative, const QString& fileBase);
void setImageFileExtensions(const QStringList& extensions);
void unknownAtom(const Atom *atom);
- QMap<QString, QString> &formattingLeftMap();
- QMap<QString, QString> &formattingRightMap();
- QMap<QString, QStringList> editionModuleMap;
- QMap<QString, QStringList> editionGroupMap;
-
- static QString trimmedTrailing(const QString &string);
- static bool matchAhead(const Atom *atom, Atom::Type expectedAtomType);
- static void supplementAlsoList(const Node *node, QList<Text> &alsoList);
- static QString outputPrefix(const QString &nodeType);
- QString getMetadataElement(const InnerNode* inner, const QString& t);
- QStringList getMetadataElements(const InnerNode* inner, const QString& t);
- void findAllSince(const InnerNode *node);
+ QList<NameCollisionNode*> collisionNodes;
+ QMap<QString, QStringList> editionGroupMap;
+ QMap<QString, QStringList> editionModuleMap;
+ QString naturalLanguage;
+ QTextCodec* outputCodec;
+ QString outputEncoding;
+ QStack<QTextStream*> outStreamStack;
+ NewClassMaps newClassMaps;
+ NewClassMaps newQmlClassMaps;
+ NewSinceMaps newSinceMaps;
private:
- void generateReimplementedFrom(const FunctionNode *func,
- CodeMarker *marker);
+ static QString baseDir_;
+ static QStringList exampleDirs;
+ static QStringList exampleImgExts;
+ static QMap<QString, QMap<QString, QString> > fmtLeftMaps;
+ static QMap<QString, QMap<QString, QString> > fmtRightMaps;
+ static QList<Generator *> generators;
+ static QStringList imageDirs;
+ static QStringList imageFiles;
+ static QMap<QString, QStringList> imgFileExts;
+ static QString project;
+ static QString outDir_;
+ static QSet<QString> outputFormats;
+ static QHash<QString, QString> outputPrefixes;
+ static QStringList scriptDirs;
+ static QStringList scriptFiles;
+ static QStringList styleDirs;
+ static QStringList styleFiles;
+
void appendFullName(Text& text,
const Node *apparentNode,
const Node *relative,
@@ -178,42 +216,18 @@ private:
const ClassNode *classe,
const QList<RelatedClass> &classes,
CodeMarker *marker);
-
-protected:
void appendSortedQmlNames(Text& text,
const Node* base,
const NodeList& subs,
CodeMarker *marker);
+ void generateReimplementedFrom(const FunctionNode *func,
+ CodeMarker *marker);
- static QString sinceTitles[];
- NewSinceMaps newSinceMaps;
- NewClassMaps newClassMaps;
- NewClassMaps newQmlClassMaps;
-
-private:
QString amp;
- QString lt;
QString gt;
+ QString lt;
QString quot;
QRegExp tag;
-
- static QList<Generator *> generators;
- static QMap<QString, QMap<QString, QString> > fmtLeftMaps;
- static QMap<QString, QMap<QString, QString> > fmtRightMaps;
- static QMap<QString, QStringList> imgFileExts;
- static QSet<QString> outputFormats;
- static QStringList imageFiles;
- static QStringList imageDirs;
- static QStringList exampleDirs;
- static QStringList exampleImgExts;
- static QStringList scriptFiles;
- static QStringList scriptDirs;
- static QStringList styleFiles;
- static QStringList styleDirs;
- static QString outDir_;
- static QString baseDir_;
- static QString project;
- static QHash<QString, QString> outputPrefixes;
};
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 9b886564c4..0662303d1e 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -273,7 +273,7 @@ void HtmlGenerator::generateTree(const Tree *tree)
findAllNamespaces(tree->root());
findAllSince(tree->root());
- PageGenerator::generateTree(tree);
+ Generator::generateTree(tree);
reportOrphans(tree->root());
generateDisambiguationPages();
@@ -1375,7 +1375,7 @@ void HtmlGenerator::generateDisambiguationPages()
for (int i=0; i<collisionNodes.size(); ++i) {
NameCollisionNode* ncn = collisionNodes.at(i);
ncn->clearCurrentChild();
- beginSubPage(ncn, PageGenerator::fileName(ncn));
+ beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = "Name Collision: " + ncn->fullTitle();
QString htmlTitle = fullTitle;
CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath());
@@ -3270,7 +3270,7 @@ QString HtmlGenerator::fileBase(const Node *node) const
{
QString result;
- result = PageGenerator::fileBase(node);
+ result = Generator::fileBase(node);
if (!node->isInnerNode()) {
switch (node->status()) {
@@ -3295,7 +3295,7 @@ QString HtmlGenerator::fileName(const Node *node)
if (static_cast<const FakeNode *>(node)->subType() == Node::Image)
return node->name();
}
- return PageGenerator::fileName(node);
+ return Generator::fileName(node);
}
QString HtmlGenerator::refForNode(const Node *node)
@@ -3719,7 +3719,7 @@ const QPair<QString,QString> HtmlGenerator::anchorForNode(const Node *node)
{
QPair<QString,QString> anchorPair;
- anchorPair.first = PageGenerator::fileName(node);
+ anchorPair.first = Generator::fileName(node);
if (node->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
anchorPair.second = fakeNode->title();
@@ -4228,25 +4228,6 @@ void HtmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* mar
}
/*!
- Output the "Inherit by" list for the QML element,
- if it is inherited by any other elements.
- */
-void HtmlGenerator::generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker)
-{
- if (qcn) {
- NodeList subs;
- QmlClassNode::subclasses(qcn->name(),subs);
- if (!subs.isEmpty()) {
- Text text;
- text << Atom::ParaLeft << "Inherited by ";
- appendSortedQmlNames(text,qcn,subs,marker);
- text << Atom::ParaRight;
- generateText(text, qcn, marker);
- }
- }
-}
-
-/*!
Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]"
line for the QML element, if there should be one.
@@ -4332,7 +4313,7 @@ bool HtmlGenerator::generatePageElement(QXmlStreamWriter& writer,
QString url = node->outputSubdirectory();
if (!url.isEmpty())
url.append(QLatin1Char('/'));
- url.append(PageGenerator::fileName(node));
+ url.append(Generator::fileName(node));
writer.writeStartElement("page");
@@ -5042,7 +5023,7 @@ QXmlStreamWriter& HtmlGenerator::xmlWriter()
*/
void HtmlGenerator::beginDitamapPage(const InnerNode* node, const QString& fileName)
{
- PageGenerator::beginSubPage(node,fileName);
+ Generator::beginSubPage(node,fileName);
QXmlStreamWriter* writer = new QXmlStreamWriter(out().device());
xmlWriterStack.push(writer);
writer->setAutoFormatting(true);
@@ -5061,7 +5042,7 @@ void HtmlGenerator::endDitamapPage()
{
xmlWriter().writeEndDocument();
delete xmlWriterStack.pop();
- PageGenerator::endSubPage();
+ Generator::endSubPage();
}
/*!
diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h
index 24c5fb7179..841c226b75 100644
--- a/src/tools/qdoc/htmlgenerator.h
+++ b/src/tools/qdoc/htmlgenerator.h
@@ -46,18 +46,18 @@
#ifndef HTMLGENERATOR_H
#define HTMLGENERATOR_H
-#include <qmap.h>
-#include <qregexp.h>
+#include <QMap>
+#include <QRegExp>
#include <QXmlStreamWriter>
#include "codemarker.h"
#include "config.h"
-#include "pagegenerator.h"
+#include "generator.h"
QT_BEGIN_NAMESPACE
class HelpProjectWriter;
-class HtmlGenerator : public PageGenerator
+class HtmlGenerator : public Generator
{
public:
enum SinceType {
@@ -180,7 +180,6 @@ private:
const InnerNode *relative,
CodeMarker *marker);
void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
- void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker);
diff --git a/src/tools/qdoc/pagegenerator.cpp b/src/tools/qdoc/pagegenerator.cpp
deleted file mode 100644
index 6a52b7755a..0000000000
--- a/src/tools/qdoc/pagegenerator.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*
- pagegenerator.cpp
-*/
-
-#include <qfile.h>
-#include <qfileinfo.h>
-#include <qdebug.h>
-#include "codemarker.h"
-#include "pagegenerator.h"
-#include "tree.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- Nothing to do in the constructor.
- */
-PageGenerator::PageGenerator()
- : outputCodec(0)
-{
- // nothing.
-}
-
-/*!
- The destructor
- */
-PageGenerator::~PageGenerator()
-{
- while (!outStreamStack.isEmpty())
- endSubPage();
-}
-
-bool PageGenerator::parseArg(const QString& src,
- const QString& tag,
- int* pos,
- int n,
- QStringRef* contents,
- QStringRef* par1,
- bool debug)
-{
-#define SKIP_CHAR(c) \
- if (debug) \
- qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \
- if (i >= n || src[i] != c) { \
- if (debug) \
- qDebug() << " char '" << c << "' not found"; \
- return false; \
-} \
- ++i;
-
-
-#define SKIP_SPACE \
- while (i < n && src[i] == ' ') \
- ++i;
-
- int i = *pos;
- int j = i;
-
- // assume "<@" has been parsed outside
- //SKIP_CHAR('<');
- //SKIP_CHAR('@');
-
- if (tag != QStringRef(&src, i, tag.length())) {
- if (0 && debug)
- qDebug() << "tag " << tag << " not found at " << i;
- return false;
- }
-
- if (debug)
- qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i;
-
- // skip tag
- i += tag.length();
-
- // parse stuff like: linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
- if (par1) {
- SKIP_SPACE;
- // read parameter name
- j = i;
- while (i < n && src[i].isLetter())
- ++i;
- if (src[i] == '=') {
- if (debug)
- qDebug() << "read parameter" << QString(src.data() + j, i - j);
- SKIP_CHAR('=');
- SKIP_CHAR('"');
- // skip parameter name
- j = i;
- while (i < n && src[i] != '"')
- ++i;
- *par1 = QStringRef(&src, j, i - j);
- SKIP_CHAR('"');
- SKIP_SPACE;
- } else {
- if (debug)
- qDebug() << "no optional parameter found";
- }
- }
- SKIP_SPACE;
- SKIP_CHAR('>');
-
- // find contents up to closing "</@tag>
- j = i;
- for (; true; ++i) {
- if (i + 4 + tag.length() > n)
- return false;
- if (src[i] != '<')
- continue;
- if (src[i + 1] != '/')
- continue;
- if (src[i + 2] != '@')
- continue;
- if (tag != QStringRef(&src, i + 3, tag.length()))
- continue;
- if (src[i + 3 + tag.length()] != '>')
- continue;
- break;
- }
-
- *contents = QStringRef(&src, j, i - j);
-
- i += tag.length() + 4;
-
- *pos = i;
- if (debug)
- qDebug() << " tag " << tag << " found: pos now: " << i;
- return true;
-#undef SKIP_CHAR
-}
-
-/*!
- This function is recursive.
- */
-void PageGenerator::generateTree(const Tree *tree)
-{
- generateInnerNode(tree->root());
-}
-
-QString PageGenerator::fileBase(const Node *node) const
-{
- if (node->relates())
- node = node->relates();
- else if (!node->isInnerNode())
- node = node->parent();
- if (node->subType() == Node::QmlPropertyGroup) {
- node = node->parent();
- }
-
- QString base = node->doc().baseName();
- if (!base.isEmpty())
- return base;
-
- const Node *p = node;
-
- forever {
- const Node *pp = p->parent();
- base.prepend(p->name());
- if (!p->qmlModuleIdentifier().isEmpty())
- base.prepend(p->qmlModuleIdentifier()+QChar('-'));
- /*
- To avoid file name conflicts in the html directory,
- we prepend a prefix (by default, "qml-") to the file name of QML
- element doc files.
- */
- if ((p->subType() == Node::QmlClass) ||
- (p->subType() == Node::QmlBasicType)) {
- base.prepend(outputPrefix(QLatin1String("QML")));
- }
- if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake)
- break;
- base.prepend(QLatin1Char('-'));
- p = pp;
- }
- if (node->type() == Node::Fake) {
- if (node->subType() == Node::Collision) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
- if (ncn->currentChild())
- return fileBase(ncn->currentChild());
- base.prepend("collision-");
- }
-#ifdef QDOC2_COMPAT
- if (base.endsWith(".html"))
- base.truncate(base.length() - 5);
-#endif
- }
-
- // the code below is effectively equivalent to:
- // base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
- // base = base.trimmed();
- // base.replace(QLatin1Char(' '), QLatin1Char('-'));
- // base = base.toLower();
- // as this function accounted for ~8% of total running time
- // we optimize a bit...
-
- QString res;
- // +5 prevents realloc in fileName() below
- res.reserve(base.size() + 5);
- bool begun = false;
- for (int i = 0; i != base.size(); ++i) {
- QChar c = base.at(i);
- uint u = c.unicode();
- if (u >= 'A' && u <= 'Z')
- u -= 'A' - 'a';
- if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) {
- res += QLatin1Char(u);
- begun = true;
- }
- else if (begun) {
- res += QLatin1Char('-');
- begun = false;
- }
- }
- while (res.endsWith(QLatin1Char('-')))
- res.chop(1);
- return res;
-}
-
-/*!
- If the \a node has a URL, return the URL as the file name.
- Otherwise, construct the file name from the fileBase() and
- the fileExtension(), and return the constructed name.
- */
-QString PageGenerator::fileName(const Node* node) const
-{
- if (!node->url().isEmpty())
- return node->url();
-
- QString name = fileBase(node);
- name += QLatin1Char('.');
- name += fileExtension(node);
- return name;
-}
-
-/*!
- Return the current output file name.
- */
-QString PageGenerator::outFileName()
-{
- return QFileInfo(static_cast<QFile*>(out().device())->fileName()).fileName();
-}
-
-/*!
- Creates the file named \a fileName in the output directory.
- Attaches a QTextStream to the created file, which is written
- to all over the place using out().
- */
-void PageGenerator::beginSubPage(const InnerNode* node, const QString& fileName)
-{
- QString path = outputDir() + QLatin1Char('/');
- if (!node->outputSubdirectory().isEmpty())
- path += node->outputSubdirectory() + QLatin1Char('/');
- path += fileName;
- QFile* outFile = new QFile(path);
- if (!outFile->open(QFile::WriteOnly))
- node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
- QTextStream* out = new QTextStream(outFile);
-
- if (outputCodec)
- out->setCodec(outputCodec);
- outStreamStack.push(out);
- const_cast<InnerNode*>(node)->setOutputFileName(fileName);
-}
-
-/*!
- Flush the text stream associated with the subpage, and
- then pop it off the text stream stack and delete it.
- This terminates output of the subpage.
- */
-void PageGenerator::endSubPage()
-{
- outStreamStack.top()->flush();
- delete outStreamStack.top()->device();
- delete outStreamStack.pop();
-}
-
-/*!
- Used for writing to the current output stream. Returns a
- reference to the crrent output stream, which is then used
- with the \c {<<} operator for writing.
- */
-QTextStream &PageGenerator::out()
-{
- return *outStreamStack.top();
-}
-
-/*!
- Recursive writing of HTML files from the root \a node.
-
- \note NameCollisionNodes are skipped here and processed
- later. See HtmlGenerator::generateDisambiguationPages()
- for more on this.
- */
-void
-PageGenerator::generateInnerNode(const InnerNode* node)
-{
- if (!node->url().isNull())
- return;
-
- if (node->type() == Node::Fake) {
- const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
- if (fakeNode->subType() == Node::ExternalPage)
- return;
- if (fakeNode->subType() == Node::Image)
- return;
- if (fakeNode->subType() == Node::QmlPropertyGroup)
- return;
- if (fakeNode->subType() == Node::Page) {
- if (node->count() > 0)
- qDebug("PAGE %s HAS CHILDREN", qPrintable(fakeNode->title()));
- }
- }
-
- /*
- Obtain a code marker for the source file.
- */
- CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
-
- if (node->parent() != 0) {
- /*
- Skip name collision nodes here and process them
- later in generateDisambiguationPages(). Each one
- is appended to a list for later.
- */
- if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
- collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
- }
- else {
- beginSubPage(node, fileName(node));
- if (node->type() == Node::Namespace || node->type() == Node::Class) {
- generateClassLikeNode(node, marker);
- }
- else if (node->type() == Node::Fake) {
- generateFakeNode(static_cast<const FakeNode *>(node), marker);
- }
- endSubPage();
- }
- }
-
- NodeList::ConstIterator c = node->childNodes().begin();
- while (c != node->childNodes().end()) {
- if ((*c)->isInnerNode() && (*c)->access() != Node::Private) {
- generateInnerNode((const InnerNode *) *c);
- }
- ++c;
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/tools/qdoc/pagegenerator.h b/src/tools/qdoc/pagegenerator.h
deleted file mode 100644
index da0d32d2ff..0000000000
--- a/src/tools/qdoc/pagegenerator.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*
- pagegenerator.h
-*/
-
-#ifndef PAGEGENERATOR_H
-#define PAGEGENERATOR_H
-
-#include <QStack>
-#include <qtextstream.h>
-#include "generator.h"
-#include "location.h"
-
-QT_BEGIN_NAMESPACE
-
-class QTextCodec;
-class ClassNode;
-class InnerNode;
-class NamespaceNode;
-class NameCollisionNode;
-
-class PageGenerator : public Generator
-{
-public:
- PageGenerator();
- ~PageGenerator();
-
- virtual void generateTree(const Tree *tree);
- virtual void generateDisambiguationPages() { }
-
-protected:
- virtual QString fileBase(const Node* node) const;
- virtual QString fileExtension(const Node* node) const = 0;
- QString fileName(const Node* node) const;
- QString outFileName();
- virtual void beginSubPage(const InnerNode* node, const QString& fileName);
- virtual void endSubPage();
- virtual void generateInnerNode(const InnerNode *node);
- QTextStream& out();
-
- QString naturalLanguage;
- QString outputEncoding;
- QTextCodec* outputCodec;
- bool parseArg(const QString& src,
- const QString& tag,
- int* pos,
- int n,
- QStringRef* contents,
- QStringRef* par1 = 0,
- bool debug = false);
-
-protected:
- QStack<QTextStream*> outStreamStack;
- QList<NameCollisionNode*> collisionNodes;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/tools/qdoc/qdoc.pro b/src/tools/qdoc/qdoc.pro
index 03de9f91df..09f9b7a0c1 100644
--- a/src/tools/qdoc/qdoc.pro
+++ b/src/tools/qdoc/qdoc.pro
@@ -39,7 +39,6 @@ HEADERS += atom.h \
location.h \
node.h \
openedlist.h \
- pagegenerator.h \
plaincodemarker.h \
puredocparser.h \
quoter.h \
@@ -65,7 +64,6 @@ SOURCES += atom.cpp \
main.cpp \
node.cpp \
openedlist.cpp \
- pagegenerator.cpp \
plaincodemarker.cpp \
puredocparser.cpp \
quoter.cpp \