summaryrefslogtreecommitdiffstats
path: root/src/tools/qdoc/ditaxmlgenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/qdoc/ditaxmlgenerator.cpp')
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.cpp5993
1 files changed, 0 insertions, 5993 deletions
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp
deleted file mode 100644
index 54b358e170..0000000000
--- a/src/tools/qdoc/ditaxmlgenerator.cpp
+++ /dev/null
@@ -1,5993 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*
- ditaxmlgenerator.cpp
-*/
-
-#include <qdebug.h>
-#include <qlist.h>
-#include <qiterator.h>
-#include <qtextcodec.h>
-#include <quuid.h>
-#include "codemarker.h"
-#include "codeparser.h"
-#include "ditaxmlgenerator.h"
-#include "node.h"
-#include "quoter.h"
-#include "separator.h"
-#include "tree.h"
-#include <ctype.h>
-#include "qdocdatabase.h"
-
-QT_BEGIN_NAMESPACE
-
-#define COMMAND_VERSION Doc::alias("version")
-int DitaXmlGenerator::id = 0;
-
-/*
- The strings in this array must appear in the same order as
- the values in enum DitaXmlGenerator::DitaTag.
- */
-QString DitaXmlGenerator::ditaTags[] =
-{
- "",
- "alt",
- "apiData",
- "apiDef",
- "apiDefItem",
- "apiDesc",
- "apiDetail",
- "apiItemName",
- "APIMap",
- "apiName",
- "apiRef",
- "apiRelation",
- "audience",
- "author",
- "b",
- "body",
- "bodydiv",
- "brand",
- "category",
- "codeblock",
- "colspec",
- "comment",
- "component",
- "copyrholder",
- "copyright",
- "copyryear",
- "created",
- "critdates",
- "cxxAPIMap",
- "cxxClass",
- "cxxClassAbstract",
- "cxxClassAccessSpecifier",
- "cxxClassAPIItemLocation",
- "cxxClassBaseClass",
- "cxxClassDeclarationFile",
- "cxxClassDeclarationFileLine",
- "cxxClassDeclarationFileLineStart",
- "cxxClassDeclarationFileLineEnd",
- "cxxClassDefinition",
- "cxxClassDerivation",
- "cxxClassDerivationAccessSpecifier",
- "cxxClassDerivations",
- "cxxClassDetail",
- "cxxClassNested",
- "cxxClassNestedClass",
- "cxxClassNestedDetail",
- "cxxDefine",
- "cxxDefineAccessSpecifier",
- "cxxDefineAPIItemLocation",
- "cxxDefineDeclarationFile",
- "cxxDefineDeclarationFileLine",
- "cxxDefineDefinition",
- "cxxDefineDetail",
- "cxxDefineNameLookup",
- "cxxDefineParameter",
- "cxxDefineParameterDeclarationName",
- "cxxDefineParameters",
- "cxxDefinePrototype",
- "cxxDefineReimplemented",
- "cxxEnumeration",
- "cxxEnumerationAccessSpecifier",
- "cxxEnumerationAPIItemLocation",
- "cxxEnumerationDeclarationFile",
- "cxxEnumerationDeclarationFileLine",
- "cxxEnumerationDeclarationFileLineStart",
- "cxxEnumerationDeclarationFileLineEnd",
- "cxxEnumerationDefinition",
- "cxxEnumerationDetail",
- "cxxEnumerationNameLookup",
- "cxxEnumerationPrototype",
- "cxxEnumerationScopedName",
- "cxxEnumerator",
- "cxxEnumeratorInitialiser",
- "cxxEnumeratorNameLookup",
- "cxxEnumeratorPrototype",
- "cxxEnumerators",
- "cxxEnumeratorScopedName",
- "cxxFunction",
- "cxxFunctionAccessSpecifier",
- "cxxFunctionAPIItemLocation",
- "cxxFunctionConst",
- "cxxFunctionConstructor",
- "cxxFunctionDeclarationFile",
- "cxxFunctionDeclarationFileLine",
- "cxxFunctionDeclaredType",
- "cxxFunctionDefinition",
- "cxxFunctionDestructor",
- "cxxFunctionDetail",
- "cxxFunctionNameLookup",
- "cxxFunctionParameter",
- "cxxFunctionParameterDeclarationName",
- "cxxFunctionParameterDeclaredType",
- "cxxFunctionParameterDefaultValue",
- "cxxFunctionParameters",
- "cxxFunctionPrototype",
- "cxxFunctionPureVirtual",
- "cxxFunctionReimplemented",
- "cxxFunctionScopedName",
- "cxxFunctionStorageClassSpecifierStatic",
- "cxxFunctionVirtual",
- "cxxTypedef",
- "cxxTypedefAccessSpecifier",
- "cxxTypedefAPIItemLocation",
- "cxxTypedefDeclarationFile",
- "cxxTypedefDeclarationFileLine",
- "cxxTypedefDefinition",
- "cxxTypedefDetail",
- "cxxTypedefNameLookup",
- "cxxTypedefScopedName",
- "cxxVariable",
- "cxxVariableAccessSpecifier",
- "cxxVariableAPIItemLocation",
- "cxxVariableDeclarationFile",
- "cxxVariableDeclarationFileLine",
- "cxxVariableDeclaredType",
- "cxxVariableDefinition",
- "cxxVariableDetail",
- "cxxVariableNameLookup",
- "cxxVariablePrototype",
- "cxxVariableReimplemented",
- "cxxVariableScopedName",
- "cxxVariableStorageClassSpecifierStatic",
- "data",
- "data-about",
- "dd",
- "dl",
- "dlentry",
- "dt",
- "entry",
- "fig",
- "i",
- "image",
- "keyword",
- "keywords",
- "li",
- "link",
- "linktext",
- "lq",
- "map",
- "mapref",
- "metadata",
- "note",
- "ol",
- "othermeta",
- "p",
- "parameter",
- "permissions",
- "ph",
- "platform",
- "pre",
- "prodinfo",
- "prodname",
- "prolog",
- "publisher",
- "qmlAttached",
- "qmlDetail",
- "qmlImportModule",
- "qmlInheritedBy",
- "qmlInherits",
- "qmlInstantiates",
- "qmlMethod",
- "qmlMethodDef",
- "qmlMethodDetail",
- "qmlName",
- "qmlProperty",
- "qmlPropertyDef",
- "qmlPropertyDetail",
- "qmlPropertyGroup",
- "qmlPropertyGroupDef",
- "qmlPropertyGroupDetail",
- "qmlQualifier",
- "qmlSignal",
- "qmlSignalDef",
- "qmlSignalDetail",
- "qmlSignalHandler",
- "qmlSignalHandlerDef",
- "qmlSignalHandlerDetail",
- "qmlSignature",
- "qmlSince",
- "qmlType",
- "qmlTypeDef",
- "qmlTypeDetail",
- "related-links",
- "resourceid",
- "revised",
- "row",
- "section",
- "sectiondiv",
- "shortdesc",
- "simpletable",
- "source",
- "stentry",
- "sthead",
- "strow",
- "sub",
- "sup",
- "table",
- "tbody",
- "tgroup",
- "thead",
- "title",
- "tm",
- "topic",
- "topicmeta",
- "topicref",
- "tt",
- "u",
- "uicontrol",
- "ul",
- "unknown",
- "vrm",
- "vrmlist",
- "xref",
- ""
-};
-
-/*!
- Composes a string to be used as an href attribute in DITA
- XML. It is composed of the file name and the UUID separated
- by a '#'. If this node is a class node, the file name is
- taken from this node; if this node is a function node, the
- file name is taken from the parent node of this node.
- */
-QString DitaXmlGenerator::ditaXmlHref(Node* n)
-{
- QString href;
- if ((n->type() == Node::Function) ||
- (n->type() == Node::Property) ||
- (n->type() == Node::Variable)) {
- href = fileBase(n->parent());
- }
- else {
- href = fileBase(n);
- }
- if (!href.endsWith(".xml") && !href.endsWith(".dita"))
- href += ".dita";
- return href + QLatin1Char('#') + n->guid();
-}
-
-void DitaXmlGenerator::debugPara(const QString& t)
-{
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass",t);
- xmlWriter().writeCharacters(t);
- writeEndTag(); // </p>
-}
-
-static bool showBrokenLinks = false;
-
-/*!
- Quick, dirty, and very ugly. Unescape \a text
- so QXmlStreamWriter::writeCharacters() can put
- the escapes back in again!
- */
-void DitaXmlGenerator::writeCharacters(const QString& text)
-{
- QString t = text;
- t = t.replace("&lt;","<");
- t = t.replace("&gt;",">");
- t = t.replace("&amp;","&");
- t = t.replace("&quot;","\"");
- xmlWriter().writeCharacters(t);
-}
-
-/*!
- Appends an <xref> element to the current XML stream
- with the \a href attribute and the \a text.
- */
-void DitaXmlGenerator::addLink(const QString& href,
- const QStringRef& text,
- DitaTag t)
-{
- if (!href.isEmpty()) {
- writeStartTag(t);
- // formathtml
- writeHrefAttribute(href);
- writeCharacters(text.toString());
- writeEndTag(); // </t>
- }
- else {
- writeCharacters(text.toString());
- }
-}
-
-/*!
- Push \a t onto the dita tag stack and write the appropriate
- start tag to the DITA XML file.
- */
-void DitaXmlGenerator::writeStartTag(DitaTag t)
-{
- xmlWriter().writeStartElement(ditaTags[t]);
- tagStack.push(t);
-}
-
-/*!
- Pop the current DITA tag off the stack, and write the
- appropriate end tag to the DITA XML file. If \a t is
- not \e DT_NONE (default), then \a t contains the enum
- value of the tag that should be on top of the stack.
-
- If the stack is empty, no end tag is written and false
- is returned. Otherwise, an end tag is written and true
- is returned.
- */
-bool DitaXmlGenerator::writeEndTag(DitaTag t)
-{
- if (tagStack.isEmpty())
- return false;
- DitaTag top = tagStack.pop();
- if (t > DT_NONE && top != t)
- qDebug() << "Expected:" << t << "ACTUAL:" << top;
- xmlWriter().writeEndElement();
- return true;
-}
-
-/*!
- Return the current DITA element tag, the one
- on top of the stack.
- */
-DitaXmlGenerator::DitaTag DitaXmlGenerator::currentTag()
-{
- return tagStack.top();
-}
-
-/*!
- Write the start \a tag. if \a title is not empty, generate
- a GUID from it and write the GUID as the value of the \e{id}
- attribute.
-
- Then if \a outputclass is not empty, write it as the value
- of the \a outputclass attribute.
-
- Fiunally, set the section nesting level to 1 and return 1.
- */
-int DitaXmlGenerator::enterDesc(DitaTag tag, const QString& outputclass, const QString& title)
-{
- writeStartTag(tag);
- if (!title.isEmpty()) {
- writeGuidAttribute(title);
- //Are there cases where the spectitle is required?
- //xmlWriter().writeAttribute("spectitle",title);
- }
- if (!outputclass.isEmpty())
- xmlWriter().writeAttribute("outputclass",outputclass);
- sectionNestingLevel = 1;
- return sectionNestingLevel;
-}
-
-/*!
- If the section nesting level is 0, output a \c{<section>}
- element with an \e id attribute generated from \a title and
- an \e outputclass attribute set to \a outputclass.
- If \a title is null, no \e id attribute is output.
- If \a outputclass is empty, no \e outputclass attribute
- is output.
-
- Finally, increment the section nesting level and return
- the new value.
- */
-int DitaXmlGenerator::enterSection(const QString& outputclass, const QString& title)
-{
- if (sectionNestingLevel == 0) {
- writeStartTag(DT_section);
- if (!title.isEmpty())
- writeGuidAttribute(title);
- if (!outputclass.isEmpty())
- xmlWriter().writeAttribute("outputclass",outputclass);
- }
- else if (!title.isEmpty()) {
- writeStartTag(DT_p);
- writeGuidAttribute(title);
- if (!outputclass.isEmpty())
- xmlWriter().writeAttribute("outputclass",outputclass);
- writeCharacters(title);
- writeEndTag(); // </p>
- }
- return ++sectionNestingLevel;
-}
-
-/*!
- If the section nesting level is greater than 0, decrement
- it. If it becomes 0, output a \c {</section>}. Return the
- decremented section nesting level.
- */
-int DitaXmlGenerator::leaveSection()
-{
- if (sectionNestingLevel > 0) {
- --sectionNestingLevel;
- if (sectionNestingLevel == 0)
- writeEndTag(); // </section> or </apiDesc>
- }
- return sectionNestingLevel;
-}
-
-/*!
- Constructs the DITA XML output generator.
- */
-DitaXmlGenerator::DitaXmlGenerator()
- : inDetailedDescription(false),
- inLegaleseText(false),
- inObsoleteLink(false),
- inTableBody(false),
- noLinks(false),
- obsoleteLinks(false),
- divNestingLevel(0),
- sectionNestingLevel(0),
- tableColumnCount(0),
- funcLeftParen("\\S(\\()"),
- nodeTypeMaps(Node::LastType,0),
- nodeSubtypeMaps(Node::LastSubtype,0),
- pageTypeMaps(Node::OnBeyondZebra,0)
-{
-}
-
-/*!
- Destroys the DITA XML output generator.
- */
-DitaXmlGenerator::~DitaXmlGenerator()
-{
- GuidMaps::iterator i = guidMaps.begin();
- while (i != guidMaps.end()) {
- delete i.value();
- ++i;
- }
-}
-
-/*!
- Initializes the DITA XML output generator's data structures
- from the configuration class \a config.
- */
-void DitaXmlGenerator::initializeGenerator(const Config &config)
-{
- Generator::initializeGenerator(config);
- obsoleteLinks = config.getBool(CONFIG_OBSOLETELINKS);
- setImageFileExtensions(QStringList() << "png" << "jpg" << "jpeg" << "gif");
-
- style = config.getString(DitaXmlGenerator::format() +
- Config::dot +
- DITAXMLGENERATOR_STYLE);
- postHeader = config.getString(DitaXmlGenerator::format() +
- Config::dot +
- DITAXMLGENERATOR_POSTHEADER);
- postPostHeader = config.getString(DitaXmlGenerator::format() +
- Config::dot +
- DITAXMLGENERATOR_POSTPOSTHEADER);
- footer = config.getString(DitaXmlGenerator::format() +
- Config::dot +
- DITAXMLGENERATOR_FOOTER);
- address = config.getString(DitaXmlGenerator::format() +
- Config::dot +
- DITAXMLGENERATOR_ADDRESS);
- pleaseGenerateMacRef = config.getBool(DitaXmlGenerator::format() +
- Config::dot +
- DITAXMLGENERATOR_GENERATEMACREFS);
-
- project = config.getString(CONFIG_PROJECT);
- projectDescription = config.getString(CONFIG_DESCRIPTION);
- if (projectDescription.isEmpty() && !project.isEmpty())
- projectDescription = project + " Reference Documentation";
-
- projectUrl = config.getString(CONFIG_URL);
- tagFile_ = config.getString(CONFIG_TAGFILE);
-
-#ifndef QT_NO_TEXTCODEC
- outputEncoding = config.getString(CONFIG_OUTPUTENCODING);
- if (outputEncoding.isEmpty())
- outputEncoding = QLatin1String("ISO-8859-1");
- outputCodec = QTextCodec::codecForName(outputEncoding.toLocal8Bit());
-#endif
-
- naturalLanguage = config.getString(CONFIG_NATURALLANGUAGE);
- if (naturalLanguage.isEmpty())
- naturalLanguage = QLatin1String("en");
-
- config.subVarsAndValues("dita.metadata.default",metadataDefaults);
- QSet<QString> editionNames = config.subVars(CONFIG_EDITION);
- QSet<QString>::ConstIterator edition = editionNames.constBegin();
- while (edition != editionNames.constEnd()) {
- QString editionName = *edition;
- QStringList editionModules = config.getStringList(CONFIG_EDITION +
- Config::dot +
- editionName +
- Config::dot +
- "modules");
- QStringList editionGroups = config.getStringList(CONFIG_EDITION +
- Config::dot +
- editionName +
- Config::dot +
- "groups");
-
- if (!editionModules.isEmpty())
- editionModuleMap[editionName] = editionModules;
- if (!editionGroups.isEmpty())
- editionGroupMap[editionName] = editionGroups;
-
- ++edition;
- }
-
- stylesheets = config.getStringList(DitaXmlGenerator::format() +
- Config::dot +
- DITAXMLGENERATOR_STYLESHEETS);
- customHeadElements = config.getStringList(DitaXmlGenerator::format() +
- Config::dot +
- DITAXMLGENERATOR_CUSTOMHEADELEMENTS);
- version = config.getString(CONFIG_VERSION);
- vrm = version.split(QLatin1Char('.'));
-}
-
-/*!
- Gracefully terminates the DITA XML output generator.
- */
-void DitaXmlGenerator::terminateGenerator()
-{
- Generator::terminateGenerator();
-}
-
-/*!
- Returns "DITAXML".
- */
-QString DitaXmlGenerator::format()
-{
- return "DITAXML";
-}
-
-/*!
- Calls lookupGuid() to get a GUID for \a text, then writes
- it to the XML stream as an "id" attribute, and returns it.
- */
-QString DitaXmlGenerator::writeGuidAttribute(QString text)
-{
- QString guid = lookupGuid(outFileName(),text);
- xmlWriter().writeAttribute("id",guid);
- return guid;
-}
-
-
-/*!
- Write's the GUID for the \a node to the current XML stream
- as an "id" attribute. If the \a node doesn't yet have a GUID,
- one is generated.
- */
-void DitaXmlGenerator::writeGuidAttribute(Node* node)
-{
- xmlWriter().writeAttribute("id",node->guid());
-}
-
-/*!
- Looks up \a text in the GUID map. If it finds \a text,
- it returns the associated GUID. Otherwise it inserts
- \a text into the map with a new GUID, and it returns
- the new GUID.
- */
-QString DitaXmlGenerator::lookupGuid(QString text)
-{
- QMap<QString, QString>::const_iterator i = name2guidMap.constFind(text);
- if (i != name2guidMap.constEnd())
- return i.value();
- QString guid = Node::cleanId(text);
- name2guidMap.insert(text,guid);
- return guid;
-}
-
-/*!
- First, look up the GUID map for \a fileName. If there isn't
- a GUID map for \a fileName, create one and insert it into
- the map of GUID maps. Then look up \a text in that GUID map.
- If \a text is found, return the associated GUID. Otherwise,
- insert \a text into the GUID map with a new GUID, and return
- the new GUID.
- */
-QString DitaXmlGenerator::lookupGuid(const QString& fileName, const QString& text)
-{
- GuidMap* gm = lookupGuidMap(fileName);
- GuidMap::const_iterator i = gm->constFind(text);
- if (i != gm->constEnd())
- return i.value();
- QString guid = Node::cleanId(text);
- gm->insert(text,guid);
- return guid;
-}
-
-/*!
- Looks up \a fileName in the map of GUID maps. If it finds
- \a fileName, it returns a pointer to the associated GUID
- map. Otherwise it creates a new GUID map and inserts it
- into the map of GUID maps with \a fileName as its key.
- */
-GuidMap* DitaXmlGenerator::lookupGuidMap(const QString& fileName)
-{
- GuidMaps::const_iterator i = guidMaps.constFind(fileName);
- if (i != guidMaps.constEnd())
- return i.value();
- GuidMap* gm = new GuidMap;
- guidMaps.insert(fileName,gm);
- return gm;
-}
-
-/*!
- Traverses the current tree generating all the DITA XML documentation.
- */
-void DitaXmlGenerator::generateDocs()
-{
- if (!preparing())
- Generator::generateDocs();
-
- if (!generating()) {
- QString fileBase = project.toLower().simplified().replace(QLatin1Char(' '), QLatin1Char('-'));
- qdb_->generateIndex(outputDir() + QLatin1Char('/') + fileBase + ".index",
- projectUrl,
- projectDescription,
- this,
- true);
- }
-
- if (!preparing()) {
- writeDitaMap();
- /*
- Generate the XML tag file, if it was requested.
- */
- qdb_->generateTagFile(tagFile_, this);
- }
-}
-
-static int countTableColumns(const Atom* t)
-{
- int result = 0;
- if (t->type() == Atom::TableHeaderLeft) {
- while (t->type() == Atom::TableHeaderLeft) {
- int count = 0;
- t = t->next();
- while (t->type() != Atom::TableHeaderRight) {
- if (t->type() == Atom::TableItemLeft) {
- for (int i=0; i<t->count(); ++i) {
- QString attr = t->string(i);
- if (!attr.contains('=')) {
- QStringList spans = attr.split(QLatin1Char(','));
- if (spans.size() == 2) {
- count += spans[0].toInt();
- }
- else {
- ++count;
- }
- }
- }
- }
- t = t->next();
- }
- if (count > result)
- result = count;
- t = t->next();
- }
- }
- else if (t->type() == Atom::TableRowLeft) {
- while (t->type() != Atom::TableRowRight) {
- if (t->type() == Atom::TableItemLeft) {
- for (int i=0; i<t->count(); ++i) {
- QString attr = t->string(i);
- if (!attr.contains('=')) {
- QStringList spans = attr.split(QLatin1Char(','));
- if (spans.size() == 2) {
- result += spans[0].toInt();
- }
- else {
- ++result;
- }
- }
- }
- }
- t = t->next();
- }
- }
- return result;
-}
-
-/*!
- Generate html from an instance of Atom.
- */
-int DitaXmlGenerator::generateAtom(const Atom *atom,
- const Node *relative,
- CodeMarker *marker)
-{
- int skipAhead = 0;
- QString hx, str;
- static bool in_para = false;
- QString guid, hc, attr;
-
- switch (atom->type()) {
- case Atom::AbstractLeft:
- break;
- case Atom::AbstractRight:
- break;
- case Atom::AutoLink:
- if (!noLinks && !inLink_ && !inContents_ && !inSectionHeading_) {
- const Node* node = 0;
- QString link = getAutoLink(atom, relative, &node);
- if (!link.isEmpty()) {
- beginLink(link);
- generateLink(atom, marker);
- endLink();
- }
- else {
- writeCharacters(protectEnc(atom->string()));
- }
- }
- else {
- writeCharacters(protectEnc(atom->string()));
- }
- break;
- case Atom::BaseName:
- break;
- case Atom::BriefLeft:
- {
- Node::Type t = relative->type();
- if (inSection()) {
- in_para = true;
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","brief");
- }
- else {
- noLinks = true;
- writeStartTag(DT_shortdesc);
- }
- if (t == Node::Property || t == Node::Variable) {
- xmlWriter().writeCharacters("This ");
- if (relative->type() == Node::Property)
- xmlWriter().writeCharacters("property");
- else if (relative->type() == Node::Variable)
- xmlWriter().writeCharacters("variable");
- xmlWriter().writeCharacters(" holds ");
- }
- if (noLinks) {
- atom = atom->next();
- while (atom != 0 && atom->type() != Atom::BriefRight) {
- if (atom->type() == Atom::String ||
- atom->type() == Atom::AutoLink)
- str += atom->string();
- skipAhead++;
- atom = atom->next();
- }
- if (t == Node::Property || t == Node::Variable)
- str[0] = str[0].toLower();
- if (str.endsWith(QLatin1Char('.')))
- str.truncate(str.length() - 1);
- writeCharacters(str + QLatin1Char('.'));
- }
- }
- break;
- case Atom::BriefRight:
- writeEndTag(); // </shortdesc> or </p>
- if (in_para)
- in_para = false;
- noLinks = false;
- break;
- case Atom::C:
- writeStartTag(DT_tt);
- if (inLink_) {
- writeCharacters(protectEnc(plainCode(atom->string())));
- }
- else {
- writeText(atom->string(), relative);
- }
- writeEndTag(); // see writeStartElement() above
- break;
- case Atom::Code:
- {
- writeStartTag(DT_codeblock);
- xmlWriter().writeAttribute("outputclass","cpp");
- writeCharacters("\n");
- writeText(trimmedTrailing(atom->string()), relative);
- writeEndTag(); // </codeblock>
- }
- break;
- case Atom::Qml:
- writeStartTag(DT_codeblock);
- xmlWriter().writeAttribute("outputclass","qml");
- writeCharacters("\n");
- writeText(trimmedTrailing(atom->string()), relative);
- writeEndTag(); // </codeblock>
- break;
- case Atom::CodeNew:
- writeStartTag(DT_p);
- xmlWriter().writeCharacters("you can rewrite it as");
- writeEndTag(); // </p>
- writeStartTag(DT_codeblock);
- writeCharacters("\n");
- writeText(trimmedTrailing(atom->string()), relative);
- writeEndTag(); // </codeblock>
- break;
- case Atom::CodeOld:
- writeStartTag(DT_p);
- xmlWriter().writeCharacters("For example, if you have code like");
- writeEndTag(); // </p>
- // fallthrough
- case Atom::CodeBad:
- writeStartTag(DT_codeblock);
- writeCharacters("\n");
- writeCharacters(trimmedTrailing(plainCode(atom->string())));
- writeEndTag(); // </codeblock>
- break;
- case Atom::DivLeft:
- {
- bool inStartElement = false;
- attr = atom->string();
- DitaTag t = currentTag();
- if ((t == DT_section) || (t == DT_sectiondiv)) {
- writeStartTag(DT_sectiondiv);
- divNestingLevel++;
- inStartElement = true;
- }
- else if ((t == DT_body) || (t == DT_bodydiv)) {
- writeStartTag(DT_bodydiv);
- divNestingLevel++;
- inStartElement = true;
- }
- if (!attr.isEmpty()) {
- if (attr.contains('=')) {
- int index = 0;
- int from = 0;
- QString values;
- while (index >= 0) {
- index = attr.indexOf('"',from);
- if (index >= 0) {
- ++index;
- from = index;
- index = attr.indexOf('"',from);
- if (index > from) {
- if (!values.isEmpty())
- values.append(' ');
- values += attr.mid(from,index-from);
- from = index+1;
- }
- }
- }
- attr = values;
- }
- }
- if (inStartElement)
- xmlWriter().writeAttribute("outputclass", attr);
- }
- break;
- case Atom::DivRight:
- if ((currentTag() == DT_sectiondiv) || (currentTag() == DT_bodydiv)) {
- writeEndTag(); // </sectiondiv>, </bodydiv>, or </p>
- if (divNestingLevel > 0)
- --divNestingLevel;
- }
- break;
- case Atom::FootnoteLeft:
- // ### For now
- if (in_para) {
- writeEndTag(); // </p>
- in_para = false;
- }
- xmlWriter().writeCharacters("<!-- ");
- break;
- case Atom::FootnoteRight:
- // ### For now
- xmlWriter().writeCharacters("-->");
- break;
- case Atom::FormatElse:
- case Atom::FormatEndif:
- case Atom::FormatIf:
- break;
- case Atom::FormattingLeft:
- {
- DitaTag t = DT_LAST;
- if (atom->string() == ATOM_FORMATTING_BOLD)
- t = DT_b;
- else if (atom->string() == ATOM_FORMATTING_PARAMETER)
- t = DT_i;
- else if (atom->string() == ATOM_FORMATTING_ITALIC)
- t = DT_i;
- else if (atom->string() == ATOM_FORMATTING_TELETYPE)
- t = DT_tt;
- else if (atom->string().startsWith("span ")) {
- t = DT_keyword;
- }
- else if (atom->string() == ATOM_FORMATTING_UICONTROL)
- t = DT_uicontrol;
- else if (atom->string() == ATOM_FORMATTING_UNDERLINE)
- t = DT_u;
- else if (atom->string() == ATOM_FORMATTING_INDEX)
- t = DT_comment;
- else if (atom->string() == ATOM_FORMATTING_SUBSCRIPT)
- t = DT_sub;
- else if (atom->string() == ATOM_FORMATTING_SUPERSCRIPT)
- t = DT_sup;
- else
- qDebug() << "DT_LAST";
- writeStartTag(t);
- if (atom->string() == ATOM_FORMATTING_PARAMETER) {
- if (atom->next() != 0 && atom->next()->type() == Atom::String) {
- QRegExp subscriptRegExp("([a-z]+)_([0-9n])");
- if (subscriptRegExp.exactMatch(atom->next()->string())) {
- xmlWriter().writeCharacters(subscriptRegExp.cap(1));
- writeStartTag(DT_sub);
- xmlWriter().writeCharacters(subscriptRegExp.cap(2));
- writeEndTag(); // </sub>
- skipAhead = 1;
- }
- }
- }
- else if (t == DT_keyword) {
- QString attr = atom->string().mid(5);
- if (!attr.isEmpty()) {
- if (attr.contains('=')) {
- int index = 0;
- int from = 0;
- QString values;
- while (index >= 0) {
- index = attr.indexOf('"',from);
- if (index >= 0) {
- ++index;
- from = index;
- index = attr.indexOf('"',from);
- if (index > from) {
- if (!values.isEmpty())
- values.append(' ');
- values += attr.mid(from,index-from);
- from = index+1;
- }
- }
- }
- attr = values;
- }
- }
- xmlWriter().writeAttribute("outputclass", attr);
- }
- }
- break;
- case Atom::FormattingRight:
- if (atom->string() == ATOM_FORMATTING_LINK) {
- endLink();
- }
- else {
- writeEndTag(); // ?
- }
- break;
- case Atom::AnnotatedList:
- {
- GroupNode* gn = qdb_->getGroup(atom->string());
- if (gn)
- generateAnnotatedList(relative, marker, gn->members());
- }
- break;
- case Atom::GeneratedList:
- if (atom->string() == "annotatedclasses") {
- generateAnnotatedList(relative, marker, qdb_->getCppClasses());
- }
- else if (atom->string() == "classes") {
- generateCompactList(Generic, relative, qdb_->getCppClasses(), true, QStringLiteral("Q"));
- }
- else if (atom->string() == "qmlclasses") {
- generateCompactList(Generic, relative, qdb_->getQmlTypes(), true, QStringLiteral(""));
- }
- else if (atom->string().contains("classesbymodule")) {
- QString arg = atom->string().trimmed();
- QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed();
- QDocDatabase* qdb = QDocDatabase::qdocDB();
- ModuleNode* mn = qdb->findModule(moduleName);
- if (mn) {
- NodeMap m;
- mn->getMemberClasses(m);
- if (!m.isEmpty()) {
- generateAnnotatedList(relative, marker, m);
- }
- }
- }
- else if (atom->string() == "classhierarchy") {
- generateClassHierarchy(relative, qdb_->getCppClasses());
- }
- else if (atom->string() == "compatclasses") {
- // "compatclasses" is no longer used. Delete this at some point.
- // mws 03/10/2013
- generateCompactList(Generic, relative, qdb_->getCompatibilityClasses(), false, QStringLiteral("Q"));
- }
- else if (atom->string() == "obsoleteclasses") {
- generateCompactList(Generic, relative, qdb_->getObsoleteClasses(), false, QStringLiteral("Q"));
- }
- else if (atom->string() == "obsoleteqmltypes") {
- generateCompactList(Generic, relative, qdb_->getObsoleteQmlTypes(), false, QStringLiteral(""));
- }
- else if (atom->string() == "obsoletecppmembers") {
- generateCompactList(Obsolete, relative, qdb_->getClassesWithObsoleteMembers(), false, QStringLiteral("Q"));
- }
- else if (atom->string() == "obsoleteqmlmembers") {
- generateCompactList(Obsolete, relative, qdb_->getQmlTypesWithObsoleteMembers(), false, QStringLiteral(""));
- }
- else if (atom->string() == "functionindex") {
- generateFunctionIndex(relative);
- }
- else if (atom->string() == "legalese") {
- generateLegaleseList(relative, marker);
- }
- else if (atom->string() == "mainclasses") {
- // "mainclasses" is no longer used. Delete this at some point.
- // mws 03/10/2013
- generateCompactList(Generic, relative, qdb_->getMainClasses(), true, QStringLiteral("Q"));
- }
- else if (atom->string() == "services") {
- // "services" is no longer used. Delete this at some point.
- // mws 03/10/2013
- generateCompactList(Generic, relative, qdb_->getServiceClasses(), false, QStringLiteral("Q"));
- }
- else if (atom->string() == "overviews") {
- generateOverviewList(relative);
- }
- else if (atom->string() == "namespaces") {
- generateAnnotatedList(relative, marker, qdb_->getNamespaces());
- }
- else if (atom->string() == "related") {
- if (relative && relative->isCollectionNode()) {
- const CollectionNode* cn = static_cast<const CollectionNode *>(relative);
- if (cn)
- generateAnnotatedList(cn, marker, cn->members());
- }
- }
- break;
- case Atom::SinceList:
- {
- const NodeMultiMap& nsmap = qdb_->getSinceMap(atom->string());
- const NodeMap& ncmap = qdb_->getClassMap(atom->string());
- const NodeMap& nqcmap = qdb_->getQmlTypeMap(atom->string());
- if (!nsmap.isEmpty()) {
- QList<Section> sections;
- QList<Section>::ConstIterator s;
-
- for (int i=0; i<LastSinceType; ++i)
- sections.append(Section(sinceTitle(i),QString(),QString(),QString()));
-
- NodeMultiMap::const_iterator n = nsmap.constBegin();
- while (n != nsmap.constEnd()) {
- const Node* node = n.value();
- switch (node->type()) {
- case Node::QmlType:
- sections[QmlClass].appendMember((Node*)node);
- break;
- case Node::Namespace:
- sections[Namespace].appendMember((Node*)node);
- break;
- case Node::Class:
- sections[Class].appendMember((Node*)node);
- break;
- case Node::Enum:
- sections[Enum].appendMember((Node*)node);
- break;
- case Node::Typedef:
- sections[Typedef].appendMember((Node*)node);
- break;
- case Node::Function: {
- const FunctionNode* fn = static_cast<const FunctionNode*>(node);
- if (fn->isMacro())
- sections[Macro].appendMember((Node*)node);
- else {
- Node* p = fn->parent();
- if (p) {
- if (p->type() == Node::Class)
- sections[MemberFunction].appendMember((Node*)node);
- else if (p->type() == Node::Namespace) {
- if (p->name().isEmpty())
- sections[GlobalFunction].appendMember((Node*)node);
- else
- sections[NamespaceFunction].appendMember((Node*)node);
- }
- else
- sections[GlobalFunction].appendMember((Node*)node);
- }
- else
- sections[GlobalFunction].appendMember((Node*)node);
- }
- break;
- }
- case Node::Property:
- sections[Property].appendMember((Node*)node);
- break;
- case Node::Variable:
- sections[Variable].appendMember((Node*)node);
- break;
- case Node::QmlProperty:
- sections[QmlProperty].appendMember((Node*)node);
- break;
- case Node::QmlSignal:
- sections[QmlSignal].appendMember((Node*)node);
- break;
- case Node::QmlSignalHandler:
- sections[QmlSignalHandler].appendMember((Node*)node);
- break;
- case Node::QmlMethod:
- sections[QmlMethod].appendMember((Node*)node);
- break;
- default:
- break;
- }
- ++n;
- }
-
- writeStartTag(DT_ul);
- s = sections.constBegin();
- while (s != sections.constEnd()) {
- if (!(*s).members.isEmpty()) {
- QString li = outFileName() + QLatin1Char('#') + Doc::canonicalTitle((*s).name);
- writeXrefListItem(li, (*s).name);
- }
- ++s;
- }
- writeEndTag(); // </ul>
-
- int idx = 0;
- s = sections.constBegin();
- while (s != sections.constEnd()) {
- if (!(*s).members.isEmpty()) {
- writeStartTag(DT_p);
- writeGuidAttribute(Doc::canonicalTitle((*s).name));
- xmlWriter().writeAttribute("outputclass","h3");
- writeCharacters(protectEnc((*s).name));
- writeEndTag(); // </p>
- if (idx == Class)
- generateCompactList(Generic, 0, ncmap, false, QString("Q"));
- else if (idx == QmlClass)
- generateCompactList(Generic, 0, nqcmap, false, QString("Q"));
- else if (idx == MemberFunction) {
- ParentMaps parentmaps;
- ParentMaps::iterator pmap;
- NodeList::const_iterator i = s->members.constBegin();
- while (i != s->members.constEnd()) {
- Node* p = (*i)->parent();
- pmap = parentmaps.find(p);
- if (pmap == parentmaps.end())
- pmap = parentmaps.insert(p,NodeMultiMap());
- pmap->insert((*i)->name(),(*i));
- ++i;
- }
- pmap = parentmaps.begin();
- while (pmap != parentmaps.end()) {
- NodeList nlist = pmap->values();
- writeStartTag(DT_p);
- xmlWriter().writeCharacters("Class ");
- writeStartTag(DT_xref);
- // formathtml
- xmlWriter().writeAttribute("href",linkForNode(pmap.key(), 0));
- QStringList pieces = pmap.key()->fullName().split("::");
- writeCharacters(protectEnc(pieces.last()));
- writeEndTag(); // </xref>
- xmlWriter().writeCharacters(":");
- writeEndTag(); // </p>
-
- generateSection(nlist, 0, marker, CodeMarker::Summary);
- ++pmap;
- }
- }
- else {
- generateSection(s->members, 0, marker, CodeMarker::Summary);
- }
- }
- ++idx;
- ++s;
- }
- }
- }
- break;
- case Atom::BR:
- // DITA XML can't do <br>
- break;
- case Atom::HR: //<p outputclass="horizontal-rule" />
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","horizontal-rule");
- writeEndTag(); // </p>
- break;
- case Atom::Image:
- case Atom::InlineImage:
- {
- QString fileName = imageFileName(relative, atom->string());
- QString text;
- if (atom->next() != 0)
- text = atom->next()->string();
- if (fileName.isEmpty()) {
- relative->location().warning(tr("Missing image: %1").arg(protectEnc(atom->string())));
- QString images = "images";
- if (!atom->string().isEmpty() && atom->string()[0] != '/')
- images.append(QLatin1Char('/'));
- fileName = images + atom->string();
- }
- if (relative && relative->isExample()) {
- const ExampleNode* cen = static_cast<const ExampleNode*>(relative);
- if (cen->imageFileName().isEmpty()) {
- ExampleNode* en = const_cast<ExampleNode*>(cen);
- en->setImageFileName(fileName);
- }
- }
-
- if (currentTag() != DT_xref && atom->type() != Atom::InlineImage)
- writeStartTag(DT_fig);
- writeStartTag(DT_image);
- writeHrefAttribute(protectEnc(fileName));
- if (atom->type() == Atom::Image) {
- xmlWriter().writeAttribute("placement","break");
- xmlWriter().writeAttribute("align","center");
- }
- if (!text.isEmpty()) {
- writeStartTag(DT_alt);
- writeCharacters(protectEnc(text));
- writeEndTag(); // </alt>
- }
- writeEndTag(); // </image>
- if (currentTag() != DT_xref && atom->type() != Atom::InlineImage)
- writeEndTag(); // </fig>
- }
- break;
- case Atom::ImageText:
- // nothing
- break;
- case Atom::ImportantLeft:
- writeStartTag(DT_note);
- xmlWriter().writeAttribute("type","important");
- break;
- case Atom::ImportantRight:
- writeEndTag(); // </note>
- break;
- case Atom::NoteLeft:
- writeStartTag(DT_note);
- xmlWriter().writeAttribute("type","note");
- break;
- case Atom::NoteRight:
- writeEndTag(); // </note>
- break;
- case Atom::LegaleseLeft:
- inLegaleseText = true;
- break;
- case Atom::LegaleseRight:
- inLegaleseText = false;
- break;
- case Atom::LineBreak:
- //xmlWriter().writeEmptyElement("br");
- break;
- case Atom::Link:
- {
- const Node *node = 0;
- QString link = getLink(atom, relative, &node);
- if (link.isEmpty() && !noLinkErrors())
- relative->doc().location().warning(tr("Can't link to '%1'").arg(atom->string()));
- else if (!inSectionHeading_)
- beginLink(link);
- skipAhead = 1;
- }
- break;
- case Atom::GuidLink:
- {
- beginLink(atom->string());
- skipAhead = 1;
- }
- break;
- case Atom::LinkNode:
- {
- const Node* node = CodeMarker::nodeForString(atom->string());
- beginLink(linkForNode(node, relative));
- skipAhead = 1;
- }
- break;
- case Atom::ListLeft:
- if (in_para) {
- writeEndTag(); // </p>
- in_para = false;
- }
- if (atom->string() == ATOM_LIST_BULLET) {
- writeStartTag(DT_ul);
- }
- else if (atom->string() == ATOM_LIST_TAG) {
- writeStartTag(DT_dl);
- }
- else if (atom->string() == ATOM_LIST_VALUE) {
- threeColumnEnumValueTable_ = isThreeColumnEnumValueTable(atom);
- if (threeColumnEnumValueTable_) {
- writeStartTag(DT_simpletable);
- xmlWriter().writeAttribute("outputclass","valuelist");
- writeStartTag(DT_sthead);
- writeStartTag(DT_stentry);
- xmlWriter().writeCharacters("Constant");
- writeEndTag(); // </stentry>
- writeStartTag(DT_stentry);
- xmlWriter().writeCharacters("Value");
- writeEndTag(); // </stentry>
- writeStartTag(DT_stentry);
- xmlWriter().writeCharacters("Description");
- writeEndTag(); // </stentry>
- writeEndTag(); // </sthead>
- }
- else {
- writeStartTag(DT_simpletable);
- xmlWriter().writeAttribute("outputclass","valuelist");
- writeStartTag(DT_sthead);
- writeStartTag(DT_stentry);
- xmlWriter().writeCharacters("Constant");
- writeEndTag(); // </stentry>
- writeStartTag(DT_stentry);
- xmlWriter().writeCharacters("Value");
- writeEndTag(); // </stentry>
- writeEndTag(); // </sthead>
- }
- }
- else {
- writeStartTag(DT_ol);
- if (atom->string() == ATOM_LIST_UPPERALPHA)
- xmlWriter().writeAttribute("outputclass","upperalpha");
- else if (atom->string() == ATOM_LIST_LOWERALPHA)
- xmlWriter().writeAttribute("outputclass","loweralpha");
- else if (atom->string() == ATOM_LIST_UPPERROMAN)
- xmlWriter().writeAttribute("outputclass","upperroman");
- else if (atom->string() == ATOM_LIST_LOWERROMAN)
- xmlWriter().writeAttribute("outputclass","lowerroman");
- else // (atom->string() == ATOM_LIST_NUMERIC)
- xmlWriter().writeAttribute("outputclass","numeric");
- if (atom->next() != 0 && atom->next()->string().toInt() != 1) {
- /*
- This attribute is not supported in DITA, and at the
- moment, including it is causing a validation error
- wherever it is used. I think it is only used in the
- qdoc manual.
- */
- //xmlWriter().writeAttribute("start",atom->next()->string());
- }
- }
- break;
- case Atom::ListItemNumber:
- // nothing
- break;
- case Atom::ListTagLeft:
- if (atom->string() == ATOM_LIST_TAG) {
- writeStartTag(DT_dt);
- }
- else { // (atom->string() == ATOM_LIST_VALUE)
- writeStartTag(DT_strow);
- writeStartTag(DT_stentry);
- writeStartTag(DT_tt);
- writeCharacters(protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(),
- relative))));
- writeEndTag(); // </tt>
- writeEndTag(); // </stentry>
- writeStartTag(DT_stentry);
-
- QString itemValue;
- if (relative->type() == Node::Enum) {
- const EnumNode *enume = static_cast<const EnumNode *>(relative);
- itemValue = enume->itemValue(atom->next()->string());
- }
-
- if (itemValue.isEmpty())
- xmlWriter().writeCharacters("?");
- else {
- writeStartTag(DT_tt);
- writeCharacters(protectEnc(itemValue));
- writeEndTag(); // </tt>
- }
- skipAhead = 1;
- }
- break;
- case Atom::ListTagRight:
- if (atom->string() == ATOM_LIST_TAG)
- writeEndTag(); // </dt>
- break;
- case Atom::ListItemLeft:
- if (atom->string() == ATOM_LIST_TAG) {
- writeStartTag(DT_dd);
- }
- else if (atom->string() == ATOM_LIST_VALUE) {
- if (threeColumnEnumValueTable_) {
- writeEndTag(); // </stentry>
- writeStartTag(DT_stentry);
- }
- }
- else {
- writeStartTag(DT_li);
- }
- if (matchAhead(atom, Atom::ParaLeft))
- skipAhead = 1;
- break;
- case Atom::ListItemRight:
- if (atom->string() == ATOM_LIST_TAG) {
- writeEndTag(); // </dd>
- }
- else if (atom->string() == ATOM_LIST_VALUE) {
- writeEndTag(); // </stentry>
- writeEndTag(); // </strow>
- }
- else {
- writeEndTag(); // </li>
- }
- break;
- case Atom::ListRight:
- if (atom->string() == ATOM_LIST_BULLET) {
- writeEndTag(); // </ul>
- }
- else if (atom->string() == ATOM_LIST_TAG) {
- writeEndTag(); // </dl>
- }
- else if (atom->string() == ATOM_LIST_VALUE) {
- writeEndTag(); // </simpletable>
- }
- else {
- writeEndTag(); // </ol>
- }
- break;
- case Atom::Nop:
- // nothing
- break;
- case Atom::ParaLeft:
- writeStartTag(DT_p);
- if (inLegaleseText)
- xmlWriter().writeAttribute("outputclass","legalese");
- in_para = true;
- break;
- case Atom::ParaRight:
- endLink();
- if (in_para) {
- writeEndTag(); // </p>
- in_para = false;
- }
- break;
- case Atom::QuotationLeft:
- writeStartTag(DT_lq);
- break;
- case Atom::QuotationRight:
- writeEndTag(); // </lq>
- break;
- case Atom::RawString:
- if (atom->string() == " ")
- break;
- if (atom->string().startsWith(QLatin1Char('&')))
- writeCharacters(atom->string());
- else if (atom->string() == "<sup>*</sup>") {
- writeStartTag(DT_sup);
- writeCharacters("*");
- writeEndTag(); // </sup>
- }
- else if (atom->string() == "<sup>&reg;</sup>") {
- writeStartTag(DT_tm);
- xmlWriter().writeAttribute("tmtype","reg");
- writeEndTag(); // </tm>
- }
- else {
- writeStartTag(DT_pre);
- xmlWriter().writeAttribute("outputclass","raw-html");
- writeCharacters(atom->string());
- writeEndTag(); // </pre>
- }
- break;
- case Atom::SectionLeft:
- enterSection("details",QString());
- break;
- case Atom::SectionRight:
- leaveSection();
- break;
- case Atom::SectionHeadingLeft:
- {
- writeStartTag(DT_p);
- QString id = Text::sectionHeading(atom).toString();
- id = stripMarkup(id);
- id = Doc::canonicalTitle(id);
- writeGuidAttribute(id);
- hx = QLatin1Char('h') + QString::number(atom->string().toInt() + hOffset(relative));
- xmlWriter().writeAttribute("outputclass",hx);
- inSectionHeading_ = true;
- }
- break;
- case Atom::SectionHeadingRight:
- writeEndTag(); // </title> (see case Atom::SectionHeadingLeft)
- inSectionHeading_ = false;
- break;
- case Atom::SidebarLeft:
- // nothing
- break;
- case Atom::SidebarRight:
- // nothing
- break;
- case Atom::String:
- if (inLink_ && !inContents_ && !inSectionHeading_) {
- generateLink(atom, marker);
- }
- else {
- writeCharacters(atom->string());
- }
- break;
- case Atom::TableLeft:
- {
- QString attr;
- if ((atom->count() > 0) && (atom->string(0) == "borderless"))
- attr = "borderless";
- else if ((atom->count() > 1) && (atom->string(1) == "borderless"))
- attr = "borderless";
- if (in_para) {
- writeEndTag(); // </p>
- in_para = false;
- }
- writeStartTag(DT_table);
- if (!attr.isEmpty())
- xmlWriter().writeAttribute("outputclass",attr);
- numTableRows_ = 0;
- if (tableColumnCount != 0) {
- qDebug() << "ERROR: Nested tables!";
- tableColumnCount = 0;
- }
- tableColumnCount = countTableColumns(atom->next());
- writeStartTag(DT_tgroup);
- xmlWriter().writeAttribute("cols",QString::number(tableColumnCount));
- for (int i = 0; i < tableColumnCount; i++) {
- writeStartTag(DT_colspec);
- xmlWriter().writeAttribute("colname", QStringLiteral("col%1").arg(i));
- xmlWriter().writeAttribute("colnum", QString::number(i));
- xmlWriter().writeAttribute("colwidth", QStringLiteral("1*"));
- writeEndTag(); // DT_colspec
- }
- inTableHeader_ = false;
- inTableBody = false;
- }
- break;
- case Atom::TableRight:
- writeEndTag(); // </tbody>
- writeEndTag(); // </tgroup>
- writeEndTag(); // </table>
- inTableHeader_ = false;
- inTableBody = false;
- tableColumnCount = 0;
- currentColumn = 0;
- break;
- case Atom::TableHeaderLeft:
- if (inTableBody) {
- writeEndTag(); // </tbody>
- writeEndTag(); // </tgroup>
- writeEndTag(); // </table>
- inTableHeader_ = false;
- inTableBody = false;
- tableColumnCount = 0;
- writeStartTag(DT_table);
- numTableRows_ = 0;
- tableColumnCount = countTableColumns(atom);
- writeStartTag(DT_tgroup);
- xmlWriter().writeAttribute("cols",QString::number(tableColumnCount));
- }
- currentColumn = 0;
- writeStartTag(DT_thead);
- xmlWriter().writeAttribute("valign","top");
- writeStartTag(DT_row);
- xmlWriter().writeAttribute("valign","top");
- inTableHeader_ = true;
- inTableBody = false;
- break;
- case Atom::TableHeaderRight:
- writeEndTag(); // </row>
- if (matchAhead(atom, Atom::TableHeaderLeft)) {
- skipAhead = 1;
- writeStartTag(DT_row);
- xmlWriter().writeAttribute("valign","top");
- }
- else {
- writeEndTag(); // </thead>
- inTableHeader_ = false;
- inTableBody = true;
- writeStartTag(DT_tbody);
- }
- break;
- case Atom::TableRowLeft:
- if (!inTableHeader_ && !inTableBody) {
- inTableBody = true;
- writeStartTag(DT_tbody);
- }
- currentColumn = 0;
- writeStartTag(DT_row);
- attr = atom->string();
- if (!attr.isEmpty()) {
- if (attr.contains('=')) {
- int index = 0;
- int from = 0;
- QString values;
- while (index >= 0) {
- index = attr.indexOf('"',from);
- if (index >= 0) {
- ++index;
- from = index;
- index = attr.indexOf('"',from);
- if (index > from) {
- if (!values.isEmpty())
- values.append(' ');
- values += attr.mid(from,index-from);
- from = index+1;
- }
- }
- }
- attr = values;
- }
- xmlWriter().writeAttribute("outputclass", attr);
- }
- xmlWriter().writeAttribute("valign","top");
- break;
- case Atom::TableRowRight:
- writeEndTag(); // </row>
- break;
- case Atom::TableItemLeft:
- {
- QString values;
- writeStartTag(DT_entry);
- for (int i=0; i<atom->count(); ++i) {
- attr = atom->string(i);
- if (attr.contains('=')) {
- int index = 0;
- int from = 0;
- while (index >= 0) {
- index = attr.indexOf('"',from);
- if (index >= 0) {
- ++index;
- from = index;
- index = attr.indexOf('"',from);
- if (index > from) {
- if (!values.isEmpty())
- values.append(' ');
- values += attr.mid(from,index-from);
- from = index+1;
- }
- }
- }
- }
- else {
- QStringList spans = attr.split(QLatin1Char(','));
- if (spans.size() == 2) {
- if (spans[0].toInt()>1) {
- xmlWriter().writeAttribute("namest",QStringLiteral("col%1").arg(currentColumn));
- xmlWriter().writeAttribute("nameend",QStringLiteral("col%1")
- .arg(currentColumn + (spans[0].toInt() - 1)));
- }
- if (spans[1].toInt()>1)
- xmlWriter().writeAttribute("morerows",spans[1].simplified());
- currentColumn += spans[0].toInt();
- }
- }
- }
- if (!values.isEmpty())
- xmlWriter().writeAttribute("outputclass",values);
- if (matchAhead(atom, Atom::ParaLeft))
- skipAhead = 1;
- }
- break;
- case Atom::TableItemRight:
- if (inTableHeader_) {
- writeEndTag(); // </entry>
- }
- else {
- writeEndTag(); // </entry>
- }
- if (matchAhead(atom, Atom::ParaLeft))
- skipAhead = 1;
- break;
- case Atom::TableOfContents:
- {
- int numColumns = 1;
- const Node* node = relative;
-
- Doc::Sections sectionUnit = Doc::Section4;
- QStringList params = atom->string().split(QLatin1Char(','));
- QString columnText = params.at(0);
- QStringList pieces = columnText.split(QLatin1Char(' '), QString::SkipEmptyParts);
- if (pieces.size() >= 2) {
- columnText = pieces.at(0);
- pieces.pop_front();
- QString path = pieces.join(' ').trimmed();
- node = qdb_->findNodeForTarget(path, relative);
- if (!node)
- relative->doc().location().warning(tr("Cannot link to '%1'").arg(path));
- }
-
- if (params.size() == 2) {
- numColumns = qMax(columnText.toInt(), numColumns);
- sectionUnit = (Doc::Sections)params.at(1).toInt();
- }
-
- if (node)
- generateTableOfContents(node,
- marker,
- sectionUnit,
- numColumns,
- relative);
- }
- break;
- case Atom::Target:
- if (in_para) {
- writeEndTag(); // </p>
- in_para = false;
- }
- writeStartTag(DT_p);
- writeGuidAttribute(Doc::canonicalTitle(atom->string()));
- xmlWriter().writeAttribute("outputclass","target");
- //xmlWriter().writeCharacters(protectEnc(atom->string()));
- writeEndTag(); // </p>
- break;
- case Atom::UnhandledFormat:
- writeStartTag(DT_b);
- xmlWriter().writeAttribute("outputclass","error");
- xmlWriter().writeCharacters("<Missing DITAXML>");
- writeEndTag(); // </b>
- break;
- case Atom::UnknownCommand:
- writeStartTag(DT_b);
- xmlWriter().writeAttribute("outputclass","error unknown-command");
- writeCharacters(protectEnc(atom->string()));
- writeEndTag(); // </b>
- break;
- case Atom::QmlText:
- case Atom::EndQmlText:
- // don't do anything with these. They are just tags.
- break;
- default:
- // unknownAtom(atom);
- break;
- }
- return skipAhead;
-}
-
-/*!
- Generate a <cxxClass> element (and all the stuff inside it)
- for the C++ class represented by \a innerNode. \a marker is
- for marking up the code. I don't know what that means exactly.
- */
-void
-DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker)
-{
- QList<Section>::ConstIterator s;
-
- QString title;
- QString rawTitle;
- QString fullTitle;
- if (inner->type() == Node::Namespace) {
- const NamespaceNode* nsn = const_cast<NamespaceNode*>(static_cast<const NamespaceNode*>(inner));
- rawTitle = inner->plainName();
- fullTitle = inner->plainFullName();
- title = rawTitle + " Namespace";
-
- /*
- Note: Because the C++ specialization we are using
- has no <cxxNamespace> element, we are using the
- <cxxClass> element with an outputclass attribute
- set to "namespace" .
- */
- generateHeader(inner, fullTitle);
- generateBrief(inner, marker); // <shortdesc>
- writeProlog(inner);
-
- writeStartTag(DT_cxxClassDetail);
- writeStartTag(DT_cxxClassDefinition);
- writeLocation(nsn);
- writeEndTag(); // <cxxClassDefinition>
-
- enterDesc(DT_apiDesc,QString(),title);
- generateStatus(nsn, marker);
- generateThreadSafeness(nsn, marker);
- generateSince(nsn, marker);
-
- enterSection(QString(), QString());
- generateBody(nsn, marker);
- generateAlsoList(nsn, marker);
- leaveSection();
- leaveSection(); // </apiDesc>
-
- bool needOtherSection = false;
- QList<Section> summarySections;
- summarySections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
- if (!summarySections.isEmpty()) {
- enterSection("redundant",QString());
- s = summarySections.constBegin();
- while (s != summarySections.constEnd()) {
- if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
- if (!s->inherited.isEmpty())
- needOtherSection = true;
- }
- else {
- QString attr;
- if (!s->members.isEmpty()) {
- writeStartTag(DT_p);
- attr = cleanRef((*s).name).toLower() + " h2";
- xmlWriter().writeAttribute("outputclass",attr);
- writeCharacters(protectEnc((*s).name));
- writeEndTag(); // </title>
- generateSection(s->members, inner, marker, CodeMarker::Summary);
- generateSectionInheritedList(*s, inner);
- }
- if (!s->reimpMembers.isEmpty()) {
- QString name = QString("Reimplemented ") + (*s).name;
- attr = cleanRef(name).toLower() + " h2";
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass",attr);
- writeCharacters(protectEnc(name));
- writeEndTag(); // </title>
- generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
- generateSectionInheritedList(*s, inner);
- }
- }
- ++s;
- }
- if (needOtherSection) {
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","h3");
- xmlWriter().writeCharacters("Additional Inherited Members");
- writeEndTag(); // </title>
- s = summarySections.constBegin();
- while (s != summarySections.constEnd()) {
- if (s->members.isEmpty())
- generateSectionInheritedList(*s, inner);
- ++s;
- }
- }
- leaveSection();
- }
-
- writeEndTag(); // </cxxClassDetail>
-
- // not included: <related-links>
- // not included: <cxxClassNested>
-
- QList<Section> detailSections;
- detailSections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
- s = detailSections.constBegin();
- while (s != detailSections.constEnd()) {
- if ((*s).name == "Classes") {
- writeNestedClasses((*s),nsn);
- break;
- }
- ++s;
- }
-
- s = detailSections.constBegin();
- while (s != detailSections.constEnd()) {
- if ((*s).name == "Function Documentation") {
- writeFunctions((*s),nsn,marker);
- }
- else if ((*s).name == "Type Documentation") {
- writeEnumerations((*s),marker);
- writeTypedefs((*s),marker);
- }
- else if ((*s).name == "Namespaces") {
- qDebug() << "Nested namespaces" << outFileName();
- }
- else if ((*s).name == "Macro Documentation") {
- //writeMacros((*s),marker);
- }
- ++s;
- }
-
- generateLowStatusMembers(inner,marker,CodeMarker::Obsolete);
- generateLowStatusMembers(inner,marker,CodeMarker::Compat);
- writeEndTag(); // </cxxClass>
- }
- else if (inner->type() == Node::Class) {
- const ClassNode* cn = const_cast<ClassNode*>(static_cast<const ClassNode*>(inner));
- rawTitle = inner->plainName();
- fullTitle = inner->plainFullName();
- title = rawTitle + " Class";
-
- generateHeader(inner, fullTitle);
- generateBrief(inner, marker); // <shortdesc>
- writeProlog(inner);
-
- writeStartTag(DT_cxxClassDetail);
- writeStartTag(DT_cxxClassDefinition);
- writeStartTag(DT_cxxClassAccessSpecifier);
- xmlWriter().writeAttribute("value",inner->accessString());
- writeEndTag(); // <cxxClassAccessSpecifier>
- if (cn->isAbstract()) {
- writeStartTag(DT_cxxClassAbstract);
- xmlWriter().writeAttribute("name","abstract");
- xmlWriter().writeAttribute("value","abstract");
- writeEndTag(); // </cxxClassAbstract>
- }
- writeDerivations(cn); // <cxxClassDerivations>
-
- // not included: <cxxClassTemplateParameters>
-
- writeLocation(cn);
- writeEndTag(); // <cxxClassDefinition>
-
- enterDesc(DT_apiDesc,QString(),title);
- generateStatus(cn, marker);
- generateInherits(cn, marker);
- generateInheritedBy(cn, marker);
- generateThreadSafeness(cn, marker);
- generateSince(cn, marker);
- enterSection(QString(), QString());
- generateBody(cn, marker);
- generateAlsoList(cn, marker);
- leaveSection();
- leaveSection(); // </apiDesc>
-
- bool needOtherSection = false;
- QList<Section> summarySections;
- summarySections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
- if (!summarySections.isEmpty()) {
- enterSection("redundant",QString());
- s = summarySections.constBegin();
- while (s != summarySections.constEnd()) {
- if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
- if (!s->inherited.isEmpty())
- needOtherSection = true;
- }
- else {
- QString attr;
- if (!s->members.isEmpty()) {
- writeStartTag(DT_p);
- attr = cleanRef((*s).name).toLower() + " h2";
- xmlWriter().writeAttribute("outputclass",attr);
- writeCharacters(protectEnc((*s).name));
- writeEndTag(); // </p>
- generateSection(s->members, inner, marker, CodeMarker::Summary);
- generateSectionInheritedList(*s, inner);
- }
- if (!s->reimpMembers.isEmpty()) {
- QString name = QString("Reimplemented ") + (*s).name;
- attr = cleanRef(name).toLower() + " h2";
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass",attr);
- writeCharacters(protectEnc(name));
- writeEndTag(); // </p>
- generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
- generateSectionInheritedList(*s, inner);
- }
- }
- ++s;
- }
- if (needOtherSection) {
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","h3");
- xmlWriter().writeCharacters("Additional Inherited Members");
- writeEndTag(); // </p>
- s = summarySections.constBegin();
- while (s != summarySections.constEnd()) {
- if (s->members.isEmpty())
- generateSectionInheritedList(*s, inner);
- ++s;
- }
- }
- leaveSection();
- }
-
- // not included: <example> or <apiImpl>
-
- writeEndTag(); // </cxxClassDetail>
-
- // not included: <related-links>
- // not included: <cxxClassNested>
-
- QList<Section> detailSections;
- detailSections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
- s = detailSections.constBegin();
- while (s != detailSections.constEnd()) {
- if ((*s).name == "Member Function Documentation") {
- writeFunctions((*s),cn,marker);
- }
- else if ((*s).name == "Member Type Documentation") {
- writeEnumerations((*s),marker);
- writeTypedefs((*s),marker);
- }
- else if ((*s).name == "Member Variable Documentation") {
- writeDataMembers((*s),marker);
- }
- else if ((*s).name == "Property Documentation") {
- writeProperties((*s),marker);
- }
- else if ((*s).name == "Macro Documentation") {
- //writeMacros((*s),marker);
- }
- else if ((*s).name == "Related Non-Members") {
- QString attribute("related-non-member");
- writeFunctions((*s),cn,marker,attribute);
- }
- ++s;
- }
-
- generateLowStatusMembers(inner,marker,CodeMarker::Obsolete);
- generateLowStatusMembers(inner,marker,CodeMarker::Compat);
- writeEndTag(); // </cxxClass>
- }
- else if (inner->isHeaderFile()) {
- const DocNode* dn = const_cast<DocNode*>(static_cast<const DocNode*>(inner));
- rawTitle = inner->plainName();
- fullTitle = inner->plainFullName();
- title = rawTitle;
-
- /*
- Note: Because the C++ specialization we are using
- has no <cxxHeaderFile> element, we are using the
- <cxxClass> element with an outputclass attribute
- set to "headerfile" .
- */
- generateHeader(inner, fullTitle);
- generateBrief(inner, marker); // <shortdesc>
- writeProlog(inner);
-
- writeStartTag(DT_cxxClassDetail);
- enterDesc(DT_apiDesc,QString(),title);
- generateStatus(dn, marker);
- generateThreadSafeness(dn, marker);
- generateSince(dn, marker);
- generateSince(dn, marker);
- enterSection(QString(), QString());
- generateBody(dn, marker);
- generateAlsoList(dn, marker);
- leaveSection();
- leaveSection(); // </apiDesc>
-
- bool needOtherSection = false;
- QList<Section> summarySections;
- summarySections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
- if (!summarySections.isEmpty()) {
- enterSection("redundant",QString());
- s = summarySections.constBegin();
- while (s != summarySections.constEnd()) {
- if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
- if (!s->inherited.isEmpty())
- needOtherSection = true;
- }
- else {
- QString attr;
- if (!s->members.isEmpty()) {
- writeStartTag(DT_p);
- attr = cleanRef((*s).name).toLower() + " h2";
- xmlWriter().writeAttribute("outputclass",attr);
- writeCharacters(protectEnc((*s).name));
- writeEndTag(); // </p>
- generateSection(s->members, inner, marker, CodeMarker::Summary);
- generateSectionInheritedList(*s, inner);
- }
- if (!s->reimpMembers.isEmpty()) {
- QString name = QString("Reimplemented ") + (*s).name;
- attr = cleanRef(name).toLower() + " h2";
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass",attr);
- writeCharacters(protectEnc(name));
- writeEndTag(); // </p>
- generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
- generateSectionInheritedList(*s, inner);
- }
- }
- ++s;
- }
- if (needOtherSection) {
- enterSection("additional-inherited-members redundant",QString());
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","h3");
- xmlWriter().writeCharacters("Additional Inherited Members");
- writeEndTag(); // </p>
- s = summarySections.constBegin();
- while (s != summarySections.constEnd()) {
- if (s->members.isEmpty())
- generateSectionInheritedList(*s, inner);
- ++s;
- }
- }
- leaveSection();
- }
-
- writeEndTag(); // </cxxClassDetail>
-
- // not included: <related-links>
- // not included: <cxxClassNested>
-
- QList<Section> detailSections;
- detailSections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay);
- s = detailSections.constBegin();
- while (s != detailSections.constEnd()) {
- if ((*s).name == "Classes") {
- writeNestedClasses((*s),dn);
- break;
- }
- ++s;
- }
-
- s = detailSections.constBegin();
- while (s != detailSections.constEnd()) {
- if ((*s).name == "Function Documentation") {
- writeFunctions((*s),dn,marker);
- }
- else if ((*s).name == "Type Documentation") {
- writeEnumerations((*s),marker);
- writeTypedefs((*s),marker);
- }
- else if ((*s).name == "Namespaces") {
- qDebug() << "Nested namespaces" << outFileName();
- }
- else if ((*s).name == "Macro Documentation") {
- //writeMacros((*s),marker);
- }
- ++s;
- }
- generateLowStatusMembers(inner,marker,CodeMarker::Obsolete);
- generateLowStatusMembers(inner,marker,CodeMarker::Compat);
- writeEndTag(); // </cxxClass>
- }
- else if (inner->isQmlType()) {
- QmlClassNode* qcn = const_cast<QmlClassNode*>(static_cast<const QmlClassNode*>(inner));
- ClassNode* cn = qcn->classNode();
- rawTitle = inner->plainName();
- fullTitle = inner->plainFullName();
- title = rawTitle + " Type";
- Node::clearPropertyGroupCount();
-
- generateHeader(inner, fullTitle);
- generateBrief(inner, marker); // <shortdesc>
- writeProlog(inner);
-
- writeStartTag(DT_qmlTypeDetail);
- generateQmlModuleDef(qcn);
- generateQmlInherits(qcn,marker);
- generateQmlInheritedBy(qcn, marker);
- generateQmlInstantiates(qcn,marker);
- generateQmlSince(qcn);
-
- enterDesc(DT_apiDesc,QString(),title);
- enterSection(QString(), QString());
- generateBody(qcn, marker);
- if (cn) {
- generateQmlText(cn->doc().body(), cn, marker, qcn->name());
- generateAlsoList(cn, marker);
- }
- leaveSection();
- leaveSection(); // </apiDesc>
- writeEndTag(); // </qmlTypeDetail>
-
- QList<Section> members = marker->qmlSections(qcn,CodeMarker::Detailed);
- if (!members.isEmpty()) {
- s = members.constBegin();
- while (s != members.constEnd()) {
- if (!s->members.isEmpty()) {
- NodeList::ConstIterator m = (*s).members.constBegin();
- while (m != (*s).members.constEnd()) {
- generateDetailedQmlMember(*m, qcn, marker);
- ++m;
- }
- }
- ++s;
- }
- }
- writeEndTag(); // </apiRef>
- }
-}
-
-/*!
- Generate the DITA page for a qdoc file that doesn't map
- to an underlying c++ file.
- */
-void DitaXmlGenerator::generateQmlBasicTypePage(QmlBasicTypeNode* qbtn, CodeMarker* marker)
-{
- QList<Section> sections;
- QList<Section>::const_iterator s;
- QString fullTitle = "QML Basic Type: " + qbtn->fullTitle();
-
- generateHeader(qbtn, fullTitle);
- generateBrief(qbtn, marker); // <shortdesc>
- writeProlog(qbtn);
-
- writeStartTag(DT_body);
- enterSection(QString(), QString());
-
- if (!qbtn->doc().isEmpty()) {
- generateBody(qbtn, marker);
- generateAlsoList(qbtn, marker);
- }
- leaveSection(); // </section>
- if (!writeEndTag()) { // </body>
- qbtn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(qbtn->name()));
- return;
- }
- writeRelatedLinks(qbtn);
- writeEndTag(); // </topic>
-}
-
-/*!
- Write a list item for a \a link with the given \a text.
- */
-void DitaXmlGenerator::writeXrefListItem(const QString& link, const QString& text)
-{
- writeStartTag(DT_li);
- writeStartTag(DT_xref);
- // formathtml
- writeHrefAttribute(link);
- writeCharacters(text);
- writeEndTag(); // </xref>
- writeEndTag(); // </li>
-}
-
-/*!
- Generate the DITA page for a qdoc file that doesn't map
- to an underlying c++ file.
- */
-void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
-{
- /*
- If the dn node is a page node, and if the page type
- is DITA map page, write the node's contents as a dita
- map and return without doing anything else.
- */
- if (dn->subType() == Node::Page && dn->pageType() == Node::DitaMapPage) {
- const DitaMapNode* dmn = static_cast<const DitaMapNode*>(dn);
- writeDitaMap(dmn);
- return;
- }
-
- QList<Section> sections;
- QList<Section>::const_iterator s;
- QString fullTitle = dn->fullTitle();
-
- generateHeader(dn, fullTitle);
- generateBrief(dn, marker); // <shortdesc>
- writeProlog(dn);
-
- writeStartTag(DT_body);
- enterSection(QString(), QString());
-
- if (dn->doc().isEmpty()) {
- if (dn->subType() == Node::File) {
- Text text;
- Quoter quoter;
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass", "small-subtitle");
- text << dn->subTitle();
- generateText(text, dn, marker);
- writeEndTag(); // </p>
- Doc::quoteFromFile(dn->doc().location(), quoter, dn->name());
- QString code = quoter.quoteTo(dn->location(), QString(), QString());
- text.clear();
- text << Atom(Atom::Code, code);
- generateText(text, dn, marker);
- }
- }
- else {
- generateBody(dn, marker);
- generateAlsoList(dn, marker);
- }
- leaveSection(); // </section>
- if (!writeEndTag()) { // </body>
- dn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(dn->name()));
- return;
- }
- writeRelatedLinks(dn);
- writeEndTag(); // </topic>
-}
-
-/*!
- Generate the DITA XML file for a group, module, or QML module.
- */
-void DitaXmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marker)
-{
- QList<Section> sections;
- QList<Section>::const_iterator s;
- QString fullTitle = cn->fullTitle();
-
- generateHeader(cn, fullTitle);
- generateBrief(cn, marker); // <shortdesc>
- writeProlog(cn);
-
- writeStartTag(DT_body);
- enterSection(QString(), QString());
- if (cn->isModule()) {
- generateStatus(cn, marker);
- NodeMap nm;
- cn->getMemberNamespaces(nm);
- if (!nm.isEmpty()) {
- enterSection("h2","Namespaces");
- generateAnnotatedList(cn, marker, nm);
- leaveSection();
- }
- nm.clear();
- cn->getMemberClasses(nm);
- if (!nm.isEmpty()) {
- enterSection("h2","Classes");
- generateAnnotatedList(cn, marker, nm);
- leaveSection();
- }
- nm.clear();
- }
-
- if (!cn->doc().isEmpty()) {
- if (cn->isModule()) {
- enterSection(QString(), QString());
- generateBody(cn, marker);
- leaveSection();
- }
- else {
- generateBody(cn, marker);
- }
- generateAlsoList(cn, marker);
- generateAnnotatedList(cn, marker, cn->members());
- }
- leaveSection(); // </section>
- if (!writeEndTag()) { // </body>
- cn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(cn->name()));
- return;
- }
- writeRelatedLinks(cn);
- writeEndTag(); // </topic>
-}
-
-/*!
- This function writes a \e{<link>} element inside a
- \e{<related-links>} element.
-
- \sa writeRelatedLinks()
- */
-void DitaXmlGenerator::writeLink(const Node* node,
- const QString& text,
- const QString& role)
-{
- if (node) {
- QString link = fileName(node) + QLatin1Char('#') + node->guid();
- if (link.endsWith(QLatin1Char('#')))
- qDebug() << "LINK ENDS WITH #:" << link << outFileName();
- writeStartTag(DT_link);
- writeHrefAttribute(link);
- xmlWriter().writeAttribute("role", role);
- writeStartTag(DT_linktext);
- writeCharacters(text);
- writeEndTag(); // </linktext>
- writeEndTag(); // </link>
- }
-}
-
-/*!
- This function writes a \e{<related-links>} element, which
- contains the \c{next}, \c{previous}, and \c{start}
- links for topic pages that have them. Note that the
- value of the \e role attribute is \c{parent} for the
- \c{start} link.
- */
-void DitaXmlGenerator::writeRelatedLinks(const Node* node)
-{
- const Node* linkNode = 0;
- QPair<QString,QString> linkPair;
- if (node && !node->links().empty()) {
- writeStartTag(DT_relatedLinks);
- if (node->links().contains(Node::PreviousLink)) {
- linkPair = node->links()[Node::PreviousLink];
- linkNode = qdb_->findNodeForTarget(linkPair.first, node);
- if (!linkNode)
- node->doc().location().warning(tr("Cannot link to '%1'").arg(linkPair.first));
- if (linkNode && linkNode->isDocNode()) {
- const DocNode *docNode = static_cast<const DocNode*>(linkNode);
- linkPair.second = docNode->title();
- }
- writeLink(linkNode, linkPair.second, "previous");
- }
- if (node->links().contains(Node::NextLink)) {
- linkPair = node->links()[Node::NextLink];
- linkNode = qdb_->findNodeForTarget(linkPair.first, node);
- if (!linkNode)
- node->doc().location().warning(tr("Cannot link to '%1'").arg(linkPair.first));
- if (linkNode && linkNode->isDocNode()) {
- const DocNode *docNode = static_cast<const DocNode*>(linkNode);
- linkPair.second = docNode->title();
- }
- writeLink(linkNode, linkPair.second, "next");
- }
- if (node->links().contains(Node::StartLink)) {
- linkPair = node->links()[Node::StartLink];
- linkNode = qdb_->findNodeForTarget(linkPair.first, node);
- if (!linkNode)
- node->doc().location().warning(tr("Cannot link to '%1'").arg(linkPair.first));
- if (linkNode && linkNode->isDocNode()) {
- const DocNode *docNode = static_cast<const DocNode*>(linkNode);
- linkPair.second = docNode->title();
- }
- writeLink(linkNode, linkPair.second, "parent");
- }
- writeEndTag(); // </related-links>
- }
-}
-
-/*!
- Returns "dita" for this subclass of class Generator.
- */
-QString DitaXmlGenerator::fileExtension() const
-{
- return "dita";
-}
-
-/*!
- Writes an XML file header to the current XML stream. This
- depends on which kind of DITA XML file is being generated,
- which is determined by the \a node type and subtype and the
- \a subpage flag.
- */
-void DitaXmlGenerator::generateHeader(const Node* node, const QString& name)
-{
- if (!node)
- return;
-
- DitaTag mainTag = DT_cxxClass;
- DitaTag nameTag = DT_apiName;
- QString doctype;
- QString dtd;
- QString base;
- QString version;
- QString outputclass;
-
- if (node->isClass()) {
- mainTag = DT_cxxClass;
- nameTag = DT_apiName;
- dtd = "dtd/cxxClass.dtd";
- version = "0.7.0";
- doctype = "<!DOCTYPE " + ditaTags[mainTag] +
- " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" +
- version + "//EN\" \"" + dtd + "\">";
- }
- else if (node->isNamespace()) {
- mainTag = DT_cxxClass;
- nameTag = DT_apiName;
- dtd = "dtd/cxxClass.dtd";
- version = "0.7.0";
- doctype = "<!DOCTYPE " + ditaTags[mainTag] +
- " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" +
- version + "//EN\" \"" + dtd + "\">";
- outputclass = "namespace";
- }
- else if (node->isCollectionNode()) {
- mainTag = DT_topic;
- nameTag = DT_title;
- dtd = "dtd/topic.dtd";
- doctype = "<!DOCTYPE " + ditaTags[mainTag] +
- " PUBLIC \"-//OASIS//DTD DITA Topic//EN\" \"" + dtd + "\">";
- switch (node->type()) {
- case Node::Group:
- outputclass = "group";
- break;
- case Node::Module:
- outputclass = "module";
- break;
- case Node::QmlModule:
- outputclass = "qmlmodule";
- break;
- default:
- outputclass = "page";
- }
- }
- else if (node->isDocNode()) {
- if (node->isHeaderFile()) {
- mainTag = DT_cxxClass;
- nameTag = DT_apiName;
- dtd = "dtd/cxxClass.dtd";
- version = "0.7.0";
- doctype = "<!DOCTYPE " + ditaTags[mainTag] +
- " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" +
- version + "//EN\" \"" + dtd + "\">";
- outputclass = "headerfile";
- }
- else if (node->isQmlType()) {
- mainTag = DT_qmlType;
- nameTag = DT_apiName;
- dtd = "dtd/qmlType.dtd";
- version = "0.1.0";
- doctype = "<!DOCTYPE " + ditaTags[mainTag] +
- " PUBLIC \"-//NOKIA//DTD DITA QML Type" +
- "//EN\" \"" + dtd + "\">";
- outputclass = "QML-type";
- }
- else {
- mainTag = DT_topic;
- nameTag = DT_title;
- dtd = "dtd/topic.dtd";
- doctype = "<!DOCTYPE " + ditaTags[mainTag] +
- " PUBLIC \"-//OASIS//DTD DITA Topic//EN\" \"" + dtd + "\">";
- switch (node->subType()) {
- case Node::Page:
- outputclass = node->pageTypeString();
- break;
- case Node::Example:
- outputclass = "example";
- break;
- case Node::File:
- outputclass = "file";
- break;
- case Node::Image: // not used
- outputclass = "image";
- break;
- case Node::ExternalPage: // not used
- outputclass = "externalpage";
- break;
- default:
- outputclass = "page";
- }
- }
- }
-
- xmlWriter().writeDTD(doctype);
- xmlWriter().writeComment(node->doc().location().fileName());
- writeStartTag(mainTag);
- QString id = node->guid();
- xmlWriter().writeAttribute("id",id);
- if (!outputclass.isEmpty())
- xmlWriter().writeAttribute("outputclass",outputclass);
- writeStartTag(nameTag); // <title> or <apiName>
- if (!name.isEmpty())
- writeCharacters(name);
- else
- writeCharacters(node->name());
- writeEndTag(); // </title> or </apiName>
-}
-
-/*!
- Outputs the \e brief command as a <shortdesc> element.
- */
-void DitaXmlGenerator::generateBrief(const Node* node, CodeMarker* marker)
-{
- Text brief = node->doc().briefText(true); // zzz
- if (!brief.isEmpty()) {
- generateText(brief, node, marker);
- }
-}
-
-/*!
- zzz
- Generates a table of contents beginning at \a node.
- Currently just returns without writing anything.
- */
-void DitaXmlGenerator::generateTableOfContents(const Node* node,
- CodeMarker* marker,
- Doc::Sections sectionUnit,
- int numColumns,
- const Node* relative)
-
-{
- return;
- if (!node->doc().hasTableOfContents())
- return;
- QList<Atom *> toc = node->doc().tableOfContents();
- if (toc.isEmpty())
- return;
-
- QString nodeName;
- if (node != relative)
- nodeName = node->name();
-
- QStringList sectionNumber;
- int columnSize = 0;
-
- QString tdTag;
- if (numColumns > 1) {
- tdTag = "<td>"; /* width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";*/
- out() << "<table class=\"toc\">\n<tr class=\"topAlign\">"
- << tdTag << '\n';
- }
-
- // disable nested links in table of contents
- inContents_ = true;
- inLink_ = true;
-
- for (int i = 0; i < toc.size(); ++i) {
- Atom *atom = toc.at(i);
-
- int nextLevel = atom->string().toInt();
- if (nextLevel > (int)sectionUnit)
- continue;
-
- if (sectionNumber.size() < nextLevel) {
- do {
- out() << "<ul>";
- sectionNumber.append("1");
- } while (sectionNumber.size() < nextLevel);
- }
- else {
- while (sectionNumber.size() > nextLevel) {
- out() << "</ul>\n";
- sectionNumber.removeLast();
- }
- sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1);
- }
- int numAtoms;
- Text headingText = Text::sectionHeading(atom);
-
- if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) {
- out() << "</ul></td>" << tdTag << "<ul>\n";
- columnSize = 0;
- }
- out() << "<li>";
- out() << "<xref href=\""
- << nodeName
- << '#'
- << Doc::canonicalTitle(headingText.toString())
- << "\">";
- generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms);
- out() << "</xref></li>\n";
-
- ++columnSize;
- }
- while (!sectionNumber.isEmpty()) {
- out() << "</ul>\n";
- sectionNumber.removeLast();
- }
-
- if (numColumns > 1)
- out() << "</td></tr></table>\n";
-
- inContents_ = false;
- inLink_ = false;
-}
-
-void DitaXmlGenerator::generateLowStatusMembers(InnerNode* inner,
- CodeMarker* marker,
- CodeMarker::Status status)
-{
- QString attribute;
- if (status == CodeMarker::Compat)
- attribute = "Qt3-support";
- else if (status == CodeMarker::Obsolete)
- attribute = "obsolete";
- else
- return;
-
- QList<Section> sections = marker->sections(inner, CodeMarker::Detailed, status);
- QMutableListIterator<Section> j(sections);
- while (j.hasNext()) {
- if (j.next().members.size() == 0)
- j.remove();
- }
- if (sections.isEmpty())
- return;
-
- if (status == CodeMarker::Obsolete)
- inner->setObsoleteLink(fileBase(inner) + "-obsolete." + fileExtension());
-
- QList<Section>::ConstIterator s = sections.constBegin();
- while (s != sections.constEnd()) {
- if ((*s).name == "Member Function Documentation") {
- writeFunctions((*s),inner,marker,attribute);
- }
- else if ((*s).name == "Member Type Documentation") {
- writeEnumerations((*s),marker,attribute);
- writeTypedefs((*s),marker,attribute);
- }
- else if ((*s).name == "Member Variable Documentation") {
- writeDataMembers((*s),marker,attribute);
- }
- else if ((*s).name == "Property Documentation") {
- writeProperties((*s),marker,attribute);
- }
- else if ((*s).name == "Macro Documentation") {
- //writeMacros((*s),marker,attribute);
- }
- ++s;
- }
-}
-
-/*!
- Write the XML for the class hierarchy to the current XML stream.
- */
-void DitaXmlGenerator::generateClassHierarchy(const Node* relative, NodeMap& classMap)
-{
- if (classMap.isEmpty())
- return;
-
- NodeMap topLevel;
- NodeMap::Iterator c = classMap.begin();
- while (c != classMap.end()) {
- ClassNode* classe = static_cast<ClassNode*>(*c);
- if (classe->baseClasses().isEmpty())
- topLevel.insert(classe->name(), classe);
- ++c;
- }
-
- QStack<NodeMap > stack;
- stack.push(topLevel);
-
- writeStartTag(DT_ul);
- while (!stack.isEmpty()) {
- if (stack.top().isEmpty()) {
- stack.pop();
- writeEndTag(); // </ul>
- if (!stack.isEmpty())
- writeEndTag(); // </li>
- }
- else {
- ClassNode* child = static_cast<ClassNode*>(*stack.top().begin());
- writeStartTag(DT_li);
- generateFullName(child, relative);
- writeEndTag(); // </li>
- stack.top().erase(stack.top().begin());
-
- NodeMap newTop;
- foreach (const RelatedClass &d, child->derivedClasses()) {
- if (d.node_ && d.access_ != Node::Private && !d.node_->doc().isEmpty())
- newTop.insert(d.node_->name(), d.node_);
- }
- if (!newTop.isEmpty()) {
- stack.push(newTop);
- writeStartTag(DT_li);
- writeStartTag(DT_ul);
- }
- }
- }
-}
-
-/*!
- Output an annotated list of the nodes in \a nodeMap.
- A two-column table is output.
- */
-void DitaXmlGenerator::generateAnnotatedList(const Node* relative,
- CodeMarker* marker,
- const NodeMap& nodeMap)
-{
- if (nodeMap.isEmpty())
- return;
- NodeList nl;
- NodeMap::const_iterator i = nodeMap.begin();
- while (i != nodeMap.end()) {
- nl.append(i.value());
- ++i;
- }
- generateAnnotatedList(relative, marker, nl);
-}
-
-/*!
- Write XML for the contents of the \a nodes to the current
- XML stream.
- */
-void DitaXmlGenerator::generateAnnotatedList(const Node* relative,
- CodeMarker* marker,
- const NodeList& nodes)
-{
- if (nodes.isEmpty())
- return;
- bool allInternal = true;
- foreach (const Node* node, nodes) {
- if (!node->isInternal() && node->status() != Node::Obsolete) {
- allInternal = false;
- }
- }
- if (allInternal)
- return;
-
- writeStartTag(DT_table);
- xmlWriter().writeAttribute("outputclass","annotated");
- writeStartTag(DT_tgroup);
- xmlWriter().writeAttribute("cols","2");
- writeStartTag(DT_tbody);
-
- foreach (const Node* node, nodes) {
- if (node->isInternal() || node->status() == Node::Obsolete)
- continue;
-
- writeStartTag(DT_row);
- writeStartTag(DT_entry);
- writeStartTag(DT_p);
- generateFullName(node, relative);
- writeEndTag(); // </p>
- writeEndTag(); // <entry>
-
- if (!node->isDocNode()) {
- Text brief = node->doc().trimmedBriefText(node->name());
- if (!brief.isEmpty()) {
- writeStartTag(DT_entry);
- writeStartTag(DT_p);
- generateText(brief, node, marker);
- writeEndTag(); // </p>
- writeEndTag(); // <entry>
- }
- else if (!node->reconstitutedBrief().isEmpty()) {
- writeStartTag(DT_entry);
- writeStartTag(DT_p);
- writeCharacters(node->reconstitutedBrief());
- writeEndTag(); // </p>
- writeEndTag(); // <entry>
- }
- }
- else {
- writeStartTag(DT_entry);
- writeStartTag(DT_p);
- if (!node->reconstitutedBrief().isEmpty()) {
- writeCharacters(node->reconstitutedBrief());
- }
- else
- writeCharacters(protectEnc(node->doc().briefText().toString()));
- writeEndTag(); // </p>
- writeEndTag(); // <entry>
- }
- writeEndTag(); // </row>
- }
- writeEndTag(); // </tbody>
- writeEndTag(); // </tgroup>
- writeEndTag(); // </table>
-}
-
-/*!
- This function finds the common prefix of the names of all
- the classes in \a classMap and then generates a compact
- list of the class names alphabetized on the part of the
- name not including the common prefix. You can tell the
- function to use \a comonPrefix as the common prefix, but
- normally you let it figure it out itself by looking at
- the name of the first and last classes in \a classMap.
- */
-void DitaXmlGenerator::generateCompactList(ListType , // currently not needed for DITA
- const Node* relative,
- const NodeMap& classMap,
- bool includeAlphabet,
- QString commonPrefix)
-{
- const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_'
-
- if (classMap.isEmpty())
- return;
-
- /*
- If commonPrefix is not empty, then the caller knows what
- the common prefix is and has passed it in, so just use that
- one. But if the commonPrefix is empty (it normally is), then
- compute a common prefix using this simple algorithm. Note we
- assume the prefix length is 1, i.e. we will have a single
- character as the common prefix.
- */
- int commonPrefixLen = commonPrefix.length();
- if (commonPrefixLen == 0) {
- QVector<int> count(26);
- for (int i=0; i<26; ++i)
- count[i] = 0;
-
- NodeMap::const_iterator iter = classMap.constBegin();
- while (iter != classMap.constEnd()) {
- if (!iter.key().contains("::")) {
- QChar c = iter.key()[0];
- if ((c >= 'A') && (c <= 'Z')) {
- int idx = c.unicode() - QChar('A').unicode();
- ++count[idx];
- }
- }
- ++iter;
- }
- int highest = 0;
- int idx = -1;
- for (int i=0; i<26; ++i) {
- if (count[i] > highest) {
- highest = count[i];
- idx = i;
- }
- }
- idx += QChar('A').unicode();
- QChar common(idx);
- commonPrefix = common;
- commonPrefixLen = 1;
- }
-
- /*
- Divide the data into 37 paragraphs: 0, ..., 9, A, ..., Z,
- underscore (_). QAccel will fall in paragraph 10 (A) and
- QXtWidget in paragraph 33 (X). This is the only place where we
- assume that NumParagraphs is 37. Each paragraph is a NodeMap.
- */
- NodeMap paragraph[NumParagraphs+1];
- QString paragraphName[NumParagraphs+1];
- QSet<char> usedParagraphNames;
-
- NodeMap::ConstIterator c = classMap.constBegin();
- while (c != classMap.constEnd()) {
- QStringList pieces = c.key().split("::");
- QString key;
- int idx = commonPrefixLen;
- if (!pieces.last().startsWith(commonPrefix))
- idx = 0;
- if (pieces.size() == 1)
- key = pieces.last().mid(idx).toLower();
- else
- key = pieces.last().toLower();
-
- int paragraphNr = NumParagraphs - 1;
-
- if (key[0].digitValue() != -1) {
- paragraphNr = key[0].digitValue();
- }
- else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) {
- paragraphNr = 10 + key[0].unicode() - 'a';
- }
-
- paragraphName[paragraphNr] = key[0].toUpper();
- usedParagraphNames.insert(key[0].toLower().cell());
- paragraph[paragraphNr].insert(key, c.value());
- ++c;
- }
-
- /*
- Each paragraph j has a size: paragraph[j].count(). In the
- discussion, we will assume paragraphs 0 to 5 will have sizes
- 3, 1, 4, 1, 5, 9.
-
- We now want to compute the paragraph offset. Paragraphs 0 to 6
- start at offsets 0, 3, 4, 8, 9, 14, 23.
- */
- int paragraphOffset[NumParagraphs + 1]; // 37 + 1
- paragraphOffset[0] = 0;
- for (int i=0; i<NumParagraphs; i++) // i = 0..36
- paragraphOffset[i+1] = paragraphOffset[i] + paragraph[i].count();
-
- int curParNr = 0;
- int curParOffset = 0;
- QMap<QChar,QString> cmap;
-
- /*
- Output the alphabet as a row of links.
- */
- if (includeAlphabet) {
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","alphabet");
- for (int i = 0; i < 26; i++) {
- QChar ch('a' + i);
- if (usedParagraphNames.contains(char('a' + i))) {
- writeStartTag(DT_xref);
- // formathtml
- QString guid = lookupGuid(outFileName(),QString(ch));
- QString attr = outFileName() + QString("#%1").arg(guid);
- xmlWriter().writeAttribute("href", attr);
- xmlWriter().writeCharacters(QString(ch.toUpper()));
- writeEndTag(); // </xref>
- }
- }
- writeEndTag(); // </p>
- }
-
- /*
- Output a <p> element to contain all the <dl> elements.
- */
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","compactlist");
-
- for (int i=0; i<classMap.count()-1; i++) {
- while ((curParNr < NumParagraphs) &&
- (curParOffset == paragraph[curParNr].count())) {
- ++curParNr;
- curParOffset = 0;
- }
-
- /*
- Starting a new paragraph means starting a new <dl>.
- */
- if (curParOffset == 0) {
- if (i > 0) {
- writeEndTag(); // </dlentry>
- writeEndTag(); // </dl>
- }
- writeStartTag(DT_dl);
- writeStartTag(DT_dlentry);
- writeStartTag(DT_dt);
- if (includeAlphabet) {
- QChar c = paragraphName[curParNr][0].toLower();
- writeGuidAttribute(QString(c));
- }
- xmlWriter().writeAttribute("outputclass","sublist-header");
- xmlWriter().writeCharacters(paragraphName[curParNr]);
- writeEndTag(); // </dt>
- }
-
- /*
- Output a <dd> for the current offset in the current paragraph.
- */
- writeStartTag(DT_dd);
- if ((curParNr < NumParagraphs) &&
- !paragraphName[curParNr].isEmpty()) {
- NodeMap::Iterator it;
- it = paragraph[curParNr].begin();
- for (int i=0; i<curParOffset; i++)
- ++it;
-
- /*
- Previously, we used generateFullName() for this, but we
- require some special formatting.
- */
- writeStartTag(DT_xref);
- // formathtml
- writeHrefAttribute(linkForNode(it.value(), relative));
-
- QStringList pieces;
- if (it.value()->isQmlType())
- pieces << it.value()->name();
- else
- pieces = it.value()->fullName(relative).split("::");
- xmlWriter().writeCharacters(protectEnc(pieces.last()));
- writeEndTag(); // </xref>
- if (pieces.size() > 1) {
- xmlWriter().writeCharacters(" (");
- generateFullName(it.value()->parent(),relative);
- xmlWriter().writeCharacters(")");
- }
- }
- writeEndTag(); // </dd>
- curParOffset++;
- }
- writeEndTag(); // </dlentry>
- writeEndTag(); // </dl>
- writeEndTag(); // </p>
-}
-
-/*!
- Write XML for a function index to the current XML stream.
- */
-void DitaXmlGenerator::generateFunctionIndex(const Node* relative)
-{
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","alphabet");
- for (int i = 0; i < 26; i++) {
- QChar ch('a' + i);
- writeStartTag(DT_xref);
- // formathtml
- QString guid = lookupGuid(outFileName(),QString(ch));
- QString attr = outFileName() + QString("#%1").arg(guid);
- xmlWriter().writeAttribute("href", attr);
- xmlWriter().writeCharacters(QString(ch.toUpper()));
- writeEndTag(); // </xref>
-
- }
- writeEndTag(); // </p>
-
- char nextLetter = 'a';
- char currentLetter;
-
- writeStartTag(DT_ul);
- NodeMapMap& funcIndex = qdb_->getFunctionIndex();
- NodeMapMap::ConstIterator f = funcIndex.constBegin();
- while (f != funcIndex.constEnd()) {
- writeStartTag(DT_li);
- currentLetter = f.key()[0].unicode();
- while (islower(currentLetter) && currentLetter >= nextLetter) {
- writeStartTag(DT_p);
- writeGuidAttribute(QString(nextLetter));
- xmlWriter().writeAttribute("outputclass","target");
- xmlWriter().writeCharacters(QString(nextLetter));
- writeEndTag(); // </p>
- nextLetter++;
- }
- xmlWriter().writeCharacters(protectEnc(f.key()));
- xmlWriter().writeCharacters(":");
-
- NodeMap::ConstIterator s = (*f).constBegin();
- while (s != (*f).constEnd()) {
- generateFullName((*s)->parent(), relative, *s);
- ++s;
- }
- writeEndTag(); // </li>
- ++f;
- }
- writeEndTag(); // </ul>
-}
-
-/*!
- Write the legalese texts as XML to the current XML stream.
- */
-void DitaXmlGenerator::generateLegaleseList(const Node* relative, CodeMarker* marker)
-{
- TextToNodeMap& legaleseTexts = qdb_->getLegaleseTexts();
- TextToNodeMap::ConstIterator it = legaleseTexts.constBegin();
- while (it != legaleseTexts.constEnd()) {
- Text text = it.key();
- generateText(text, relative, marker);
- writeStartTag(DT_ul);
- do {
- writeStartTag(DT_li);
- generateFullName(it.value(), relative);
- writeEndTag(); // </li>
- ++it;
- } while (it != legaleseTexts.constEnd() && it.key() == text);
- writeEndTag(); //</ul>
- }
-}
-
-/*!
- Generate the text for the QML item described by \a node
- and write it to the current XML stream.
- */
-void DitaXmlGenerator::generateQmlItem(const Node* node,
- const Node* relative,
- CodeMarker* marker,
- bool summary)
-{
- QString marked = marker->markedUpQmlItem(node,summary);
- QRegExp tag("(<[^@>]*>)");
- if (marked.indexOf(tag) != -1) {
- QString tmp = protectEnc(marked.mid(tag.pos(1), tag.cap(1).length()));
- marked.replace(tag.pos(1), tag.cap(1).length(), tmp);
- }
- marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
- "<i>\\1<sub>\\2</sub></i>");
- if (summary) {
- marked.remove("<@type>");
- marked.remove("</@type>");
- }
- writeText(marked, relative);
-}
-
-/*!
- Write the XML for the overview list to the current XML stream.
- */
-void DitaXmlGenerator::generateOverviewList(const Node* relative)
-{
- CNMap groups;
- CNMap modules;
- CNMap qmlModules;
- QRegExp singleDigit("\\b([0-9])\\b");
-
- qdb_->mergeCollections(Node::Group, groups, relative);
- qdb_->mergeCollections(Node::Module, modules, relative);
- qdb_->mergeCollections(Node::QmlModule, qmlModules, relative);
-
- QStringList keys = groups.uniqueKeys();
- foreach (QString key, keys) {
- GroupNode* gn = static_cast<GroupNode*>(groups.value(key));
- if (gn) {
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","h3");
- writeStartTag(DT_xref);
- // formathtml
- xmlWriter().writeAttribute("href",linkForNode(gn, relative));
- writeCharacters(protectEnc(gn->fullTitle()));
- writeEndTag(); // </xref>
- writeEndTag(); // </p>
-
- if (gn->members().isEmpty())
- continue;
-
- NodeMap nm;
- foreach (Node* member, gn->members()) {
- if (member->isInternal() || member->isExample() || member->isExternalPage() ||
- member->isObsolete())
- continue;
- // not interested either in individual (Qt Designer etc.) manual chapters
- if (member->links().contains(Node::ContentsLink))
- continue;
- QString sortKey = member->fullTitle().toLower();
- if (sortKey.startsWith("the "))
- sortKey.remove(0, 4);
- sortKey.replace(singleDigit, "0\\1");
- nm.insert(sortKey, member);
- }
-
- writeStartTag(DT_ul);
- QStringList titles = nm.keys();
- foreach (QString t, titles) {
- Node* member = nm.value(t);
- QString title = member->fullTitle();
- if (title.startsWith("The "))
- title.remove(0, 4);
- writeStartTag(DT_li);
- writeStartTag(DT_xref);
- // formathtml
- xmlWriter().writeAttribute("href",linkForNode(member, relative));
- writeCharacters(protectEnc(title));
- writeEndTag(); // </xref>
- writeEndTag(); // </li>
- }
- writeEndTag(); // </ul>
- }
- }
-}
-
-/*!
- Write the XML for a standard section of a page, e.g.
- "Public Functions" or "Protected Slots." The section
- is written too the current XML stream as a table.
- */
-void DitaXmlGenerator::generateSection(const NodeList& nl,
- const Node* relative,
- CodeMarker* marker,
- CodeMarker::SynopsisStyle style)
-{
- if (!nl.isEmpty()) {
- writeStartTag(DT_ul);
- NodeList::ConstIterator m = nl.constBegin();
- while (m != nl.constEnd()) {
- if ((*m)->access() != Node::Private) {
- writeStartTag(DT_li);
- QString marked = getMarkedUpSynopsis(*m, relative, marker, style);
- writeText(marked, relative);
- writeEndTag(); // </li>
- }
- ++m;
- }
- writeEndTag(); // </ul>
- }
-}
-
-/*!
- Writes the "inherited from" list to the current XML stream.
- */
-void DitaXmlGenerator::generateSectionInheritedList(const Section& section, const Node* relative)
-{
- if (section.inherited.isEmpty())
- return;
- writeStartTag(DT_ul);
- QList<QPair<InnerNode*,int> >::ConstIterator p = section.inherited.constBegin();
- while (p != section.inherited.constEnd()) {
- writeStartTag(DT_li);
- QString text;
- text.setNum((*p).second);
- text += QLatin1Char(' ');
- if ((*p).second == 1)
- text += section.singularMember;
- else
- text += section.pluralMember;
- text += " inherited from ";
- writeCharacters(text);
- writeStartTag(DT_xref);
- // formathtml
- // zzz
- text = fileName((*p).first) + QLatin1Char('#');
- text += DitaXmlGenerator::cleanRef(section.name.toLower());
- xmlWriter().writeAttribute("href",text);
- text = protectEnc((*p).first->plainFullName(relative));
- writeCharacters(text);
- writeEndTag(); // </xref>
- writeEndTag(); // </li>
- ++p;
- }
- writeEndTag(); // </ul>
-}
-
-/*!
- Get the synopsis from the \a node using the \a relative
- node if needed, and mark up the synopsis using \a marker.
- Use the style to decide which kind of sysnopsis to build,
- normally \c Summary or \c Detailed. Return the marked up
- string.
- */
-QString DitaXmlGenerator::getMarkedUpSynopsis(const Node* node,
- const Node* relative,
- CodeMarker* marker,
- CodeMarker::SynopsisStyle style)
-{
- QString marked = marker->markedUpSynopsis(node, relative, style);
- QRegExp tag("(<[^@>]*>)");
- if (marked.indexOf(tag) != -1) {
- QString tmp = protectEnc(marked.mid(tag.pos(1), tag.cap(1).length()));
- marked.replace(tag.pos(1), tag.cap(1).length(), tmp);
- }
- marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])</@param>"),
- "<i> \\1<sub>\\2</sub></i>");
- if (style == CodeMarker::Summary) {
- marked.remove("<@name>"); // was "<b>"
- marked.remove("</@name>"); // was "</b>"
- }
-
- if (style == CodeMarker::Subpage) {
- QRegExp extraRegExp("<@extra>.*</@extra>");
- extraRegExp.setMinimal(true);
- marked.remove(extraRegExp);
- }
-
- if (style != CodeMarker::Detailed) {
- marked.remove("<@type>");
- marked.remove("</@type>");
- }
- return marked;
-}
-
-/*!
- Renamed from highlightedCode() in the html generator. Gets the text
- from \a markedCode , and then the text is written to the current XML
- stream.
- */
-void DitaXmlGenerator::writeText(const QString& markedCode, const Node* relative)
-{
- QString src = markedCode;
- QString text;
- QStringRef arg;
- QStringRef par1;
-
- const QChar charLangle = '<';
- const QChar charAt = '@';
-
- /*
- First strip out all the extraneous markup. The table
- below contains the markup we want to keep. Everything
- else that begins with "<@" or "</@" is stripped out.
- */
- static const QString spanTags[] = {
- "<@link ", "<@link ",
- "<@type>", "<@type>",
- "<@headerfile>", "<@headerfile>",
- "<@func>", "<@func>",
- "<@func ", "<@func ",
- "<@param>", "<@param>",
- "<@extra>", "<@extra>",
- "</@link>", "</@link>",
- "</@type>", "</@type>",
- "</@headerfile>", "</@headerfile>",
- "</@func>", "</@func>",
- "</@param>", "</@param>",
- "</@extra>", "</@extra>"
- };
- for (int i = 0, n = src.size(); i < n;) {
- if (src.at(i) == charLangle) {
- bool handled = false;
- for (int k = 0; k != 13; ++k) {
- const QString & tag = spanTags[2 * k];
- if (tag == QStringRef(&src, i, tag.length())) {
- text += spanTags[2 * k + 1];
- i += tag.length();
- handled = true;
- break;
- }
- }
- if (!handled) {
- ++i;
- if (src.at(i) == charAt ||
- (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) {
- // drop 'our' unknown tags (the ones still containing '@')
- while (i < n && src.at(i) != QLatin1Char('>'))
- ++i;
- ++i;
- }
- else {
- // retain all others
- text += charLangle;
- }
- }
- }
- else {
- text += src.at(i);
- ++i;
- }
- }
-
- // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
- // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
- src = text;
- text = QString();
- static const QString markTags[] = {
- // 0 1 2 3 4 5
- "link", "type", "headerfile", "func", "param", "extra"
- };
-
- for (int i = 0, n = src.size(); i < n;) {
- if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
- i += 2;
- for (int k = 0; k != 6; ++k) {
- if (parseArg(src, markTags[k], &i, n, &arg, &par1)) {
- const Node* n = 0;
- switch (k) {
- case 0: // <@link>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- n = CodeMarker::nodeForString(par1.toString());
- addLink(linkForNode(n, relative), arg);
- break;
- case 4: // <@param>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- writeStartTag(DT_i);
- //writeCharacters(" " + arg.toString());
- writeCharacters(arg.toString());
- writeEndTag(); // </i>
- break;
- case 5: // <@extra>
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- writeStartTag(DT_tt);
- writeCharacters(arg.toString());
- writeEndTag(); // </tt>
- break;
- case 3:
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- par1 = QStringRef();
- n = qdb_->findFunctionNode(arg.toString(), relative, Node::DontCare);
- addLink(linkForNode(n, relative), arg);
- break;
- case 1:
- case 2:
- default:
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- par1 = QStringRef();
- n = qdb_->findTypeNode(arg.toString(), relative);
- if (n && n->isQmlBasicType()) {
- if (relative && relative->isQmlType())
- addLink(linkForNode(n, relative), arg);
- else
- writeCharacters(arg.toString());
- }
- else
- addLink(linkForNode(n, relative), arg); // (zzz) Is this correct for all cases?
- break;
- } // switch
- break;
- }
- }
- }
- else
- text += src.at(i++);
- }
- if (!text.isEmpty())
- writeCharacters(text);
-}
-
-void DitaXmlGenerator::generateLink(const Atom* atom, CodeMarker* marker)
-{
- static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_");
-
- if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) {
- // hack for C++: move () outside of link
- int k = funcLeftParen.pos(1);
- writeCharacters(protectEnc(atom->string().left(k)));
- if (link_.isEmpty()) {
- if (showBrokenLinks)
- writeEndTag(); // </i>
- }
- else
- writeEndTag(); // </xref>
- inLink_ = false;
- writeCharacters(protectEnc(atom->string().mid(k)));
- }
- else if (marker->recognizeLanguage("Java")) {
- // hack for Java: remove () and use <tt> when appropriate
- bool func = atom->string().endsWith("()");
- bool tt = (func || atom->string().contains(camelCase));
- if (tt)
- writeStartTag(DT_tt);
- if (func)
- writeCharacters(protectEnc(atom->string().left(atom->string().length() - 2)));
- else
- writeCharacters(protectEnc(atom->string()));
- writeEndTag(); // </tt>
- }
- else
- writeCharacters(protectEnc(atom->string()));
-}
-
-QString DitaXmlGenerator::cleanRef(const QString& ref)
-{
- QString clean;
-
- if (ref.isEmpty())
- return clean;
-
- clean.reserve(ref.size() + 20);
- const QChar c = ref[0];
- const uint u = c.unicode();
-
- if ((u >= 'a' && u <= 'z') ||
- (u >= 'A' && u <= 'Z') ||
- (u >= '0' && u <= '9')) {
- clean += c;
- }
- else if (u == '~') {
- clean += "dtor.";
- }
- else if (u == '_') {
- clean += "underscore.";
- }
- else {
- clean += QLatin1Char('A');
- }
-
- for (int i = 1; i < (int) ref.length(); i++) {
- const QChar c = ref[i];
- const uint u = c.unicode();
- if ((u >= 'a' && u <= 'z') ||
- (u >= 'A' && u <= 'Z') ||
- (u >= '0' && u <= '9') || u == '-' ||
- u == '_' || u == ':' || u == '.') {
- clean += c;
- }
- else if (c.isSpace()) {
- clean += QLatin1Char('-');
- }
- else if (u == '!') {
- clean += "-not";
- }
- else if (u == '&') {
- clean += "-and";
- }
- else if (u == '<') {
- clean += "-lt";
- }
- else if (u == '=') {
- clean += "-eq";
- }
- else if (u == '>') {
- clean += "-gt";
- }
- else if (u == '#') {
- clean += QLatin1Char('#');
- }
- else {
- clean += QLatin1Char('-');
- clean += QString::number((int)u, 16);
- }
- }
- return clean;
-}
-
-QString DitaXmlGenerator::registerRef(const QString& ref)
-{
- QString clean = DitaXmlGenerator::cleanRef(ref);
-
- for (;;) {
- QString& prevRef = refMap[clean.toLower()];
- if (prevRef.isEmpty()) {
- prevRef = ref;
- break;
- }
- else if (prevRef == ref)
- break;
- clean += QLatin1Char('x');
- }
- return clean;
-}
-
-/*!
- Calls protect() with the \a string. Returns the result.
- */
-QString DitaXmlGenerator::protectEnc(const QString& string)
-{
-#ifndef QT_NO_TEXTCODEC
- return protect(string, outputEncoding);
-#else
- return protect(string);
-#endif
-}
-
-QString DitaXmlGenerator::protect(const QString& string, const QString& ) //outputEncoding)
-{
-#define APPEND(x) \
- if (xml.isEmpty()) { \
- xml = string; \
- xml.truncate(i); \
-} \
- xml += (x);
-
- QString xml;
- int n = string.length();
-
- for (int i = 0; i < n; ++i) {
- QChar ch = string.at(i);
-
- if (ch == QLatin1Char('&')) {
- APPEND("&amp;");
- }
- else if (ch == QLatin1Char('<')) {
- APPEND("&lt;");
- }
- else if (ch == QLatin1Char('>')) {
- APPEND("&gt;");
- }
- else if (ch == QLatin1Char('"')) {
- APPEND("&quot;");
- }
- else {
- if (!xml.isEmpty())
- xml += ch;
- }
- }
-
- if (!xml.isEmpty())
- return xml;
- return string;
-
-#undef APPEND
-}
-
-/*!
- Constructs a file name appropriate for the \a node
- and returns the file name.
- */
-QString DitaXmlGenerator::fileBase(const Node* node) const
-{
- QString result;
- result = Generator::fileBase(node);
- return result;
-}
-
-QString DitaXmlGenerator::guidForNode(const Node* node)
-{
- switch (node->type()) {
- case Node::Namespace:
- case Node::Class:
- default:
- break;
- case Node::Enum:
- return node->guid();
- case Node::Typedef:
- {
- const TypedefNode* tdn = static_cast<const TypedefNode*>(node);
- if (tdn->associatedEnum())
- return guidForNode(tdn->associatedEnum());
- }
- return node->guid();
- case Node::Function:
- {
- const FunctionNode* fn = static_cast<const FunctionNode*>(node);
- if (fn->associatedProperty()) {
- return guidForNode(fn->associatedProperty());
- }
- else {
- QString ref = fn->name();
- if (fn->overloadNumber() != 1) {
- ref += QLatin1Char('-') + QString::number(fn->overloadNumber());
- }
- }
- return fn->guid();
- }
- case Node::Document:
- break;
- case Node::QmlPropertyGroup:
- case Node::QmlProperty:
- case Node::Property:
- return node->guid();
- case Node::QmlSignal:
- return node->guid();
- case Node::QmlSignalHandler:
- return node->guid();
- case Node::QmlMethod:
- return node->guid();
- case Node::Variable:
- return node->guid();
- }
- return QString();
-}
-
-/*!
- Constructs a file name appropriate for the \a node and returns
- it. If the \a node is not a not an external page, an image, or
- a ditamap, call fileName() in the base class, Generator.
- */
-QString DitaXmlGenerator::fileName(const Node* node)
-{
- if (node->isDocNode()) {
- if (static_cast<const DocNode*>(node)->pageType() == Node::DitaMapPage)
- return node->name();
- if (static_cast<const DocNode*>(node)->subType() == Node::ExternalPage)
- return node->name();
- if (static_cast<const DocNode*>(node)->subType() == Node::Image)
- return node->name();
- }
- return Generator::fileName(node);
-}
-
-/*!
- This function is called for links, i.e. for words that
- are marked with the qdoc link command. For autolinks
- that are not marked with the qdoc link command, qdoc
- calls getAutoLink().
-
- Return the link represented by the \a atom, and set \a node
- to point to the target node for that link. \a relative points
- to the node holding the qdoc comment where the link command
- was found.
- */
-QString DitaXmlGenerator::getLink(const Atom *atom, const Node *relative, const Node** node)
-{
- const QString& t = atom->string();
- if (t.at(0) == QChar('h')) {
- if (t.startsWith("http:") || t.startsWith("https:"))
- return t;
- }
- else if (t.at(0) == QChar('f')) {
- if (t.startsWith("file:") || t.startsWith("ftp:"))
- return t;
- }
- else if (t.at(0) == QChar('m')) {
- if (t.startsWith("mailto:"))
- return t;
- }
-
- QString ref;
-
- *node = qdb_->findNodeForAtom(atom, relative, ref);
- if (!(*node))
- return QString();
-
- QString url = (*node)->url();
- if (!url.isEmpty()) {
- if (ref.isEmpty())
- return url;
- int hashtag = url.lastIndexOf(QChar('#'));
- if (hashtag != -1)
- url.truncate(hashtag);
- return url + "#" + ref;
- }
- /*
- Given that *node is not null, we now cconstruct a link
- to the page that *node represents, and then if we found
- a target on that page, we connect the target to the link
- with '#'.
- */
- QString link = linkForNode(*node, relative);
- if (*node && (*node)->subType() == Node::Image)
- link = "images/used-in-examples/" + link;
- if (!ref.isEmpty()) {
- int hashtag = link.lastIndexOf(QChar('#'));
- if (hashtag != -1)
- link.truncate(hashtag);
- link += QLatin1Char('#') + ref;
- }
- return link;
-}
-
-/*!
- This function is called for autolinks, i.e. for words that
- are not marked with the qdoc link command that qdoc has
- reason to believe should be links. For links marked with
- the qdoc link command, qdoc calls getLink().
-
- Return the link represented by the \a atom, and set \a node
- to point to the target node for that link. \a relative points
- to the node holding the qdoc comment where the link command
- was found.
- */
-QString DitaXmlGenerator::getAutoLink(const Atom *atom, const Node *relative, const Node** node)
-{
- QString ref;
- QString link;
-
- *node = qdb_->findNodeForAtom(atom, relative, ref);
- if (!(*node))
- return QString();
-
- QString url = (*node)->url();
- if (!url.isEmpty()) {
- if (ref.isEmpty())
- return url;
- int hashtag = url.lastIndexOf(QChar('#'));
- if (hashtag != -1)
- url.truncate(hashtag);
- return url + "#" + ref;
- }
-
- link = linkForNode(*node, relative);
- if (!ref.isEmpty())
- link += QLatin1Char('#') + ref;
- return link;
-}
-
-
-QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative)
-{
- if (node == 0 || node == relative)
- return QString();
- if (!node->url().isEmpty())
- return node->url();
- if (fileBase(node).isEmpty())
- return QString();
- if (node->access() == Node::Private)
- return QString();
-
- QString fn = fileName(node);
- if (node && relative && node->parent() != relative) {
- if (node->parent()->isQmlType() && relative->isQmlType()) {
- if (node->parent()->isAbstract()) {
- /*
- This is a bit of a hack. What we discover with
- the three 'if' statements immediately above,
- is that node's parent is marked \qmlabstract
- but the link appears in a qdoc comment for a
- subclass of the node's parent. This means the
- link should refer to the file for the relative
- node, not the file for node.
- */
- fn = fileName(relative);
- }
- }
- }
- QString link = fn;
-
- if (!node->isInnerNode() || node->type() == Node::QmlPropertyGroup) {
- QString guid = guidForNode(node);
- if (relative && fn == fileName(relative) && guid == guidForNode(relative)) {
- return QString();
- }
- link += QLatin1Char('#');
- link += guid;
- }
- /*
- If the output is going to subdirectories, then if the
- two nodes will be output to different directories, then
- the link must go up to the parent directory and then
- back down into the other subdirectory.
- */
- if (node && relative && (node != relative)) {
- if (useOutputSubdirs() && node->outputSubdirectory() != relative->outputSubdirectory())
- link.prepend(QString("../" + node->outputSubdirectory() + QLatin1Char('/')));
- }
- return link;
-}
-
-void DitaXmlGenerator::generateFullName(const Node* apparentNode,
- const Node* relative,
- const Node* actualNode)
-{
- if (actualNode == 0)
- actualNode = apparentNode;
- writeStartTag(DT_xref);
- // formathtml
- QString href = linkForNode(actualNode, relative);
- writeHrefAttribute(href);
- writeCharacters(protectEnc(apparentNode->fullName(relative)));
- writeEndTag(); // </xref>
-}
-
-/*!
- We're writing an attribute that indicates that the text
- data is a heading, hence, h1, h2, h3... etc, and we must
- decide which number to use.
- */
-int DitaXmlGenerator::hOffset(const Node* node)
-{
- switch (node->type()) {
- case Node::Namespace:
- case Node::Class:
- return 2;
- case Node::QmlType:
- case Node::Document:
- return 1;
- case Node::Enum:
- case Node::Typedef:
- case Node::Function:
- case Node::Property:
- default:
- return 3;
- }
-}
-
-bool DitaXmlGenerator::isThreeColumnEnumValueTable(const Atom* atom)
-{
- while (atom != 0 && !(atom->type() == Atom::ListRight && atom->string() == ATOM_LIST_VALUE)) {
- if (atom->type() == Atom::ListItemLeft && !matchAhead(atom, Atom::ListItemRight))
- return true;
- atom = atom->next();
- }
- return false;
-}
-
-const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node* node)
-{
- QPair<QString,QString> anchorPair;
- anchorPair.first = Generator::fileName(node);
- if (node->type() == Node::Document) {
- const DocNode *docNode = static_cast<const DocNode*>(node);
- anchorPair.second = docNode->title();
- }
-
- return anchorPair;
-}
-
-void DitaXmlGenerator::generateStatus(const Node* node, CodeMarker* marker)
-{
- Text text;
-
- switch (node->status()) {
- case Node::Obsolete:
- if (node->isInnerNode())
- Generator::generateStatus(node, marker);
- break;
- case Node::Compat:
- // Porting to Qt 4 no longer supported
- break;
- default:
- Generator::generateStatus(node, marker);
- }
-}
-
-void DitaXmlGenerator::beginLink(const QString& link)
-{
- link_ = link;
- if (link_.isEmpty())
- return;
- writeStartTag(DT_xref);
- // formathtml
- writeHrefAttribute(link_);
- inLink_ = true;
-}
-
-void DitaXmlGenerator::endLink()
-{
- if (inLink_) {
- if (link_.isEmpty()) {
- if (showBrokenLinks)
- writeEndTag(); // </i>
- }
- else {
- if (inObsoleteLink) {
- writeStartTag(DT_sup);
- xmlWriter().writeCharacters("(obsolete)");
- writeEndTag(); // </sup>
- }
- writeEndTag(); // </xref>
- }
- }
- inLink_ = false;
- inObsoleteLink = false;
-}
-
-/*!
- Generates the summary for the \a section. Only used for
- sections of QML element documentation.
-
- Currently handles only the QML property group.
- */
-void DitaXmlGenerator::generateQmlSummary(const Section& section,
- const Node* relative,
- CodeMarker* marker)
-{
- if (!section.members.isEmpty()) {
- writeStartTag(DT_ul);
- NodeList::ConstIterator m;
- m = section.members.constBegin();
- while (m != section.members.constEnd()) {
- writeStartTag(DT_li);
- generateQmlItem(*m,relative,marker,true);
- writeEndTag(); // </li>
- ++m;
- }
- writeEndTag(); // </ul>
- }
-}
-
-/*!
- Writes the QML property \a qpn to the current DITA XML file.
- Assumes that the correct start tag has already been written,
- but nothing has been written inside that tag. This function
- begins by writing the GUID id attribute for the property.
- */
-void DitaXmlGenerator::startQmlProperty(QmlPropertyNode* qpn,
- const InnerNode* relative,
- CodeMarker* marker)
-{
- writeStartTag(DT_qmlProperty);
- writeGuidAttribute((Node*)qpn);
- writeStartTag(DT_apiName);
- writeCharacters(qpn->name());
- writeEndTag(); // </apiName>
- generateBrief(qpn, marker); // <shortdesc>
- writeStartTag(DT_qmlPropertyDetail);
- writeStartTag(DT_qmlPropertyDef);
- if (!qpn->isReadOnlySet())
- qpn->setReadOnly(!qpn->isWritable());
- if (qpn->isReadOnly()) {
- writeStartTag(DT_qmlQualifier);
- xmlWriter().writeAttribute("name","read-only");
- xmlWriter().writeAttribute("value","read-only");
- writeEndTag(); // </qmlQualifier>
- }
- if (qpn->isDefault()) {
- writeStartTag(DT_qmlQualifier);
- xmlWriter().writeAttribute("name","default");
- xmlWriter().writeAttribute("value","default");
- writeEndTag(); // </qmlQualifier>
- }
- if (qpn->isAttached()) {
- writeStartTag(DT_qmlAttached);
- xmlWriter().writeAttribute("name","attached");
- xmlWriter().writeAttribute("value","yes");
- writeEndTag(); // </qmlAttached>
- }
- writeStartTag(DT_apiData);
- generateQmlItem(qpn, relative, marker, false);
- writeEndTag(); // </apiData>
- writeEndTag(); // </qmlPropertyDef>
-}
-
-/*!
- Outputs the DITA detailed documentation for a section
- on a QML element reference page.
- */
-void DitaXmlGenerator::generateDetailedQmlMember(Node* node,
- const InnerNode* relative,
- CodeMarker* marker)
-{
- QString marked;
- QmlPropertyNode* qpn = 0;
-
- if (node->type() == Node::QmlPropertyGroup) {
- const QmlPropertyGroupNode* qpgn = static_cast<const QmlPropertyGroupNode*>(node);
- NodeList::ConstIterator p = qpgn->childNodes().constBegin();
- if (qpgn->childNodes().size() == 1) {
- qpn = static_cast<QmlPropertyNode*>(*p);
- startQmlProperty(qpn,relative,marker);
- writeApiDesc(node, marker, node->title());
- writeEndTag(); // </qmlPropertyDetail>
- writeEndTag(); // </qmlProperty>
- }
- else {
- writeStartTag(DT_qmlPropertyGroup);
- QString id = "id-qml-propertygroup-" + node->name();
- id.replace('.','-');
- xmlWriter().writeAttribute("id",id);
- writeStartTag(DT_apiName);
- //writeCharacters("...");
- writeEndTag(); // </apiName>
- writeStartTag(DT_qmlPropertyGroupDetail);
- writeApiDesc(node, marker, node->title());
- writeEndTag(); // </qmlPropertyGroupDetail>
- while (p != qpgn->childNodes().constEnd()) {
- if ((*p)->type() == Node::QmlProperty) {
- qpn = static_cast<QmlPropertyNode*>(*p);
- startQmlProperty(qpn,relative,marker);
- writeEndTag(); // </qmlPropertyDetail>
- writeEndTag(); // </qmlProperty>
- }
- ++p;
- }
- writeEndTag(); // </qmlPropertyGroup
- }
- }
- else if (node->type() == Node::QmlProperty) {
- qpn = static_cast<QmlPropertyNode*>(node);
- startQmlProperty(qpn,relative,marker);
- writeApiDesc(node, marker, node->title());
- writeEndTag(); // </qmlPropertyDetail>
- writeEndTag(); // </qmlProperty>
- }
- else if (node->type() == Node::QmlSignal)
- writeQmlRef(DT_qmlSignal,node,relative,marker);
- else if (node->type() == Node::QmlSignalHandler)
- writeQmlRef(DT_qmlSignalHandler,node,relative,marker);
- else if (node->type() == Node::QmlMethod)
- writeQmlRef(DT_qmlMethod,node,relative,marker);
-}
-
-/*!
- Outputs the DITA detailed documentation for a section
- on a QML element reference page.
- */
-void DitaXmlGenerator::writeQmlRef(DitaTag tag,
- Node* node,
- const InnerNode* relative,
- CodeMarker* marker)
-{
- writeStartTag(tag);
- Node* n = const_cast<Node*>(node);
- writeGuidAttribute(n);
- writeStartTag(DT_apiName);
- writeCharacters(n->name());
- writeEndTag(); // </apiName>
- writeStartTag((DitaTag)((int)tag+2));
- writeStartTag((DitaTag)((int)tag+1));
- writeStartTag(DT_apiData);
- QString marked = getMarkedUpSynopsis(n, relative, marker, CodeMarker::Detailed);
- writeText(marked, relative);
- writeEndTag(); // </apiData>
- if (node->isAttached()) {
- writeStartTag(DT_qmlAttached);
- xmlWriter().writeAttribute("name","attached");
- xmlWriter().writeAttribute("value","yes");
- writeEndTag(); // </qmlAttached>
- }
- writeEndTag(); // </qmlXxxDef>
- writeApiDesc(node, marker, node->title());
- writeEndTag(); // </qmlXxxDetail>
- writeEndTag(); // tag
-}
-
-/*!
- This generates a <qmlTypeDef> in which the
- QML module name and version number are specified.
- */
-void DitaXmlGenerator::generateQmlModuleDef(QmlClassNode* qcn)
-{
- writeStartTag(DT_qmlImportModule);
- writeStartTag(DT_apiItemName);
- writeCharacters(qcn->qmlModuleName());
- writeEndTag(); // </apiItemName>
- writeStartTag(DT_apiData);
- writeCharacters(qcn->qmlModuleVersion());
- writeEndTag(); // </apiData>
- writeEndTag(); // </qmlImportModule>
-}
-
-/*!
- Output the "Inherits" line for the QML element,
- if there should be one.
- */
-void DitaXmlGenerator::generateQmlInherits(QmlClassNode* qcn, CodeMarker* marker)
-{
- if (!qcn)
- return;
- QmlClassNode* base = qcn->qmlBaseNode();
- while (base && base->isInternal()) {
- base = base->qmlBaseNode();
- }
- if (base) {
- writeStartTag(DT_qmlInherits);
- //writeStartTag(DT_qmlTypeDef);
- //xmlWriter().writeAttribute("outputclass","inherits");
- writeStartTag(DT_apiData);
- Text text;
- text << Atom(Atom::LinkNode,CodeMarker::stringForNode(base));
- text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
- text << Atom(Atom::String, base->name());
- text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
- generateText(text, qcn, marker);
- writeEndTag(); // </apiData>
- writeEndTag(); // </qmlInherits>
- }
-}
-
-/*!
- 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()) {
- writeStartTag(DT_qmlInheritedBy);
- //writeStartTag(DT_qmlTypeDef);
- //xmlWriter().writeAttribute("outputclass","inherited-by");
- writeStartTag(DT_apiData);
- Text text;
- appendSortedQmlNames(text,qcn,subs);
- text << Atom::ParaRight;
- generateText(text, qcn, marker);
- writeEndTag(); // </apiData>
- writeEndTag(); // </qmlIneritedBy>
- }
- }
-}
-
-/*!
- Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]"
- line for the QML element, if there should be one.
-
- If there is no class node, or if the class node status
- is set to Node::Internal, do nothing.
- */
-void DitaXmlGenerator::generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker)
-{
- ClassNode* cn = qcn->classNode();
- if (cn && (cn->status() != Node::Internal)) {
- writeStartTag(DT_qmlInstantiates);
- //writeStartTag(DT_qmlTypeDef);
- //xmlWriter().writeAttribute("outputclass","instantiates");
- writeStartTag(DT_apiData);
- Text text;
- text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
- text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
- text << Atom(Atom::String, cn->name());
- text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
- generateText(text, qcn, marker);
- writeEndTag(); // </apiData>
- writeEndTag(); // </qmlInstantiates>
- }
-}
-
-/*!
- Generate a <qmlXxxDef> for the "since" version string, if there is one.
- */
-void DitaXmlGenerator::generateQmlSince(const Node* node)
-{
- if (!node->since().isEmpty()) {
- writeStartTag(DT_qmlSince);
- //writeStartTag(DT_qmlTypeDef);
- //xmlWriter().writeAttribute("outputclass","since");
- writeStartTag(DT_apiItemName);
- QStringList pieces = node->since().split(QLatin1Char(' '));
- writeCharacters(pieces[0]);
- writeEndTag(); // </apiItemName>
- writeStartTag(DT_apiData);
- if (pieces.size() > 1)
- writeCharacters(pieces[1]);
- writeEndTag(); // </apiData>
- writeEndTag(); // </qmlSince>
- }
-}
-
-/*!
- Output the "[QmlGraphicsXxx is instantiated by QML Type Xxx]"
- line for the class, if there should be one.
-
- If there is no QML element, or if the class node status
- is set to Node::Internal, do nothing.
- */
-void DitaXmlGenerator::generateInstantiatedBy(ClassNode* cn, CodeMarker* marker)
-{
- if (cn && cn->status() != Node::Internal && cn->qmlElement() != 0) {
- const QmlClassNode* qcn = cn->qmlElement();
- writeStartTag(DT_p);
- xmlWriter().writeAttribute("outputclass","instantiated-by");
- Text text;
- text << "[";
- text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn));
- text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
- text << Atom(Atom::String, cn->name());
- text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
- text << " is instantiated by QML Type ";
- text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn));
- text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK);
- text << Atom(Atom::String, qcn->name());
- text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
- text << "]";
- generateText(text, cn, marker);
- writeEndTag(); // </p>
- }
-}
-
-/*!
- Return the full qualification of the node \a n, but without
- the name of \a n itself. e.g. A::B::C
- */
-QString DitaXmlGenerator::fullQualification(const Node* n)
-{
- QString fq;
- InnerNode* in = n->parent();
- while (in) {
- if ((in->type() == Node::Class) ||
- (in->type() == Node::Namespace)) {
- if (in->name().isEmpty())
- break;
- if (fq.isEmpty())
- fq = in->name();
- else
- fq = in->name() + "::" + fq;
- }
- else
- break;
- in = in->parent();
- }
- return fq;
-}
-
-/*!
- Outputs the <cxxClassDerivations> element.
- \code
- <cxxClassDerivations>
- <cxxClassDerivation>
- ...
- </cxxClassDerivation>
- ...
- </cxxClassDerivations>
- \endcode
-
- The <cxxClassDerivation> element is:
-
- \code
- <cxxClassDerivation>
- <cxxClassDerivationAccessSpecifier value="public"/>
- <cxxClassBaseClass href="class_base">Base</cxxClassBaseClass>
- </cxxClassDerivation>
- \endcode
- */
-void DitaXmlGenerator::writeDerivations(const ClassNode* cn)
-{
- QList<RelatedClass>::ConstIterator r;
-
- if (!cn->baseClasses().isEmpty()) {
- writeStartTag(DT_cxxClassDerivations);
- r = cn->baseClasses().constBegin();
- while (r != cn->baseClasses().constEnd()) {
- ClassNode* bcn = (*r).node_;
- if (bcn) {
- writeStartTag(DT_cxxClassDerivation);
- writeStartTag(DT_cxxClassDerivationAccessSpecifier);
- xmlWriter().writeAttribute("value",(*r).accessString());
- writeEndTag(); // </cxxClassDerivationAccessSpecifier>
-
- // not included: <cxxClassDerivationVirtual>
-
- writeStartTag(DT_cxxClassBaseClass);
- QString attr = fileName(bcn) + QLatin1Char('#') + bcn->guid();
- xmlWriter().writeAttribute("href",attr);
- writeCharacters(bcn->plainFullName());
- writeEndTag(); // </cxxClassBaseClass>
-
- // not included: <ClassBaseStruct> or <cxxClassBaseUnion>
-
- writeEndTag(); // </cxxClassDerivation>
-
- // not included: <cxxStructDerivation>
- }
- ++r;
- }
- writeEndTag(); // </cxxClassDerivations>
- }
-}
-
-/*!
- Writes a <cxxXXXAPIItemLocation> element, depending on the
- type of the node \a n, which can be a class, function, enum,
- typedef, or property.
- */
-void DitaXmlGenerator::writeLocation(const Node* n)
-{
- DitaTag s1, s2, s3a, s3b;
- s1 = DT_cxxClassAPIItemLocation;
- s2 = DT_cxxClassDeclarationFile;
- s3a = DT_cxxClassDeclarationFileLineStart;
- s3b = DT_cxxClassDeclarationFileLineEnd;
- if (n->type() == Node::Class || n->type() == Node::Namespace) {
- s1 = DT_cxxClassAPIItemLocation;
- s2 = DT_cxxClassDeclarationFile;
- s3a = DT_cxxClassDeclarationFileLineStart;
- s3b = DT_cxxClassDeclarationFileLineEnd;
- }
- else if (n->type() == Node::Function) {
- FunctionNode* fn = const_cast<FunctionNode*>(static_cast<const FunctionNode*>(n));
- if (fn->isMacro()) {
- s1 = DT_cxxDefineAPIItemLocation;
- s2 = DT_cxxDefineDeclarationFile;
- s3a = DT_cxxDefineDeclarationFileLine;
- s3b = DT_NONE;
- }
- else {
- s1 = DT_cxxFunctionAPIItemLocation;
- s2 = DT_cxxFunctionDeclarationFile;
- s3a = DT_cxxFunctionDeclarationFileLine;
- s3b = DT_NONE;
- }
- }
- else if (n->type() == Node::Enum) {
- s1 = DT_cxxEnumerationAPIItemLocation;
- s2 = DT_cxxEnumerationDeclarationFile;
- s3a = DT_cxxEnumerationDeclarationFileLineStart;
- s3b = DT_cxxEnumerationDeclarationFileLineEnd;
- }
- else if (n->type() == Node::Typedef) {
- s1 = DT_cxxTypedefAPIItemLocation;
- s2 = DT_cxxTypedefDeclarationFile;
- s3a = DT_cxxTypedefDeclarationFileLine;
- s3b = DT_NONE;
- }
- else if ((n->type() == Node::Property) ||
- (n->type() == Node::Variable)) {
- s1 = DT_cxxVariableAPIItemLocation;
- s2 = DT_cxxVariableDeclarationFile;
- s3a = DT_cxxVariableDeclarationFileLine;
- s3b = DT_NONE;
- }
- writeStartTag(s1);
- writeStartTag(s2);
- xmlWriter().writeAttribute("name","filePath");
- xmlWriter().writeAttribute("value",n->location().filePath());
- writeEndTag(); // <s2>
- writeStartTag(s3a);
- xmlWriter().writeAttribute("name","lineNumber");
- QString lineNr;
- xmlWriter().writeAttribute("value",lineNr.setNum(n->location().lineNo()));
- writeEndTag(); // </s3a>
- if (s3b != DT_NONE) {
- writeStartTag(s3b);
- xmlWriter().writeAttribute("name","lineNumber");
- QString lineNr;
- xmlWriter().writeAttribute("value",lineNr.setNum(n->location().lineNo()));
- writeEndTag(); // </s3b>
- }
- writeEndTag(); // </cxx<s1>ApiItemLocation>
-}
-
-/*!
- Write the <cxxFunction> elements.
- */
-void DitaXmlGenerator::writeFunctions(const Section& s,
- const InnerNode* parent,
- CodeMarker* marker,
- const QString& attribute)
-{
- NodeList::ConstIterator m = s.members.constBegin();
- while (m != s.members.constEnd()) {
- if ((*m)->type() == Node::Function) {
- FunctionNode* fn = const_cast<FunctionNode*>(static_cast<const FunctionNode*>(*m));
- writeStartTag(DT_cxxFunction);
- xmlWriter().writeAttribute("id",fn->guid());
- if (fn->metaness() == FunctionNode::Signal)
- xmlWriter().writeAttribute("otherprops","signal");
- else if (fn->metaness() == FunctionNode::Slot)
- xmlWriter().writeAttribute("otherprops","slot");
- if (!attribute.isEmpty())
- xmlWriter().writeAttribute("outputclass",attribute);
- writeStartTag(DT_apiName);
- writeCharacters(fn->name());
- writeEndTag(); // </apiName>
- generateBrief(fn,marker);
-
- // not included: <prolog>
-
- writeStartTag(DT_cxxFunctionDetail);
- writeStartTag(DT_cxxFunctionDefinition);
- writeStartTag(DT_cxxFunctionAccessSpecifier);
- xmlWriter().writeAttribute("value",fn->accessString());
- writeEndTag(); // <cxxFunctionAccessSpecifier>
-
- // not included: <cxxFunctionStorageClassSpecifierExtern>
-
- if (fn->isStatic()) {
- writeStartTag(DT_cxxFunctionStorageClassSpecifierStatic);
- xmlWriter().writeAttribute("name","static");
- xmlWriter().writeAttribute("value","static");
- writeEndTag(); // <cxxFunctionStorageClassSpecifierStatic>
- }
-
- // not included: <cxxFunctionStorageClassSpecifierMutable>,
-
- if (fn->isConst()) {
- writeStartTag(DT_cxxFunctionConst);
- xmlWriter().writeAttribute("name","const");
- xmlWriter().writeAttribute("value","const");
- writeEndTag(); // <cxxFunctionConst>
- }
-
- // not included: <cxxFunctionExplicit>
- // <cxxFunctionInline
-
- if (fn->virtualness() != FunctionNode::NonVirtual) {
- writeStartTag(DT_cxxFunctionVirtual);
- xmlWriter().writeAttribute("name","virtual");
- xmlWriter().writeAttribute("value","virtual");
- writeEndTag(); // <cxxFunctionVirtual>
- if (fn->virtualness() == FunctionNode::PureVirtual) {
- writeStartTag(DT_cxxFunctionPureVirtual);
- xmlWriter().writeAttribute("name","pure virtual");
- xmlWriter().writeAttribute("value","pure virtual");
- writeEndTag(); // <cxxFunctionPureVirtual>
- }
- }
-
- if (fn->name() == parent->name()) {
- writeStartTag(DT_cxxFunctionConstructor);
- xmlWriter().writeAttribute("name","constructor");
- xmlWriter().writeAttribute("value","constructor");
- writeEndTag(); // <cxxFunctionConstructor>
- }
- else if (fn->name()[0] == QChar('~')) {
- writeStartTag(DT_cxxFunctionDestructor);
- xmlWriter().writeAttribute("name","destructor");
- xmlWriter().writeAttribute("value","destructor");
- writeEndTag(); // <cxxFunctionDestructor>
- }
- else {
- writeStartTag(DT_cxxFunctionDeclaredType);
- QString src = marker->typified(fn->returnType());
- replaceTypesWithLinks(fn,parent,src);
- writeEndTag(); // <cxxFunctionDeclaredType>
- }
-
- // not included: <cxxFunctionReturnType>
-
- QString fq = fullQualification(fn);
- if (!fq.isEmpty()) {
- writeStartTag(DT_cxxFunctionScopedName);
- writeCharacters(fq);
- writeEndTag(); // <cxxFunctionScopedName>
- }
- writeStartTag(DT_cxxFunctionPrototype);
- writeCharacters(fn->signature(true));
- writeEndTag(); // <cxxFunctionPrototype>
-
- QString fnl = fn->signature(false);
- int idx = fnl.indexOf(' ');
- if (idx < 0)
- idx = 0;
- else
- ++idx;
- fnl = fn->parent()->name() + "::" + fnl.mid(idx);
- writeStartTag(DT_cxxFunctionNameLookup);
- writeCharacters(fnl);
- writeEndTag(); // <cxxFunctionNameLookup>
-
- if (!fn->isInternal() && fn->isReimp() && fn->reimplementedFrom() != 0) {
- FunctionNode* rfn = (FunctionNode*)fn->reimplementedFrom();
- if (rfn && !rfn->isInternal()) {
- writeStartTag(DT_cxxFunctionReimplemented);
- xmlWriter().writeAttribute("href",ditaXmlHref(rfn));
- writeCharacters(rfn->plainFullName());
- writeEndTag(); // </cxxFunctionReimplemented>
- }
- }
- writeParameters(fn,parent,marker);
- writeLocation(fn);
- writeEndTag(); // <cxxFunctionDefinition>
-
- writeApiDesc(fn, marker, QString());
- // generateAlsoList(inner, marker);
-
- // not included: <example> or <apiImpl>
-
- writeEndTag(); // </cxxFunctionDetail>
- writeEndTag(); // </cxxFunction>
-
- if (fn->metaness() == FunctionNode::Ctor ||
- fn->metaness() == FunctionNode::Dtor ||
- fn->overloadNumber() != 1) {
- }
- }
- ++m;
- }
-}
-
-static const QString typeTag("type");
-static const QChar charLangle = '<';
-static const QChar charAt = '@';
-
-/*!
- This function replaces class and enum names with <apiRelation>
- elements, i.e. links.
- */
-void DitaXmlGenerator::replaceTypesWithLinks(const Node* n, const InnerNode* parent, QString& src)
-{
- QStringRef arg;
- QStringRef par1;
- int srcSize = src.size();
- QString text;
- for (int i=0; i<srcSize;) {
- if (src.at(i) == charLangle && src.at(i+1) == charAt) {
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
- i += 2;
- if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
- const Node* tn = qdb_->findTypeNode(arg.toString(), parent);
- if (tn) {
- //Do not generate a link from a C++ function to a QML Basic Type (such as int)
- if (n->isFunction() && tn->isQmlBasicType())
- writeCharacters(arg.toString());
- else
- addLink(linkForNode(tn,parent),arg,DT_apiRelation);
- }
- else {
- // Write simple arguments, like void and bool,
- // which do not have a Qt defined target.
- writeCharacters(arg.toString());
- }
- }
- }
- else {
- text += src.at(i++);
- }
- }
- if (!text.isEmpty()) {
- writeCharacters(text);
- text.clear();
- }
-}
-
-/*!
- This function writes the <cxxFunctionParameters> element.
- */
-void DitaXmlGenerator::writeParameters(const FunctionNode* fn,
- const InnerNode* parent,
- CodeMarker* marker)
-{
- const QList<Parameter>& parameters = fn->parameters();
- if (!parameters.isEmpty()) {
- writeStartTag(DT_cxxFunctionParameters);
- QList<Parameter>::ConstIterator p = parameters.constBegin();
- while (p != parameters.constEnd()) {
- writeStartTag(DT_cxxFunctionParameter);
- writeStartTag(DT_cxxFunctionParameterDeclaredType);
- QString src = marker->typified((*p).leftType());
- replaceTypesWithLinks(fn,parent,src);
- //writeCharacters((*p).leftType());
- if (!(*p).rightType().isEmpty())
- writeCharacters((*p).rightType());
- writeEndTag(); // <cxxFunctionParameterDeclaredType>
- writeStartTag(DT_cxxFunctionParameterDeclarationName);
- writeCharacters((*p).name());
- writeEndTag(); // <cxxFunctionParameterDeclarationName>
-
- // not included: <cxxFunctionParameterDefinitionName>
-
- if (!(*p).defaultValue().isEmpty()) {
- writeStartTag(DT_cxxFunctionParameterDefaultValue);
- writeCharacters((*p).defaultValue());
- writeEndTag(); // <cxxFunctionParameterDefaultValue>
- }
-
- // not included: <apiDefNote>
-
- writeEndTag(); // <cxxFunctionParameter>
- ++p;
- }
- writeEndTag(); // <cxxFunctionParameters>
- }
-}
-
-/*!
- This function writes the enum types.
- */
-void DitaXmlGenerator::writeEnumerations(const Section& s,
- CodeMarker* marker,
- const QString& attribute)
-{
- NodeList::ConstIterator m = s.members.constBegin();
- while (m != s.members.constEnd()) {
- if ((*m)->type() == Node::Enum) {
- const EnumNode* en = static_cast<const EnumNode*>(*m);
- writeStartTag(DT_cxxEnumeration);
- xmlWriter().writeAttribute("id",en->guid());
- if (!attribute.isEmpty())
- xmlWriter().writeAttribute("outputclass",attribute);
- writeStartTag(DT_apiName);
- writeCharacters(en->name());
- writeEndTag(); // </apiName>
- generateBrief(en,marker);
-
- // not included <prolog>
-
- writeStartTag(DT_cxxEnumerationDetail);
- writeStartTag(DT_cxxEnumerationDefinition);
- writeStartTag(DT_cxxEnumerationAccessSpecifier);
- xmlWriter().writeAttribute("value",en->accessString());
- writeEndTag(); // <cxxEnumerationAccessSpecifier>
-
- QString fq = fullQualification(en);
- if (!fq.isEmpty()) {
- writeStartTag(DT_cxxEnumerationScopedName);
- writeCharacters(fq);
- writeEndTag(); // <cxxEnumerationScopedName>
- }
- const QList<EnumItem>& items = en->items();
- if (!items.isEmpty()) {
- writeStartTag(DT_cxxEnumerationPrototype);
- writeCharacters(en->name());
- xmlWriter().writeCharacters(" = { ");
- QList<EnumItem>::ConstIterator i = items.constBegin();
- while (i != items.constEnd()) {
- writeCharacters((*i).name());
- if (!(*i).value().isEmpty()) {
- xmlWriter().writeCharacters(" = ");
- writeCharacters((*i).value());
- }
- ++i;
- if (i != items.constEnd())
- xmlWriter().writeCharacters(", ");
- }
- xmlWriter().writeCharacters(" }");
- writeEndTag(); // <cxxEnumerationPrototype>
- }
-
- writeStartTag(DT_cxxEnumerationNameLookup);
- writeCharacters(en->parent()->name() + "::" + en->name());
- writeEndTag(); // <cxxEnumerationNameLookup>
-
- // not included: <cxxEnumerationReimplemented>
-
- if (!items.isEmpty()) {
- writeStartTag(DT_cxxEnumerators);
- QList<EnumItem>::ConstIterator i = items.constBegin();
- while (i != items.constEnd()) {
- writeStartTag(DT_cxxEnumerator);
- writeStartTag(DT_apiName);
- writeCharacters((*i).name());
- writeEndTag(); // </apiName>
-
- QString fq = fullQualification(en->parent());
- if (!fq.isEmpty()) {
- writeStartTag(DT_cxxEnumeratorScopedName);
- writeCharacters(fq + "::" + (*i).name());
- writeEndTag(); // <cxxEnumeratorScopedName>
- }
- writeStartTag(DT_cxxEnumeratorPrototype);
- writeCharacters((*i).name());
- writeEndTag(); // <cxxEnumeratorPrototype>
- writeStartTag(DT_cxxEnumeratorNameLookup);
- writeCharacters(en->parent()->name() + "::" + (*i).name());
- writeEndTag(); // <cxxEnumeratorNameLookup>
-
- if (!(*i).value().isEmpty()) {
- writeStartTag(DT_cxxEnumeratorInitialiser);
- if ((*i).value().toInt(0,16) == 0)
- xmlWriter().writeAttribute("value", "0");
- else
- xmlWriter().writeAttribute("value", (*i).value());
- writeEndTag(); // <cxxEnumeratorInitialiser>
- }
-
- // not included: <cxxEnumeratorAPIItemLocation>
-#if 0
- if (!(*i).text().isEmpty()) {
- writeStartTag(DT_apiDesc);
- generateText((*i).text(), en, marker);
- writeEndTag(); // </apiDesc>
- }
-#endif
- writeEndTag(); // <cxxEnumerator>
- ++i;
- }
- writeEndTag(); // <cxxEnumerators>
- }
-
- writeLocation(en);
- writeEndTag(); // <cxxEnumerationDefinition>
-
- writeApiDesc(en, marker, QString());
-
- // not included: <example> or <apiImpl>
-
- writeEndTag(); // </cxxEnumerationDetail>
-
- // not included: <related-links>
-
- writeEndTag(); // </cxxEnumeration>
- }
- ++m;
- }
-}
-
-/*!
- This function writes the output for the \typedef commands.
- */
-void DitaXmlGenerator::writeTypedefs(const Section& s,
- CodeMarker* marker,
- const QString& attribute)
-
-{
- NodeList::ConstIterator m = s.members.constBegin();
- while (m != s.members.constEnd()) {
- if ((*m)->type() == Node::Typedef) {
- const TypedefNode* tn = static_cast<const TypedefNode*>(*m);
- writeStartTag(DT_cxxTypedef);
- xmlWriter().writeAttribute("id",tn->guid());
- if (!attribute.isEmpty())
- xmlWriter().writeAttribute("outputclass",attribute);
- writeStartTag(DT_apiName);
- writeCharacters(tn->name());
- writeEndTag(); // </apiName>
- generateBrief(tn,marker);
-
- // not included: <prolog>
-
- writeStartTag(DT_cxxTypedefDetail);
- writeStartTag(DT_cxxTypedefDefinition);
- writeStartTag(DT_cxxTypedefAccessSpecifier);
- xmlWriter().writeAttribute("value",tn->accessString());
- writeEndTag(); // <cxxTypedefAccessSpecifier>
-
- // not included: <cxxTypedefDeclaredType>
-
- QString fq = fullQualification(tn);
- if (!fq.isEmpty()) {
- writeStartTag(DT_cxxTypedefScopedName);
- writeCharacters(fq);
- writeEndTag(); // <cxxTypedefScopedName>
- }
-
- // not included: <cxxTypedefPrototype>
-
- writeStartTag(DT_cxxTypedefNameLookup);
- writeCharacters(tn->parent()->name() + "::" + tn->name());
- writeEndTag(); // <cxxTypedefNameLookup>
-
- // not included: <cxxTypedefReimplemented>
-
- writeLocation(tn);
- writeEndTag(); // <cxxTypedefDefinition>
-
- writeApiDesc(tn, marker, QString());
-
- // not included: <example> or <apiImpl>
-
- writeEndTag(); // </cxxTypedefDetail>
-
- // not included: <related-links>
-
- writeEndTag(); // </cxxTypedef>
- }
- ++m;
- }
-}
-
-/*!
- This function writes the output for the \property commands.
- This is the Q_PROPERTYs.
- */
-void DitaXmlGenerator::writeProperties(const Section& s,
- CodeMarker* marker,
- const QString& attribute)
-{
- NodeList::ConstIterator m = s.members.constBegin();
- while (m != s.members.constEnd()) {
- if ((*m)->type() == Node::Property) {
- const PropertyNode* pn = static_cast<const PropertyNode*>(*m);
- writeStartTag(DT_cxxVariable);
- xmlWriter().writeAttribute("id",pn->guid());
- if (!attribute.isEmpty())
- xmlWriter().writeAttribute("outputclass",attribute);
- writeStartTag(DT_apiName);
- writeCharacters(pn->name());
- writeEndTag(); // </apiName>
- generateBrief(pn,marker);
-
- // not included: <prolog>
-
- writeStartTag(DT_cxxVariableDetail);
- writeStartTag(DT_cxxVariableDefinition);
- writeStartTag(DT_cxxVariableAccessSpecifier);
- xmlWriter().writeAttribute("value",pn->accessString());
- writeEndTag(); // <cxxVariableAccessSpecifier>
-
- // not included: <cxxVariableStorageClassSpecifierExtern>,
- // <cxxVariableStorageClassSpecifierStatic>,
- // <cxxVariableStorageClassSpecifierMutable>,
- // <cxxVariableConst>, <cxxVariableVolatile>
-
- if (!pn->qualifiedDataType().isEmpty()) {
- writeStartTag(DT_cxxVariableDeclaredType);
- writeCharacters(pn->qualifiedDataType());
- writeEndTag(); // <cxxVariableDeclaredType>
- }
- QString fq = fullQualification(pn);
- if (!fq.isEmpty()) {
- writeStartTag(DT_cxxVariableScopedName);
- writeCharacters(fq);
- writeEndTag(); // <cxxVariableScopedName>
- }
-
- writeStartTag(DT_cxxVariablePrototype);
- xmlWriter().writeCharacters("Q_PROPERTY(");
- writeCharacters(pn->qualifiedDataType());
- xmlWriter().writeCharacters(" ");
- writeCharacters(pn->name());
- writePropertyParameter("READ",pn->getters());
- writePropertyParameter("WRITE",pn->setters());
- writePropertyParameter("RESET",pn->resetters());
- writePropertyParameter("NOTIFY",pn->notifiers());
- if (pn->isDesignable() != pn->designableDefault()) {
- xmlWriter().writeCharacters(" DESIGNABLE ");
- if (!pn->runtimeDesignabilityFunction().isEmpty())
- writeCharacters(pn->runtimeDesignabilityFunction());
- else
- xmlWriter().writeCharacters(pn->isDesignable() ? "true" : "false");
- }
- if (pn->isScriptable() != pn->scriptableDefault()) {
- xmlWriter().writeCharacters(" SCRIPTABLE ");
- if (!pn->runtimeScriptabilityFunction().isEmpty())
- writeCharacters(pn->runtimeScriptabilityFunction());
- else
- xmlWriter().writeCharacters(pn->isScriptable() ? "true" : "false");
- }
- if (pn->isWritable() != pn->writableDefault()) {
- xmlWriter().writeCharacters(" STORED ");
- xmlWriter().writeCharacters(pn->isStored() ? "true" : "false");
- }
- if (pn->isUser() != pn->userDefault()) {
- xmlWriter().writeCharacters(" USER ");
- xmlWriter().writeCharacters(pn->isUser() ? "true" : "false");
- }
- if (pn->isConstant())
- xmlWriter().writeCharacters(" CONSTANT");
- if (pn->isFinal())
- xmlWriter().writeCharacters(" FINAL");
- xmlWriter().writeCharacters(")");
- writeEndTag(); // <cxxVariablePrototype>
-
- writeStartTag(DT_cxxVariableNameLookup);
- writeCharacters(pn->parent()->name() + "::" + pn->name());
- writeEndTag(); // <cxxVariableNameLookup>
-
- if (pn->overriddenFrom() != 0) {
- PropertyNode* opn = (PropertyNode*)pn->overriddenFrom();
- writeStartTag(DT_cxxVariableReimplemented);
- xmlWriter().writeAttribute("href",ditaXmlHref(opn));
- writeCharacters(opn->plainFullName());
- writeEndTag(); // </cxxVariableReimplemented>
- }
-
- writeLocation(pn);
- writeEndTag(); // <cxxVariableDefinition>
-
- writeApiDesc(pn, marker, QString());
-
- // not included: <example> or <apiImpl>
-
- writeEndTag(); // </cxxVariableDetail>
-
- // not included: <related-links>
-
- writeEndTag(); // </cxxVariable>
- }
- ++m;
- }
-}
-
-/*!
- This function outputs the nodes resulting from \variable commands.
- */
-void DitaXmlGenerator::writeDataMembers(const Section& s,
- CodeMarker* marker,
- const QString& attribute)
-{
- NodeList::ConstIterator m = s.members.constBegin();
- while (m != s.members.constEnd()) {
- if ((*m)->type() == Node::Variable) {
- const VariableNode* vn = static_cast<const VariableNode*>(*m);
- writeStartTag(DT_cxxVariable);
- xmlWriter().writeAttribute("id",vn->guid());
- if (!attribute.isEmpty())
- xmlWriter().writeAttribute("outputclass",attribute);
- writeStartTag(DT_apiName);
- writeCharacters(vn->name());
- writeEndTag(); // </apiName>
- generateBrief(vn,marker);
-
- // not included: <prolog>
-
- writeStartTag(DT_cxxVariableDetail);
- writeStartTag(DT_cxxVariableDefinition);
- writeStartTag(DT_cxxVariableAccessSpecifier);
- xmlWriter().writeAttribute("value",vn->accessString());
- writeEndTag(); // <cxxVariableAccessSpecifier>
-
- // not included: <cxxVAriableStorageClassSpecifierExtern>
-
- if (vn->isStatic()) {
- writeStartTag(DT_cxxVariableStorageClassSpecifierStatic);
- xmlWriter().writeAttribute("name","static");
- xmlWriter().writeAttribute("value","static");
- writeEndTag(); // <cxxVariableStorageClassSpecifierStatic>
- }
-
- // not included: <cxxVAriableStorageClassSpecifierMutable>,
- // <cxxVariableConst>, <cxxVariableVolatile>
-
- writeStartTag(DT_cxxVariableDeclaredType);
- writeCharacters(vn->leftType());
- if (!vn->rightType().isEmpty())
- writeCharacters(vn->rightType());
- writeEndTag(); // <cxxVariableDeclaredType>
-
- QString fq = fullQualification(vn);
- if (!fq.isEmpty()) {
- writeStartTag(DT_cxxVariableScopedName);
- writeCharacters(fq);
- writeEndTag(); // <cxxVariableScopedName>
- }
-
- writeStartTag(DT_cxxVariablePrototype);
- writeCharacters(vn->leftType() + QLatin1Char(' '));
- //writeCharacters(vn->parent()->name() + "::" + vn->name());
- writeCharacters(vn->name());
- if (!vn->rightType().isEmpty())
- writeCharacters(vn->rightType());
- writeEndTag(); // <cxxVariablePrototype>
-
- writeStartTag(DT_cxxVariableNameLookup);
- writeCharacters(vn->parent()->name() + "::" + vn->name());
- writeEndTag(); // <cxxVariableNameLookup>
-
- // not included: <cxxVariableReimplemented>
-
- writeLocation(vn);
- writeEndTag(); // <cxxVariableDefinition>
-
- writeApiDesc(vn, marker, QString());
-
- // not included: <example> or <apiImpl>
-
- writeEndTag(); // </cxxVariableDetail>
-
- // not included: <related-links>
-
- writeEndTag(); // </cxxVariable>
- }
- ++m;
- }
-}
-
-/*!
- This function writes a \macro as a <cxxDefine>.
- */
-void DitaXmlGenerator::writeMacros(const Section& s,
- CodeMarker* marker,
- const QString& attribute)
-{
- NodeList::ConstIterator m = s.members.constBegin();
- while (m != s.members.constEnd()) {
- if ((*m)->type() == Node::Function) {
- const FunctionNode* fn = static_cast<const FunctionNode*>(*m);
- if (fn->isMacro()) {
- writeStartTag(DT_cxxDefine);
- xmlWriter().writeAttribute("id",fn->guid());
- if (!attribute.isEmpty())
- xmlWriter().writeAttribute("outputclass",attribute);
- writeStartTag(DT_apiName);
- writeCharacters(fn->name());
- writeEndTag(); // </apiName>
- generateBrief(fn,marker);
-
- // not included: <prolog>
-
- writeStartTag(DT_cxxDefineDetail);
- writeStartTag(DT_cxxDefineDefinition);
- writeStartTag(DT_cxxDefineAccessSpecifier);
- xmlWriter().writeAttribute("value",fn->accessString());
- writeEndTag(); // <cxxDefineAccessSpecifier>
-
- writeStartTag(DT_cxxDefinePrototype);
- xmlWriter().writeCharacters("#define ");
- writeCharacters(fn->name());
- if (fn->metaness() == FunctionNode::MacroWithParams) {
- QStringList params = fn->parameterNames();
- if (!params.isEmpty()) {
- xmlWriter().writeCharacters("(");
- for (int i = 0; i < params.size(); ++i) {
- if (params[i].isEmpty())
- xmlWriter().writeCharacters("...");
- else
- writeCharacters(params[i]);
- if ((i+1) < params.size())
- xmlWriter().writeCharacters(", ");
- }
- xmlWriter().writeCharacters(")");
- }
- }
- writeEndTag(); // <cxxDefinePrototype>
-
- writeStartTag(DT_cxxDefineNameLookup);
- writeCharacters(fn->name());
- writeEndTag(); // <cxxDefineNameLookup>
-
- if (fn->reimplementedFrom() != 0) {
- FunctionNode* rfn = (FunctionNode*)fn->reimplementedFrom();
- writeStartTag(DT_cxxDefineReimplemented);
- xmlWriter().writeAttribute("href",ditaXmlHref(rfn));
- writeCharacters(rfn->plainFullName());
- writeEndTag(); // </cxxDefineReimplemented>
- }
-
- if (fn->metaness() == FunctionNode::MacroWithParams) {
- QStringList params = fn->parameterNames();
- if (!params.isEmpty()) {
- writeStartTag(DT_cxxDefineParameters);
- for (int i = 0; i < params.size(); ++i) {
- writeStartTag(DT_cxxDefineParameter);
- writeStartTag(DT_cxxDefineParameterDeclarationName);
- writeCharacters(params[i]);
- writeEndTag(); // <cxxDefineParameterDeclarationName>
-
- // not included: <apiDefNote>
-
- writeEndTag(); // <cxxDefineParameter>
- }
- writeEndTag(); // <cxxDefineParameters>
- }
- }
-
- writeLocation(fn);
- writeEndTag(); // <cxxDefineDefinition>
-
- writeApiDesc(fn, marker, QString());
-
- // not included: <example> or <apiImpl>
-
- writeEndTag(); // </cxxDefineDetail>
-
- // not included: <related-links>
-
- writeEndTag(); // </cxxDefine>
- }
- }
- ++m;
- }
-}
-
-/*!
- This function writes one parameter of a Q_PROPERTY macro.
- The property is identified by \a tag ("READ" "WRIE" etc),
- and it is found in the 'a nlist.
- */
-void DitaXmlGenerator::writePropertyParameter(const QString& tag, const NodeList& nlist)
-{
- NodeList::const_iterator n = nlist.constBegin();
- while (n != nlist.constEnd()) {
- xmlWriter().writeCharacters(" ");
- writeCharacters(tag);
- xmlWriter().writeCharacters(" ");
- writeCharacters((*n)->name());
- ++n;
- }
-}
-
-/*!
- Calls beginSubPage() in the base class to open the file.
- Then creates a new XML stream writer using the IO device
- from opened file and pushes the XML writer onto a stackj.
- 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(). Finally, it sets some
- parameters in the XML writer and calls writeStartDocument().
-
- It also ensures that a GUID map is created for the output file.
- */
-void DitaXmlGenerator::beginSubPage(const InnerNode* node,
- const QString& fileName)
-{
- Generator::beginSubPage(node,fileName);
- (void) lookupGuidMap(fileName);
- QXmlStreamWriter* writer = new QXmlStreamWriter(out().device());
- xmlWriterStack.push(writer);
- writer->setAutoFormatting(true);
- writer->setAutoFormattingIndent(4);
- writer->writeStartDocument();
- clearSectionNesting();
-}
-
-/*!
- Calls writeEndDocument() and then pops the XML stream writer
- off the stack and deletes it. Then it calls endSubPage() in
- the base class to close the device.
- */
-void DitaXmlGenerator::endSubPage()
-{
- if (inSection())
- qDebug() << "Missing </section> in" << outFileName() << sectionNestingLevel;
- xmlWriter().writeEndDocument();
- delete xmlWriterStack.pop();
- Generator::endSubPage();
-}
-
-/*!
- Returns a reference to the XML stream writer currently in use.
- There is one XML stream writer open for each XML file being
- written, and they are kept on a stack. The one on top of the
- stack is the one being written to at the moment.
- */
-QXmlStreamWriter& DitaXmlGenerator::xmlWriter()
-{
- return *xmlWriterStack.top();
-}
-
-/*!
- Writes the \e {<apiDesc>} element for \a node to the current XML
- stream using the code \a marker and the \a title.
- */
-void DitaXmlGenerator::writeApiDesc(const Node* node,
- CodeMarker* marker,
- const QString& title)
-{
- if (!node->doc().isEmpty()) {
- inDetailedDescription = true;
- enterDesc(DT_apiDesc,QString(),title);
- generateBody(node, marker);
- generateAlsoList(node, marker);
- leaveSection();
- }
- inDetailedDescription = false;
-}
-
-/*!
- Write the nested class elements.
- */
-void DitaXmlGenerator::writeNestedClasses(const Section& s,
- const Node* n)
-{
- if (s.members.isEmpty())
- return;
- writeStartTag(DT_cxxClassNested);
- writeStartTag(DT_cxxClassNestedDetail);
-
- NodeList::ConstIterator m = s.members.constBegin();
- while (m != s.members.constEnd()) {
- if ((*m)->type() == Node::Class) {
- writeStartTag(DT_cxxClassNestedClass);
- QString link = linkForNode((*m), n);
- xmlWriter().writeAttribute("href", link);
- QString name = n->name() + "::" + (*m)->name();
- writeCharacters(name);
- writeEndTag(); // <cxxClassNestedClass>
- }
- ++m;
- }
- writeEndTag(); // <cxxClassNestedDetail>
- writeEndTag(); // <cxxClassNested>
-}
-
-/*!
- Recursive writing of DITA XML files from the root \a node.
- */
-void
-DitaXmlGenerator::generateInnerNode(InnerNode* node)
-{
- if (!node->url().isNull())
- return;
-
- if (node->isDocNode()) {
- DocNode* docNode = static_cast<DocNode*>(node);
- if (docNode->subType() == Node::ExternalPage)
- return;
- if (docNode->subType() == Node::Image)
- return;
- if (docNode->subType() == Node::Page) {
- if (node->count() > 0)
- qDebug("PAGE %s HAS CHILDREN", qPrintable(docNode->title()));
- }
- }
- else if (node->isQmlPropertyGroup())
- return;
-
- /*
- Obtain a code marker for the source file.
- */
- CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
- if (node->parent() != 0) {
- if (!node->name().endsWith(".ditamap"))
- beginSubPage(node, fileName(node));
- if (node->isNamespace() || node->isClass() || node->isQmlType() || node->isHeaderFile())
- generateClassLikeNode(node, marker);
- else if (node->isDocNode())
- generateDocNode(static_cast<DocNode*>(node), marker);
- else if (node->isQmlBasicType())
- generateQmlBasicTypePage(static_cast<QmlBasicTypeNode*>(node), marker);
- if (!node->name().endsWith(".ditamap"))
- endSubPage();
- }
-
- NodeList::ConstIterator c = node->childNodes().constBegin();
- while (c != node->childNodes().constEnd()) {
- if ((*c)->isInnerNode() && (*c)->access() != Node::Private)
- generateInnerNode((InnerNode*)*c);
- ++c;
- }
-}
-
-/*!
- Returns \c true if \a format is "DITAXML" or "HTML" .
- */
-bool DitaXmlGenerator::canHandleFormat(const QString& format)
-{
- return (format == "HTML") || (format == this->format());
-}
-
-/*!
- If the node multimap \a nmm contains nodes mapped to \a key,
- if any of the nodes mapped to \a key has the same href as the
- \a node, return true. Otherwise, return false.
- */
-bool DitaXmlGenerator::isDuplicate(NodeMultiMap* nmm, const QString& key, Node* node)
-{
- QList<Node*> matches = nmm->values(key);
- if (!matches.isEmpty()) {
- for (int i=0; i<matches.size(); ++i) {
- if (matches[i] == node)
- return true;
- if (fileName(node) == fileName(matches[i]))
- return true;
- }
- }
- return false;
-}
-/*!
- Collect all the nodes in the tree according to their type or subtype.
-
- If a node is found that is named index.html, return that node as the
- root page node.
-
- type: Class
- type: Namespace
-
- subtype: Example
- subtype: External page
- subtype: Group
- subtype: Header file
- subtype: Module
- subtype: Page
- subtype: QML basic type
- subtype: QML class
- subtype: QML module
- */
-Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
-{
- Node* rootPageNode = 0;
- const NodeList& children = parent->childNodes();
- if (children.size() == 0)
- return rootPageNode;
-
- QString message;
- for (int i=0; i<children.size(); ++i) {
- Node* child = children[i];
- if (!child || child->isInternal() || child->doc().isEmpty() || child->isIndexNode())
- continue;
-
- if (child->name() == "index.html" || child->name() == "index") {
- rootPageNode = child;
- }
-
- switch (child->type()) {
- case Node::Namespace:
- if (!isDuplicate(nodeTypeMaps[Node::Namespace],child->name(),child))
- nodeTypeMaps[Node::Namespace]->insert(child->name(),child);
- break;
- case Node::Class:
- if (!isDuplicate(nodeTypeMaps[Node::Class],child->name(),child))
- nodeTypeMaps[Node::Class]->insert(child->name(),child);
- break;
- case Node::QmlType:
- if (!isDuplicate(nodeTypeMaps[Node::QmlType],child->name(),child))
- nodeTypeMaps[Node::QmlType]->insert(child->name(),child);
- break;
- case Node::QmlBasicType:
- if (!isDuplicate(nodeTypeMaps[Node::QmlBasicType],child->title(),child))
- nodeTypeMaps[Node::QmlBasicType]->insert(child->title(),child);
- break;
- case Node::Group:
- if (!isDuplicate(nodeTypeMaps[Node::Group],child->title(),child))
- nodeTypeMaps[Node::Group]->insert(child->title(),child);
- break;
- case Node::Module:
- if (!isDuplicate(nodeTypeMaps[Node::Module],child->title(),child))
- nodeTypeMaps[Node::Module]->insert(child->title(),child);
- break;
- case Node::QmlModule:
- if (!isDuplicate(nodeTypeMaps[Node::QmlModule],child->title(),child))
- nodeTypeMaps[Node::QmlModule]->insert(child->title(),child);
- break;
- case Node::Document:
- switch (child->subType()) {
- case Node::Example:
- if (!isDuplicate(nodeSubtypeMaps[Node::Example],child->title(),child))
- nodeSubtypeMaps[Node::Example]->insert(child->title(),child);
- break;
- case Node::HeaderFile:
- if (!isDuplicate(nodeSubtypeMaps[Node::HeaderFile],child->title(),child))
- nodeSubtypeMaps[Node::HeaderFile]->insert(child->title(),child);
- break;
- case Node::File:
- break;
- case Node::Image:
- break;
- case Node::Page:
- if (!isDuplicate(pageTypeMaps[child->pageType()],child->title(),child))
- pageTypeMaps[child->pageType()]->insert(child->title(),child);
- break;
- case Node::ExternalPage:
- if (!isDuplicate(nodeSubtypeMaps[Node::ExternalPage],child->title(),child))
- nodeSubtypeMaps[Node::ExternalPage]->insert(child->title(),child);
- break;
- default:
- break;
- }
- break;
- case Node::Enum:
- break;
- case Node::Typedef:
- break;
- case Node::Function:
- break;
- case Node::Property:
- break;
- case Node::Variable:
- break;
- case Node::QmlProperty:
- break;
- case Node::QmlPropertyGroup:
- break;
- case Node::QmlSignal:
- break;
- case Node::QmlSignalHandler:
- break;
- case Node::QmlMethod:
- break;
- default:
- break;
- }
- }
- return rootPageNode;
-}
-
-/*!
- Creates the DITA map for the qdoc run. The map is written
- to the file \e{qt.ditamap" in the DITA XML output directory.
- */
-void DitaXmlGenerator::writeDitaMap()
-{
- QString doctype;
-
-/*
- Remove #if 0 to get a flat ditamap.
-*/
-#if 0
- beginSubPage(qdb_->primaryTreeRoot(),"qt.ditamap");
- doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
- xmlWriter().writeDTD(doctype);
- writeStartTag(DT_map);
- writeStartTag(DT_topicmeta);
- writeStartTag(DT_shortdesc);
- xmlWriter().writeCharacters("The top level map for the Qt documentation");
- writeEndTag(); // </shortdesc>
- writeEndTag(); // </topicmeta>
- GuidMaps::iterator i = guidMaps.constBegin();
- while (i != guidMaps.constEnd()) {
- writeStartTag(DT_topicref);
- if (i.key() != "qt.ditamap")
- xmlWriter().writeAttribute("href",i.key());
- writeEndTag(); // </topicref>
- ++i;
- }
- endSubPage();
-#endif
-
- for (unsigned i=0; i<Node::LastType; ++i)
- nodeTypeMaps[i] = new NodeMultiMap;
- for (unsigned i=0; i<Node::LastSubtype; ++i)
- nodeSubtypeMaps[i] = new NodeMultiMap;
- for (unsigned i=0; i<Node::OnBeyondZebra; ++i)
- pageTypeMaps[i] = new NodeMultiMap;
- Node* rootPageNode = collectNodesByTypeAndSubtype(qdb_->primaryTreeRoot());
-
- beginSubPage(qdb_->primaryTreeRoot(),"qt.ditamap");
-
- doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
- xmlWriter().writeDTD(doctype);
- writeStartTag(DT_map);
- writeStartTag(DT_topicmeta);
- writeStartTag(DT_shortdesc);
- xmlWriter().writeCharacters("The top level map for the Qt documentation");
- writeEndTag(); // </shortdesc>
- writeEndTag(); // </topicmeta>
-
- writeStartTag(DT_topicref);
- if (rootPageNode) {
- if (!rootPageNode->title().isEmpty())
- xmlWriter().writeAttribute("navtitle",rootPageNode->title());
- else
- xmlWriter().writeAttribute("navtitle",project);
- xmlWriter().writeAttribute("href",fileName(rootPageNode));
- }
- else
- xmlWriter().writeAttribute("navtitle",project);
-
- writeTopicrefs(pageTypeMaps[Node::OverviewPage], "Overviews");
- writeTopicrefs(pageTypeMaps[Node::HowToPage], "Howtos");
- writeTopicrefs(pageTypeMaps[Node::TutorialPage], "Tutorials");
- writeTopicrefs(pageTypeMaps[Node::FAQPage], "FAQs");
- writeTopicrefs(pageTypeMaps[Node::ArticlePage], "Articles");
- writeTopicrefs(nodeSubtypeMaps[Node::Example], "Examples");
-
- if (nodeTypeMaps[Node::QmlModule]->size() > 1)
- writeTopicrefs(nodeTypeMaps[Node::QmlModule], "QML modules");
-
- if (nodeTypeMaps[Node::QmlModule]->size() == 1)
- writeTopicrefs(nodeTypeMaps[Node::QmlType], "QML types", nodeTypeMaps[Node::QmlModule]->values()[0]);
- else
- writeTopicrefs(nodeTypeMaps[Node::QmlType], "QML types");
- writeTopicrefs(nodeTypeMaps[Node::QmlBasicType], "QML basic types");
-
- if (nodeTypeMaps[Node::Module]->size() > 1)
- writeTopicrefs(nodeTypeMaps[Node::Module], "Modules");
-
- if (nodeTypeMaps[Node::Module]->size() == 1)
- writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes", nodeTypeMaps[Node::Module]->values()[0]);
- else
- writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes");
- writeTopicrefs(nodeTypeMaps[Node::Namespace], "C++ namespaces");
- writeTopicrefs(nodeSubtypeMaps[Node::HeaderFile], "Header files");
- writeTopicrefs(nodeTypeMaps[Node::Group], "Groups");
-
- writeEndTag(); // </topicref>
- endSubPage();
-
- for (unsigned i=0; i<Node::LastType; ++i)
- delete nodeTypeMaps[i];
- for (unsigned i=0; i<Node::LastSubtype; ++i)
- delete nodeSubtypeMaps[i];
- for (unsigned i=0; i<Node::OnBeyondZebra; ++i)
- delete pageTypeMaps[i];
-}
-
-/*!
- Creates the DITA map from the topicrefs in \a node,
- which is a DitaMapNode.
- */
-void DitaXmlGenerator::writeDitaMap(const DitaMapNode* node)
-{
- beginSubPage(node,node->name());
-
- QString doctype;
- doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
- xmlWriter().writeDTD(doctype);
- writeStartTag(DT_map);
- writeStartTag(DT_topicmeta);
- writeStartTag(DT_shortdesc);
- xmlWriter().writeCharacters(node->title());
- writeEndTag(); // </shortdesc>
- writeEndTag(); // </topicmeta>
- const DitaRefList map = node->map();
- writeDitaRefs(map);
- endSubPage();
-}
-
-/*!
- Write the \a ditarefs to the current output file.
- */
-void DitaXmlGenerator::writeDitaRefs(const DitaRefList& ditarefs)
-{
- foreach (DitaRef* t, ditarefs) {
- if (t->isMapRef())
- writeStartTag(DT_mapref);
- else
- writeStartTag(DT_topicref);
- xmlWriter().writeAttribute("navtitle",t->navtitle());
- if (t->href().isEmpty()) {
- const DocNode* dn = qdb_->findDocNodeByTitle(t->navtitle());
- if (dn)
- xmlWriter().writeAttribute("href",fileName(dn));
- }
- else
- xmlWriter().writeAttribute("href",t->href());
- if (t->subrefs() && !t->subrefs()->isEmpty())
- writeDitaRefs(*(t->subrefs()));
- writeEndTag(); // </topicref> or </mapref>
- }
-}
-
-void DitaXmlGenerator::writeTopicrefs(NodeMultiMap* nmm, const QString& navtitle, Node* headingnode)
-{
- if (!nmm || nmm->isEmpty())
- return;
- writeStartTag(DT_topicref);
- xmlWriter().writeAttribute("navtitle",navtitle);
- if (headingnode)
- xmlWriter().writeAttribute("href",fileName(headingnode));
- NodeMultiMap::iterator i;
- NodeMultiMap *ditaMaps = pageTypeMaps[Node::DitaMapPage];
-
- /*!
- Put all pages that are already in a hand-written ditamap not in
- the qt.ditamap separately. It loops through all ditamaps recursively
- before deciding to write an article to qt.ditamap.
- */
- if ((navtitle == "Articles" && ditaMaps && ditaMaps->size() > 0)) {
- NodeMultiMap::iterator mapIterator = ditaMaps->begin();
- while (mapIterator != ditaMaps->end()) {
- writeStartTag(DT_mapref);
- xmlWriter().writeAttribute("navtitle",mapIterator.key());
- xmlWriter().writeAttribute("href",fileName(mapIterator.value()));
- writeEndTag();
- ++mapIterator;
- }
- i = nmm->begin();
- while (i != nmm->end()) {
- // Hardcode not writing index.dita multiple times in the tree.
- // index.dita should only appear at the top of the ditamap.
- if (fileName(i.value()) == "index.dita") {
- i++;
- continue;
- }
- bool foundInDitaMap = false;
- mapIterator = ditaMaps->begin();
- while (mapIterator != ditaMaps->end()) {
- const DitaMapNode *dmNode = static_cast<const DitaMapNode *>(mapIterator.value());
- for (int count = 0; count < dmNode->map().count(); count++) {
- if (dmNode->map().at(count)->navtitle() == i.key()) {
- foundInDitaMap = true;
- break;
- }
- }
- ++mapIterator;
- }
- if (!foundInDitaMap) {
- writeStartTag(DT_topicref);
- xmlWriter().writeAttribute("navtitle",i.key());
- xmlWriter().writeAttribute("href",fileName(i.value()));
- writeEndTag(); // </topicref>
- }
- ++i;
- }
- }
- /*!
- Shortcut when there are no hand-written ditamaps or when we are
- not generating the articles list.
- */
- else {
- i = nmm->begin();
- while (i != nmm->end()) {
- // Hardcode not writing index.dita multiple times in the tree.
- // index.dita should only appear at the top of the ditamap.
- if (fileName(i.value()) == "index.dita") {
- i++;
- continue;
- }
- writeStartTag(DT_topicref);
- xmlWriter().writeAttribute("navtitle",i.key());
- xmlWriter().writeAttribute("href",fileName(i.value()));
- switch (i.value()->type()) {
- case Node::Class:
- case Node::Namespace: {
- const NamespaceNode* nn = static_cast<const NamespaceNode*>(i.value());
- const NodeList& c = nn->childNodes();
- QMap<QString, const Node*> tempMap;
- for (int j=0; j<c.size(); ++j) {
- if (c[j]->isInternal() || c[j]->access() == Node::Private || c[j]->doc().isEmpty())
- continue;
- if (c[j]->type() == Node::Class) {
- tempMap.insert(c[j]->name(), c[j]);
- }
- }
- QMap<QString, const Node*>::iterator classIterator = tempMap.begin();
- while (classIterator != tempMap.end()) {
- const Node* currentNode = static_cast<const Node*>(classIterator.value());
- writeStartTag(DT_topicref);
- xmlWriter().writeAttribute("navtitle",currentNode->name());
- xmlWriter().writeAttribute("href",fileName(currentNode));
- writeEndTag(); // </topicref>
- ++classIterator;
- }
-
- break;
- }
- default:
- break;
- }
- writeEndTag(); // </topicref>
- ++i;
- }
- }
- writeEndTag(); // </topicref>
-}
-
-
-/*!
- Looks up the tag name for \a t in the map of metadata
- values for the current topic in \a inner. If a value
- for the tag is found, the element is written with the
- found value. Otherwise if \a force is set, an empty
- element is written using the tag.
-
- Returns \c true or false depending on whether it writes
- an element using the tag \a t.
-
- \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.
- */
-bool DitaXmlGenerator::writeMetadataElement(const InnerNode* inner,
- DitaXmlGenerator::DitaTag t,
- bool force)
-{
- QString s = getMetadataElement(inner,t);
- if (s.isEmpty() && !force)
- return false;
- writeStartTag(t);
- if (!s.isEmpty())
- xmlWriter().writeCharacters(s);
- writeEndTag();
- return true;
-}
-
-
-/*!
- Looks up the tag name for \a t in the map of metadata
- values for the current topic in \a inner. If one or more
- value sfor the tag are found, the elements are written.
- Otherwise nothing is written.
-
- Returns \c true or false depending on whether it writes
- at least one element using the tag \a t.
-
- \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.
- */
-bool DitaXmlGenerator::writeMetadataElements(const InnerNode* inner,
- DitaXmlGenerator::DitaTag t)
-{
- QStringList s = getMetadataElements(inner,t);
- if (s.isEmpty())
- return false;
- for (int i=0; i<s.size(); ++i) {
- writeStartTag(t);
- xmlWriter().writeCharacters(s[i]);
- writeEndTag();
- }
- return true;
-}
-
-/*!
- Looks up the tag name for \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 DitaXmlGenerator::getMetadataElement(const InnerNode* inner, DitaXmlGenerator::DitaTag t)
-{
- QString s = Generator::getMetadataElement(inner, ditaTags[t]);
- if (s.isEmpty()) {
- QStringList sl = metadataDefault(t);
- if (!sl.isEmpty())
- s = sl[0];
- }
- return s;
-}
-
-/*!
- Looks up the tag name for \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
- all this function for a particular \a t, you consume
- \a t.
- */
-QStringList DitaXmlGenerator::getMetadataElements(const InnerNode* inner,
- DitaXmlGenerator::DitaTag t)
-{
- QStringList s = Generator::getMetadataElements(inner,ditaTags[t]);
- if (s.isEmpty())
- s = metadataDefault(t);
- return s;
-}
-
-/*!
- Returns the value of key \a t or an empty string
- if \a t is not found in the map.
- */
-QStringList DitaXmlGenerator::metadataDefault(DitaTag t) const
-{
- return metadataDefaults.value(ditaTags[t]).values_;
-}
-
-/*!
- Writes the <prolog> element for the \a inner node
- using the \a marker. The <prolog> element contains
- the <metadata> element, plus some others. This
- function writes one or more of these elements:
-
- \list
- \o <audience> *
- \o <author> *
- \o <brand> not used
- \o <category> *
- \o <compomnent> *
- \o <copyrholder> *
- \o <copyright> *
- \o <created> not used
- \o <copyryear> *
- \o <critdates> not used
- \o <keyword> not used
- \o <keywords> not used
- \o <metadata> *
- \o <othermeta> *
- \o <permissions> *
- \o <platform> not used
- \o <prodinfo> *
- \o <prodname> *
- \o <prolog> *
- \o <publisher> *
- \o <resourceid> not used
- \o <revised> not used
- \o <source> not used
- \o <tm> not used
- \o <unknown> not used
- \o <vrm> *
- \o <vrmlist> *
- \endlist
-
- \node * means the tag has been used.
-
- */
-void
-DitaXmlGenerator::writeProlog(const InnerNode* inner)
-{
- if (!inner)
- return;
- writeStartTag(DT_prolog);
- writeMetadataElements(inner,DT_author);
- writeMetadataElement(inner,DT_publisher);
- QString s = getMetadataElement(inner,DT_copyryear);
- QString t = getMetadataElement(inner,DT_copyrholder);
- writeStartTag(DT_copyright);
- writeStartTag(DT_copyryear);
- if (!s.isEmpty())
- xmlWriter().writeAttribute("year",s);
- writeEndTag(); // </copyryear>
- writeStartTag(DT_copyrholder);
- if (!s.isEmpty())
- xmlWriter().writeCharacters(t);
- writeEndTag(); // </copyrholder>
- writeEndTag(); // </copyright>
- s = getMetadataElement(inner,DT_permissions);
- writeStartTag(DT_permissions);
- xmlWriter().writeAttribute("view",s);
- writeEndTag(); // </permissions>
- writeStartTag(DT_metadata);
- QStringList sl = getMetadataElements(inner,DT_audience);
- if (!sl.isEmpty()) {
- for (int i=0; i<sl.size(); ++i) {
- writeStartTag(DT_audience);
- xmlWriter().writeAttribute("type",sl[i]);
- writeEndTag(); // </audience>
- }
- }
- if (!writeMetadataElement(inner,DT_category,false)) {
- writeStartTag(DT_category);
- QString category = "Page";
- if (inner->isClass())
- category = "Class reference";
- if (inner->isQmlType())
- category = "QML Reference";
- else if (inner->isQmlBasicType())
- category = "QML Basic Type";
- else if (inner->isNamespace())
- category = "Namespace";
- else if (inner->isModule())
- category = "Module";
- else if (inner->isQmlModule())
- category = "QML Module";
- else if (inner->isGroup())
- category = "Group";
- else if (inner->isDocNode()) {
- if (inner->isHeaderFile())
- category = "Header File";
- else if (inner->subType() == Node::File)
- category = "Example Source File";
- else if (inner->isExample())
- category = "Example";
- else if (inner->subType() == Node::Image)
- category = "Image";
- else if (inner->subType() == Node::Page)
- category = "Page";
- else if (inner->isExternalPage())
- category = "External Page"; // Is this necessary?
- }
- xmlWriter().writeCharacters(category);
- writeEndTag(); // </category>
- }
- if (vrm.size() > 0) {
- writeStartTag(DT_prodinfo);
- if (!writeMetadataElement(inner,DT_prodname,false)) {
- writeStartTag(DT_prodname);
- xmlWriter().writeCharacters(projectDescription);
- writeEndTag(); // </prodname>
- }
- writeStartTag(DT_vrmlist);
- writeStartTag(DT_vrm);
- if (vrm.size() > 0)
- xmlWriter().writeAttribute("version",vrm[0]);
- if (vrm.size() > 1)
- xmlWriter().writeAttribute("release",vrm[1]);
- if (vrm.size() > 2)
- xmlWriter().writeAttribute("modification",vrm[2]);
- writeEndTag(); // <vrm>
- writeEndTag(); // <vrmlist>
- if (!writeMetadataElement(inner,DT_component,false)) {
- QString component = inner->moduleName();
- if (!component.isEmpty()) {
- writeStartTag(DT_component);
- xmlWriter().writeCharacters(component);
- writeEndTag(); // </component>
- }
- }
- writeEndTag(); // </prodinfo>
- }
- const QStringMultiMap& metaTagMap = inner->doc().metaTagMap();
- QMapIterator<QString, QString> i(metaTagMap);
- while (i.hasNext()) {
- i.next();
- writeStartTag(DT_othermeta);
- xmlWriter().writeAttribute("name",i.key());
- xmlWriter().writeAttribute("content",i.value());
- writeEndTag(); // </othermeta>
- }
- if ((tagStack.first() == DT_cxxClass && !inner->includes().isEmpty()) || inner->isHeaderFile()) {
- writeStartTag(DT_othermeta);
- xmlWriter().writeAttribute("name","includeFile");
- QString text;
- QStringList::ConstIterator i = inner->includes().constBegin();
- while (i != inner->includes().constEnd()) {
- if ((*i).startsWith(QLatin1Char('<')) && (*i).endsWith(QLatin1Char('>')))
- text += *i;
- else
- text += QLatin1Char('<') + *i + QLatin1Char('>');
- ++i;
- if (i != inner->includes().constEnd())
- text += "\n";
- }
- xmlWriter().writeAttribute("content",text);
- writeEndTag(); // </othermeta>
- }
- writeEndTag(); // </metadata>
- writeEndTag(); // </prolog>
-}
-
-/*!
- This function should be called to write the \a href attribute
- if the href could be an \e http or \e ftp link. If \a href is
- one or the other, a \e scope attribute is also writen, with
- value \e external.
- */
-void DitaXmlGenerator::writeHrefAttribute(const QString& href)
-{
- xmlWriter().writeAttribute("href", href);
- if (href.startsWith("http:") || href.startsWith("ftp:") ||
- href.startsWith("https:") || href.startsWith("mailto:"))
- xmlWriter().writeAttribute("scope", "external");
-}
-
-/*!
- Strips the markup tags from \a src, when we are trying to
- create an \e{id} attribute. Returns the stripped text.
- */
-QString DitaXmlGenerator::stripMarkup(const QString& src) const
-{
- QString text;
- const QChar charAt = '@';
- const QChar charSlash = '/';
- const QChar charLangle = '<';
- const QChar charRangle = '>';
-
- int n = src.size();
- int i = 0;
- while (i < n) {
- if (src.at(i) == charLangle) {
- ++i;
- if (src.at(i) == charAt || (src.at(i) == charSlash && src.at(i+1) == charAt)) {
- while (i < n && src.at(i) != charRangle)
- ++i;
- ++i;
- }
- else {
- text += charLangle;
- }
- }
- else
- text += src.at(i++);
- }
- return text;
-}
-
-QT_END_NAMESPACE