summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.cpp142
-rw-r--r--src/tools/qdoc/ditaxmlgenerator.h6
-rw-r--r--src/tools/qdoc/doc/config/qt-defines.qdocconf1
-rw-r--r--src/tools/qdoc/doc/examples/componentset/uicomponents.qdoc7
-rw-r--r--src/tools/qdoc/doc/examples/examples.qdoc24
-rw-r--r--src/tools/qdoc/doc/qdoc-guide.qdoc38
-rw-r--r--src/tools/qdoc/doc/qdoc-manual.qdoc56
-rw-r--r--src/tools/qdoc/generator.cpp1916
-rw-r--r--src/tools/qdoc/generator.h176
-rw-r--r--src/tools/qdoc/helpprojectwriter.cpp8
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp270
-rw-r--r--src/tools/qdoc/htmlgenerator.h16
-rw-r--r--src/tools/qdoc/node.cpp2
-rw-r--r--src/tools/qdoc/node.h1
-rw-r--r--src/tools/qdoc/pagegenerator.cpp389
-rw-r--r--src/tools/qdoc/pagegenerator.h99
-rw-r--r--src/tools/qdoc/qdoc.pro2
-rw-r--r--src/tools/qdoc/qmlvisitor.cpp10
-rw-r--r--src/tools/qdoc/tree.cpp12
19 files changed, 1389 insertions, 1786 deletions
diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp
index f19f902c6b..25c92fb44f 100644
--- a/src/tools/qdoc/ditaxmlgenerator.cpp
+++ b/src/tools/qdoc/ditaxmlgenerator.cpp
@@ -43,6 +43,11 @@
ditaxmlgenerator.cpp
*/
+#include <QDebug>
+#include <QList>
+#include <qiterator.h>
+#include <QTextCodec>
+#include <QUuid>
#include "codemarker.h"
#include "codeparser.h"
#include "ditaxmlgenerator.h"
@@ -51,11 +56,6 @@
#include "separator.h"
#include "tree.h"
#include <ctype.h>
-#include <qdebug.h>
-#include <qlist.h>
-#include <qiterator.h>
-#include <qtextcodec.h>
-#include <QUuid>
QT_BEGIN_NAMESPACE
@@ -328,8 +328,7 @@ DitaXmlGenerator::DitaTag DitaXmlGenerator::currentTag()
/*!
Write the start tag \c{<apiDesc>}. if \a title is not
empty, generate a GUID from it and write the GUID as the
- value of the \e{id} attribute. Then write \a title as
- the value of the \e {spectitle} attribute.
+ value of the \e{id} attribute.
Then if \a outputclass is not empty, write it as the value
of the \a outputclass attribute.
@@ -341,7 +340,8 @@ int DitaXmlGenerator::enterApiDesc(const QString& outputclass, const QString& ti
writeStartTag(DT_apiDesc);
if (!title.isEmpty()) {
writeGuidAttribute(title);
- xmlWriter().writeAttribute("spectitle",title);
+ //Are there cases where the spectitle is required?
+ //xmlWriter().writeAttribute("spectitle",title);
}
if (!outputclass.isEmpty())
xmlWriter().writeAttribute("outputclass",outputclass);
@@ -636,7 +636,7 @@ void DitaXmlGenerator::generateTree(const Tree *tree)
findAllNamespaces(tree->root());
findAllSince(tree->root());
- PageGenerator::generateTree(tree);
+ Generator::generateTree(tree);
writeDitaMap(tree);
}
@@ -1770,13 +1770,15 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
writeEndTag(); // <cxxClassDefinition>
enterApiDesc(QString(),title);
+#if 0
+ // To be removed, if really not needed.
Text brief = nsn->doc().briefText(); // zzz
if (!brief.isEmpty()) {
writeStartTag(DT_p);
generateText(brief, nsn, marker);
writeEndTag(); // </p>
}
- generateIncludes(nsn, marker);
+#endif
generateStatus(nsn, marker);
generateThreadSafeness(nsn, marker);
generateSince(nsn, marker);
@@ -1904,13 +1906,15 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
writeEndTag(); // <cxxClassDefinition>
enterApiDesc(QString(),title);
+#if 0
+ // To be removed, if really not needed.
Text brief = cn->doc().briefText(); // zzz
if (!brief.isEmpty()) {
writeStartTag(DT_p);
generateText(brief, cn, marker);
writeEndTag(); // </p>
}
- generateIncludes(cn, marker);
+#endif
generateStatus(cn, marker);
generateInherits(cn, marker);
generateInheritedBy(cn, marker);
@@ -2028,13 +2032,15 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
writeStartTag(DT_cxxClassDetail);
enterApiDesc(QString(),title);
+#if 0
+ // To be removed, if really not needed.
Text brief = fn->doc().briefText(); // zzz
if (!brief.isEmpty()) {
writeStartTag(DT_p);
generateText(brief, fn, marker);
writeEndTag(); // </p>
}
- generateIncludes(fn, marker);
+#endif
generateStatus(fn, marker);
generateThreadSafeness(fn, marker);
generateSince(fn, marker);
@@ -2148,12 +2154,15 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
writeStartTag(DT_cxxClassDetail);
enterApiDesc(QString(),title);
+#if 0
+ // To be removed, if really not needed.
Text brief = qcn->doc().briefText(); // zzz
if (!brief.isEmpty()) {
writeStartTag(DT_p);
generateText(brief, qcn, marker);
writeEndTag(); // </p>
}
+#endif
generateQmlInstantiates(qcn, marker);
generateQmlInherits(qcn, marker);
generateQmlInheritedBy(qcn, marker);
@@ -2517,19 +2526,6 @@ void DitaXmlGenerator::generateBrief(const Node* node, CodeMarker* marker)
}
/*!
- Writes the \c {#include ...} required to include the class
- or namespace in a compilation.
- */
-void DitaXmlGenerator::generateIncludes(const InnerNode* inner, CodeMarker* marker)
-{
- if (!inner->includes().isEmpty()) {
- writeStartTag(DT_codeblock);
- writeText(marker->markedUpIncludes(inner->includes()), marker, inner);
- writeEndTag(); // </codeblock>
- }
-}
-
-/*!
zzz
Generates a table of contents beginning at \a node.
Currently just returns without writing anything.
@@ -3487,15 +3483,16 @@ QString DitaXmlGenerator::getMarkedUpSynopsis(const Node* node,
}
/*!
- Renamed from highlightedCode() in the html generator. Writes
- the \a markedCode to the current XML stream.
+ 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,
CodeMarker* marker,
const Node* relative)
{
QString src = markedCode;
- QString html;
+ QString text;
QStringRef arg;
QStringRef par1;
@@ -3528,7 +3525,7 @@ void DitaXmlGenerator::writeText(const QString& markedCode,
for (int k = 0; k != 13; ++k) {
const QString & tag = spanTags[2 * k];
if (tag == QStringRef(&src, i, tag.length())) {
- html += spanTags[2 * k + 1];
+ text += spanTags[2 * k + 1];
i += tag.length();
handled = true;
break;
@@ -3545,20 +3542,20 @@ void DitaXmlGenerator::writeText(const QString& markedCode,
}
else {
// retain all others
- html += charLangle;
+ text += charLangle;
}
}
}
else {
- html += src.at(i);
+ text += src.at(i);
++i;
}
}
// replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
// replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags
- src = html;
- html = QString();
+ src = text;
+ text = QString();
static const QString markTags[] = {
// 0 1 2 3 4 5
"link", "type", "headerfile", "func", "param", "extra"
@@ -3571,18 +3568,18 @@ void DitaXmlGenerator::writeText(const QString& markedCode,
if (parseArg(src, markTags[k], &i, n, &arg, &par1)) {
const Node* n = 0;
if (k == 0) { // <@link>
- if (!html.isEmpty()) {
- writeCharacters(html);
- html.clear();
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
}
n = CodeMarker::nodeForString(par1.toString());
QString link = linkForNode(n, relative);
addLink(link, arg);
}
else if (k == 4) { // <@param>
- if (!html.isEmpty()) {
- writeCharacters(html);
- html.clear();
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
}
writeStartTag(DT_i);
//writeCharacters(" " + arg.toString());
@@ -3590,18 +3587,18 @@ void DitaXmlGenerator::writeText(const QString& markedCode,
writeEndTag(); // </i>
}
else if (k == 5) { // <@extra>
- if (!html.isEmpty()) {
- writeCharacters(html);
- html.clear();
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
}
writeStartTag(DT_tt);
writeCharacters(arg.toString());
writeEndTag(); // </tt>
}
else {
- if (!html.isEmpty()) {
- writeCharacters(html);
- html.clear();
+ if (!text.isEmpty()) {
+ writeCharacters(text);
+ text.clear();
}
par1 = QStringRef();
QString link;
@@ -3626,12 +3623,11 @@ void DitaXmlGenerator::writeText(const QString& markedCode,
}
}
else {
- html += src.at(i++);
+ text += src.at(i++);
}
}
-
- if (!html.isEmpty()) {
- writeCharacters(html);
+ if (!text.isEmpty()) {
+ writeCharacters(text);
}
}
@@ -3816,7 +3812,7 @@ QString DitaXmlGenerator::protect(const QString& string, const QString& ) //outp
QString DitaXmlGenerator::fileBase(const Node* node) const
{
QString result;
- result = PageGenerator::fileBase(node);
+ result = Generator::fileBase(node);
#if 0
if (!node->isInnerNode()) {
switch (node->status()) {
@@ -3898,7 +3894,7 @@ QString DitaXmlGenerator::fileName(const Node* node)
if (static_cast<const FakeNode*>(node)->subType() == Node::Image)
return node->name();
}
- return PageGenerator::fileName(node);
+ return Generator::fileName(node);
}
QString DitaXmlGenerator::linkForNode(const Node* node, const Node* relative)
@@ -4162,7 +4158,7 @@ const Node* DitaXmlGenerator::findNodeForTarget(const QString& target,
const QPair<QString,QString> DitaXmlGenerator::anchorForNode(const Node* node)
{
QPair<QString,QString> anchorPair;
- anchorPair.first = PageGenerator::fileName(node);
+ anchorPair.first = Generator::fileName(node);
if (node->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
anchorPair.second = fakeNode->title();
@@ -4594,26 +4590,6 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker*
}
/*!
- Output the "Inherit by" list for the QML element,
- if it is inherited by any other elements.
- */
-void DitaXmlGenerator::generateQmlInheritedBy(const QmlClassNode* qcn,
- CodeMarker* marker)
-{
- if (qcn) {
- NodeList subs;
- QmlClassNode::subclasses(qcn->name(),subs);
- if (!subs.isEmpty()) {
- Text text;
- text << Atom::ParaLeft << "Inherited by ";
- appendSortedQmlNames(text,qcn,subs,marker);
- text << Atom::ParaRight;
- generateText(text, qcn, marker);
- }
- }
-}
-
-/*!
Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]"
line for the QML element, if there should be one.
@@ -5559,7 +5535,7 @@ void DitaXmlGenerator::writePropertyParameter(const QString& tag, const NodeList
void DitaXmlGenerator::beginSubPage(const InnerNode* node,
const QString& fileName)
{
- PageGenerator::beginSubPage(node,fileName);
+ Generator::beginSubPage(node,fileName);
(void) lookupGuidMap(fileName);
QXmlStreamWriter* writer = new QXmlStreamWriter(out().device());
xmlWriterStack.push(writer);
@@ -5580,7 +5556,7 @@ void DitaXmlGenerator::endSubPage()
qDebug() << "Missing </section> in" << outFileName() << sectionNestingLevel;
xmlWriter().writeEndDocument();
delete xmlWriterStack.pop();
- PageGenerator::endSubPage();
+ Generator::endSubPage();
}
/*!
@@ -6353,6 +6329,24 @@ DitaXmlGenerator::writeProlog(const InnerNode* inner)
xmlWriter().writeAttribute("content",i.value());
writeEndTag(); // </othermeta>
}
+ if ((tagStack.first() == DT_cxxClass && !inner->includes().isEmpty()) ||
+ (inner->type() == Node::Fake && inner->subType() == Node::HeaderFile)) {
+ writeStartTag(DT_othermeta);
+ xmlWriter().writeAttribute("name","includeFile");
+ QString text;
+ QStringList::ConstIterator i = inner->includes().begin();
+ while (i != inner->includes().end()) {
+ if ((*i).startsWith("<") && (*i).endsWith(">"))
+ text += *i;
+ else
+ text += "<" + *i + ">";
+ ++i;
+ if (i != inner->includes().end())
+ text += "\n";
+ }
+ xmlWriter().writeAttribute("content",text);
+ writeEndTag(); // </othermeta>
+ }
writeEndTag(); // </metadata>
writeEndTag(); // </prolog>
}
diff --git a/src/tools/qdoc/ditaxmlgenerator.h b/src/tools/qdoc/ditaxmlgenerator.h
index b3da02bce1..a4fc890dde 100644
--- a/src/tools/qdoc/ditaxmlgenerator.h
+++ b/src/tools/qdoc/ditaxmlgenerator.h
@@ -47,14 +47,14 @@
#include <QXmlStreamWriter>
#include "codemarker.h"
#include "config.h"
-#include "pagegenerator.h"
+#include "generator.h"
QT_BEGIN_NAMESPACE
typedef QMap<QString, QString> GuidMap;
typedef QMap<QString, GuidMap*> GuidMaps;
-class DitaXmlGenerator : public PageGenerator
+class DitaXmlGenerator : public Generator
{
public:
enum SinceType {
@@ -340,7 +340,6 @@ private:
const QString& name,
bool subpage = false);
void generateBrief(const Node* node, CodeMarker* marker);
- void generateIncludes(const InnerNode* inner, CodeMarker* marker);
void generateTableOfContents(const Node* node,
CodeMarker* marker,
Doc::Sections sectioningUnit,
@@ -381,7 +380,6 @@ private:
const InnerNode* relative,
CodeMarker* marker);
void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
- void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker);
diff --git a/src/tools/qdoc/doc/config/qt-defines.qdocconf b/src/tools/qdoc/doc/config/qt-defines.qdocconf
index 50a355f04c..e11b32dc4c 100644
--- a/src/tools/qdoc/doc/config/qt-defines.qdocconf
+++ b/src/tools/qdoc/doc/config/qt-defines.qdocconf
@@ -3,7 +3,6 @@ defines = Q_QDOC \
QT_.*_LIB \
QT_COMPAT \
QT_KEYPAD_NAVIGATION \
- QT_NO_EGL \
QT3_SUPPORT \
Q_WS_.* \
Q_OS_.* \
diff --git a/src/tools/qdoc/doc/examples/componentset/uicomponents.qdoc b/src/tools/qdoc/doc/examples/componentset/uicomponents.qdoc
index 10c23c7c0f..ad61daa3ca 100644
--- a/src/tools/qdoc/doc/examples/componentset/uicomponents.qdoc
+++ b/src/tools/qdoc/doc/examples/componentset/uicomponents.qdoc
@@ -28,10 +28,11 @@
/*!
\qmlmodule UIComponents 1.0
\title UI Components
- \brief Basic set of QML Components
+ \brief Basic set of UI components
- This is a listing of a list of QML components. These files are available
- for general import and they are based off the \l{Qt Quick Code Samples}.
+ This is a listing of a list of UI components implemented by QML types. These
+ files are available for general import and they are based off the \l{Qt
+ Quick Code Samples}.
This module is part of the \l{componentset}{UIComponents} example.
*/
diff --git a/src/tools/qdoc/doc/examples/examples.qdoc b/src/tools/qdoc/doc/examples/examples.qdoc
index 800589b9ac..236e7ae74a 100644
--- a/src/tools/qdoc/doc/examples/examples.qdoc
+++ b/src/tools/qdoc/doc/examples/examples.qdoc
@@ -29,11 +29,11 @@
\example componentset
\title QML Documentation Example
- This example demonstrates one of the ways to document QML components.
+ This example demonstrates one of the ways to document QML types.
- In particular, there are sample components that are documented with QDoc
- commands comments. There are documentation comments for the QML components
- and their public interfaces. The components are grouped into a module, the
+ In particular, there are sample types that are documented with QDoc
+ commands comments. There are documentation comments for the QML types
+ and their public interfaces. The types are grouped into a module, the
\l{UI Components} module.
The \l{componentset/uicomponents.qdoc}{uicomponents.qdoc} file generates
@@ -43,18 +43,18 @@
\section1 QML Class
- The components use the \l{qmlclass-command}{\\qmlclass} to document the
- component. In addition, they have the \l{inmodule-command}{\\inmodule}
+ The QML types use the \l{qmlclass-command}{\\qmlclass} to document the
+ type. In addition, they have the \l{inmodule-command}{\\inmodule}
command in order for QDoc to associate them to the \c UIComponents module.
QDoc uses the \l{brief-command}{\\brief} command to place a basic
- description when listing the component.
+ description when listing the types.
\section1 Properties, Signals, Handlers, and Methods
- The components have their properties, signals, handlers, and methods
+ The types have their properties, signals, handlers, and methods
defined in their respective QML files. QDoc associates the properties and
- methods to the components, therefore, you only need to place the
+ methods to the types, therefore, you only need to place the
documentation above the property, method, or signal.
To document the type of a \e {property alias}, you must use the
@@ -75,10 +75,10 @@
If you wish to omit certain parts of the documentation, you may use the
\l{omit-command}{\\omit} and \l{omit-command}{\\endomit} command.
- \section1 Components with C++ Implementation
+ \section1 QML Types with C++ Implementation
- This example only demonstrates the documentation for components in QML
+ This example only demonstrates the documentation for types in QML
files, but the regular \l{qml-documentation}{QML commands} may be placed
- inside C++ classes to define the public API of the component.
+ inside C++ classes to define the public API of the QML type.
*/
diff --git a/src/tools/qdoc/doc/qdoc-guide.qdoc b/src/tools/qdoc/doc/qdoc-guide.qdoc
index 33cc5c67fd..a875c48770 100644
--- a/src/tools/qdoc/doc/qdoc-guide.qdoc
+++ b/src/tools/qdoc/doc/qdoc-guide.qdoc
@@ -48,7 +48,7 @@
documentation set. Additionally, the guide presents special considerations
and options to documenting non-C++ API documentation as well as QML
documentation. Finally, the guide will provide a sample project
- documentation and a QML component documentation.
+ documentation and an example of a QML type documentation.
For specific QDoc information, consult the
\l{Table of Contents}{QDoc Manual}.
@@ -246,13 +246,13 @@
configuration file.
\code
outputprefixes = QML
- outputprefixes.QML = qml-components-
+ outputprefixes.QML = uicomponents-
\endcode
- The outputprefixes will, for example, prefix QML components HTML filenames.
+ The outputprefixes will, for example, prefix QML type HTML filenames.
\code
files:
- qml-components-button.html
- qml-components-scrollbar.html
+ uicomponents-button.html
+ uicomponents-scrollbar.html
\endcode
*/
@@ -295,7 +295,7 @@
\list
\li \l{enum-command}{\\enum} - for enumeration documentation
\li \l{class-command}{\\class} - for C++ class documentation
- \li \l{qmlclass-command}{\\qmlclass} - for QML component documentation
+ \li \l{qmlclass-command}{\\qmlclass} - for QML type documentation
\li \l{page-command}{\\page} - for creating a page.
\endlist
@@ -411,7 +411,7 @@
\li Article
\li FAQ (Frequently Asked Questions)
\li C++ API Documentation
- \li QML Component Documentation
+ \li QML Type Documentation
\li Code Example
\endlist
@@ -440,7 +440,7 @@
not properly process QDoc comments in header files.
\keyword qml-documentation
- \section2 Documenting QML Components
+ \section2 Documenting QML Types
In the world of \l{Qt Quick}{QML}, there are additional entities we need to
document such as QML signals, attached properties, and QML methods.
@@ -453,7 +453,7 @@
\li \l{qmlattachedproperty-command}{\\qmlattachedproperty}
\li \l{qmlattachedsignal-command}{\\qmlattachedsignal}
\li \l{qmlbasictype-command}{\\qmlbasictype}
- \li \l{qmlclass-command}{\\qmlclass} - creates a QML component documentation
+ \li \l{qmlclass-command}{\\qmlclass} - creates a QML type documentation
\li \l{qmlmethod-command}{\\qmlmethod}
\li \l{qmlproperty-command}{\\qmlproperty}
\li \l{qmlsignal-command}{\\qmlsignal}
@@ -511,25 +511,25 @@
\section3 QML Modules
- A component belongs to a component \e set or a \e module. The module
- may include all the related components for a platform or contain a certain
+ A QML type belongs to a \e module. The module
+ may include all the related types for a platform or contain a certain
version of \l{Qt Quick}. For example, the Qt Quick 2 \l{QML Elements} belong
to the QtQuick2 module while there is also a QtQuick1 module for the older
- elements introduced in Qt 4.
+ types introduced in Qt 4.
- Modules affect the way Qdoc link and relate the components. The
+ Modules affect the way Qdoc link and relate the types. The
\l{qmlclass-command}{\\qmlclass} topic command must have an
\l{inqmlmodule-command}{\\inqmlmodule} context command to relate the
- component to a module. Similarly, a \l{qmlmodule-command}{\\qmlmodule} topic
+ type to a module. Similarly, a \l{qmlmodule-command}{\\qmlmodule} topic
command must exist in a separate \c .qdoc file to create the overview page
- for the module. The overview page will list the related components.
+ for the module. The overview page will list the related types.
- The links to the components, must therefore, also contain the module name.
- For example, if a component called \c TabWidget is in the \c UIComponents
+ The links to the QML types, must therefore, also contain the module name.
+ For example, if a type called \c TabWidget is in the \c UIComponents
module, it must be linked as \c {UIComponents::TabWidget}.
The \l{componentset}{UIComponents} example demonstrates proper usage of
- QDoc commands to document QML components and QML modules.
+ QDoc commands to document QML types and QML modules.
\section3 Read-only and Internal QML Properties
@@ -539,7 +539,7 @@
\code
readonly property int sampleReadOnlyProperty: 0
\endcode
- For example, the example \l{TabWidget} component has a fictitious read-only
+ For example, the example \l{TabWidget} type has a fictitious read-only
property \c sampleReadOnlyProperty. Its declaration has the \c readonly
identifier and it has an initial value.
diff --git a/src/tools/qdoc/doc/qdoc-manual.qdoc b/src/tools/qdoc/doc/qdoc-manual.qdoc
index e6bdf5af27..342cabc432 100644
--- a/src/tools/qdoc/doc/qdoc-manual.qdoc
+++ b/src/tools/qdoc/doc/qdoc-manual.qdoc
@@ -5202,7 +5202,7 @@
\li tutorial - For text pages that are part of a tutorial.
\li api - This is the type of page used for C++ class references
- and QML element references, etc. You should never use this one for
+ and QML type references, etc. You should never use this one for
the pages you write, because this one is reserved for qdoc.
\endlist
@@ -5351,13 +5351,13 @@
\section1 \\qmlattachedproperty
The \\qmlattachedproperty command is for documenting a QML
- property that will be attached to some QML element type. See
+ property that will be attached to some QML type. See
\l{http://doc.qt.nokia.com/4.7/qdeclarativeintroduction.html#attached-properties}
{Attached Properties}. The argument is the rest of the line. The
argument text should be the property type, followed by the QML
element name where the property is being declared, the \c{::}
qualifier, and finally the property name. If we have a QML
- attached property named \c isCurrentItem in QML element \c ListView,
+ attached property named \c isCurrentItem in QML \c ListView,
and the property has type \c {bool}, the \\qmlattachedproperty for
it would look like this:
@@ -5389,7 +5389,7 @@
the \l{qmlsignal-command} {\\qmlsignal} command.
The argument is the rest of the line. It should be the name of the
- QML element where the signal handler is declared, the \c{::}
+ QML type where the signal handler is declared, the \c{::}
qualifier, and finally the signal handler name. If we have a QML
attached signal handler named \c onAdd() in the \c GridView
element, the \\qmlattachedsignal for it would look like this:
@@ -5447,10 +5447,10 @@
\target qmlclass-command
\section1 \\qmlclass
- The \\qmlclass command is for documenting a QML element that is
+ The \\qmlclass command is for documenting a QML type that is
instantiated by a C++ class. The command has two arguments. The
- first argument is the name of the QML element. The second argument
- is the name of the C++ class that instantiates the QML element.
+ first argument is the name of the QML type. The second argument
+ is the name of the C++ class that instantiates the QML type.
\code
/ *!
@@ -5481,12 +5481,12 @@
\endcode
This example generates the
- \l {http://doc.qt.nokia.com/4.7/qml-transform.html} {QML Transform
- Element} page. The \\qmlclass comment should include the \l
- {since-command} {\\since} command, because all QML elements are
+ \l {http://doc.qt.nokia.com/4.7/qml-transform.html} {QML Transform}
+ page. The \\qmlclass comment should include the \l
+ {since-command} {\\since} command, because all QML types are
new. It should also include the \l{brief-command} {\\brief}
- command. And since every QML element is a member of a group of QML
- elements, it should also include one or more \l{ingroup-command}
+ command. And if a type is a member of a group of QML
+ types, it should also include one or more \l{ingroup-command}
{\\ingroup} commands.
\target qmlmethod-command
@@ -5521,9 +5521,9 @@
The \\qmlproperty command is for documenting a QML property. The
argument is the rest of the line. The argument text should be the
- property type, followed by the QML element name, the \c{::}
+ property type, followed by the QML type name, the \c{::}
qualifier, and finally the property name. If we have a QML
- property named \c x in QML element \c Translate, and the property
+ property named \c x in QML type \c Translate, and the property
has type \c {real}, the \\qmlproperty for it would look like this:
\code
@@ -5544,7 +5544,7 @@
The \\qmlsignal command is for documenting a
\l{http://doc.qt.nokia.com/4.7/qdeclarativeintroduction.html#signal-handlers}
{signal handler}.
- The argument is the rest of the line. It should be the QML element where the
+ The argument is the rest of the line. It should be the QML type where the
signal handler is declared, the \c{::} qualifier, and finally the signal
handler name. If we have a QML signal handler named \c onAdd() in QML
element \c MouseArea, the \\qmlsignal for it would look like this:
@@ -5571,7 +5571,7 @@
\section1 \\qmlmodule
Insert the \c{\\qmlmodule} command to create a \c QML module page. A QML
- module is a collection of QML components or any related material. This
+ module is a collection of QML types or any related material. This
command is similar to the \l{group-command}.
A QML class may belong to a module by inserting the
@@ -5594,7 +5594,7 @@
\endcode
The \l{componentset}{UIComponents} example demonstrates proper usage of
- QDoc commands to document QML components and QML modules.
+ QDoc commands to document QML types and QML modules.
\target inqmlmodule-command
\section1 \\inqmlmodule
@@ -5615,7 +5615,7 @@
\c{\l ClickableComponents::ClickableButton} format.
The \l{componentset}{UIComponents} example demonstrates proper usage of
- QDoc commands to document QML components and QML modules.
+ QDoc commands to document QML types and QML modules.
\target typedef-command
\section1 \\typedef
@@ -6154,7 +6154,7 @@
See how QDoc renders this property on the reference page for the
\l {http://doc.qt.nokia.com/4.7/qml-state.html#changes-prop} {State}
- element.
+ type.
\target obsolete-command
\section1 \\obsolete
@@ -6538,18 +6538,18 @@
is an overload of another function, or this function is a
reimplementation of another function, or this typedef is \e
related to some class or header file. There is also a command
- for documenting that a QML element inherits some other QML
- element.
+ for documenting that a QML type inherits some other QML
+ type.
\section1 Commands
\target inherits-command
\section2 \\inherits
- The \\inherits command is for documenting that one QML element
- inherits some other QML element. It must be included in the
+ The \\inherits command is for documenting that one QML type
+ inherits some other QML type. It must be included in the
inheriting element's \l{qmlclass-command}{\\qmlclass} comment.
- The argument is the name of the inherited QML element.
+ The argument is the name of the inherited QML type.
\code
/ *!
@@ -7957,12 +7957,12 @@
\code
outputprefixes = QML
- outputprefixes.QML = qt-components-
+ outputprefixes.QML = uicomponents-
\endcode
- By default, files containing the API documentation for QML elements
- or components are prefixed with "qml-". In the above example, the
- prefix "qt-components-" is used instead.
+ By default, files containing the API documentation for QML types
+ are prefixed with "qml-". In the above example, the
+ prefix \c "uicomponents" is used instead.
\target qhp-variable
\section1 qhp
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index c990413234..97ab5652ae 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -42,13 +42,11 @@
/*
generator.cpp
*/
-#include <qdir.h>
-#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES
-#include <qdebug.h>
-#endif
-#include <qdebug.h>
+#include <QDir>
+#include <QDebug>
#include "codemarker.h"
#include "config.h"
+#include "ditaxmlgenerator.h"
#include "doc.h"
#include "editdistance.h"
#include "generator.h"
@@ -57,28 +55,25 @@
#include "quoter.h"
#include "separator.h"
#include "tokenizer.h"
-#include "ditaxmlgenerator.h"
+#include "tree.h"
QT_BEGIN_NAMESPACE
-QList<Generator *> Generator::generators;
+QString Generator::baseDir_;
+QStringList Generator::exampleDirs;
+QStringList Generator::exampleImgExts;
QMap<QString, QMap<QString, QString> > Generator::fmtLeftMaps;
QMap<QString, QMap<QString, QString> > Generator::fmtRightMaps;
-QMap<QString, QStringList> Generator::imgFileExts;
-QSet<QString> Generator::outputFormats;
-QStringList Generator::imageFiles;
+QList<Generator *> Generator::generators;
QStringList Generator::imageDirs;
-QStringList Generator::exampleDirs;
-QStringList Generator::exampleImgExts;
-QStringList Generator::scriptFiles;
-QStringList Generator::scriptDirs;
-QStringList Generator::styleFiles;
-QStringList Generator::styleDirs;
+QStringList Generator::imageFiles;
+QMap<QString, QStringList> Generator::imgFileExts;
QString Generator::outDir_;
-QString Generator::baseDir_;
-QString Generator::project;
+QSet<QString> Generator::outputFormats;
QHash<QString, QString> Generator::outputPrefixes;
-
+QString Generator::project;
+QStringList Generator::scriptDirs;
+QStringList Generator::scriptFiles;
QString Generator::sinceTitles[] =
{
" New Namespaces",
@@ -98,19 +93,14 @@ QString Generator::sinceTitles[] =
" New QML Methods",
""
};
+QStringList Generator::styleDirs;
+QStringList Generator::styleFiles;
-static void singularPlural(Text& text, const NodeList& nodes)
-{
- if (nodes.count() == 1)
- text << " is";
- else
- text << " are";
-}
Generator::Generator()
: amp("&amp;"),
- lt("&lt;"),
gt("&gt;"),
+ lt("&lt;"),
quot("&quot;"),
tag("</?@[^>]*>")
{
@@ -122,233 +112,371 @@ Generator::~Generator()
generators.removeAll(this);
}
-void Generator::initializeGenerator(const Config & /* config */)
+void Generator::appendFullName(Text& text,
+ const Node *apparentNode,
+ const Node *relative,
+ CodeMarker *marker,
+ const Node *actualNode)
{
+ if (actualNode == 0)
+ actualNode = apparentNode;
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, marker->plainFullName(apparentNode, relative))
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
-void Generator::terminateGenerator()
+void Generator::appendFullName(Text& text,
+ const Node *apparentNode,
+ const QString& fullName,
+ const Node *actualNode)
{
+ if (actualNode == 0)
+ actualNode = apparentNode;
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, fullName)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
-void Generator::initialize(const Config &config)
+void Generator::appendFullNames(Text& text,
+ const NodeList& nodes,
+ const Node* relative,
+ CodeMarker* marker)
{
- outputFormats = config.getOutputFormats();
- if (!outputFormats.isEmpty()) {
- outDir_ = config.getOutputDir();
- baseDir_ = config.getString(CONFIG_BASEDIR);
- if (!baseDir_.isEmpty())
- config.location().warning(tr("\"basedir\" specified in config file. "
- "All output will be in module directories of the output directory"));
- if (outDir_.isEmpty())
- config.lastLocation().fatal(tr("No output directory specified in configuration file or on the command line"));
+ NodeList::ConstIterator n = nodes.begin();
+ int index = 0;
+ while (n != nodes.end()) {
+ appendFullName(text,*n,relative,marker);
+ text << comma(index++,nodes.count());
+ ++n;
+ }
+}
- QDir dirInfo;
- if (dirInfo.exists(outDir_)) {
- if (!Config::removeDirContents(outDir_))
- config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir_));
- }
- else {
- if (!dirInfo.mkpath(outDir_))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_));
+void Generator::appendSortedNames(Text& text,
+ const ClassNode *classe,
+ const QList<RelatedClass> &classes,
+ CodeMarker *marker)
+{
+ QList<RelatedClass>::ConstIterator r;
+ QMap<QString,Text> classMap;
+ int index = 0;
+
+ r = classes.begin();
+ while (r != classes.end()) {
+ if ((*r).node->access() == Node::Public &&
+ (*r).node->status() != Node::Internal
+ && !(*r).node->doc().isEmpty()) {
+ Text className;
+ appendFullName(className, (*r).node, classe, marker);
+ classMap[className.toString().toLower()] = className;
}
+ ++r;
+ }
- if (!dirInfo.mkdir(outDir_ + "/images"))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'")
- .arg(outDir_ + "/images"));
- if (!dirInfo.mkdir(outDir_ + "/images/used-in-examples"))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'")
- .arg(outDir_ + "/images/used-in-examples"));
- if (!dirInfo.mkdir(outDir_ + "/scripts"))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'")
- .arg(outDir_ + "/scripts"));
- if (!dirInfo.mkdir(outDir_ + "/style"))
- config.lastLocation().fatal(tr("Cannot create output directory '%1'")
- .arg(outDir_ + "/style"));
+ QStringList classNames = classMap.keys();
+ classNames.sort();
+
+ foreach (const QString &className, classNames) {
+ text << classMap[className];
+ text << separator(index++, classNames.count());
}
+}
- imageFiles = config.getCleanPathList(CONFIG_IMAGES);
- imageDirs = config.getCleanPathList(CONFIG_IMAGEDIRS);
- scriptFiles = config.getCleanPathList(CONFIG_SCRIPTS);
- scriptDirs = config.getCleanPathList(CONFIG_SCRIPTDIRS);
- styleFiles = config.getCleanPathList(CONFIG_STYLES);
- styleDirs = config.getCleanPathList(CONFIG_STYLEDIRS);
- exampleDirs = config.getCleanPathList(CONFIG_EXAMPLEDIRS);
- exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot +
- CONFIG_IMAGEEXTENSIONS);
+void Generator::appendSortedQmlNames(Text& text,
+ const Node* base,
+ const NodeList& subs,
+ CodeMarker *marker)
+{
+ QMap<QString,Text> classMap;
+ int index = 0;
- QString imagesDotFileExtensions =
- CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS;
- QSet<QString> formats = config.subVars(imagesDotFileExtensions);
- QSet<QString>::ConstIterator f = formats.begin();
- while (f != formats.end()) {
- imgFileExts[*f] = config.getStringList(imagesDotFileExtensions +
- Config::dot + *f);
- ++f;
+ for (int i = 0; i < subs.size(); ++i) {
+ Text t;
+ if (!base->isQtQuickNode() || !subs[i]->isQtQuickNode() ||
+ (base->qmlModuleIdentifier() == subs[i]->qmlModuleIdentifier())) {
+ appendFullName(t, subs[i], base, marker);
+ classMap[t.toString().toLower()] = t;
+ }
}
- QList<Generator *>::ConstIterator g = generators.begin();
- while (g != generators.end()) {
- if (outputFormats.contains((*g)->format())) {
- (*g)->initializeGenerator(config);
- QStringList extraImages =
- config.getCleanPathList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format());
- QStringList::ConstIterator e = extraImages.begin();
- while (e != extraImages.end()) {
- QString userFriendlyFilePath;
- QString filePath = Config::findFile(config.lastLocation(),
- imageFiles,
- imageDirs,
- *e,
- imgFileExts[(*g)->format()],
- userFriendlyFilePath);
- if (!filePath.isEmpty())
- Config::copyFile(config.lastLocation(),
- filePath,
- userFriendlyFilePath,
- (*g)->outputDir() +
- "/images");
- ++e;
- }
+ QStringList names = classMap.keys();
+ names.sort();
- // Documentation template handling
- QString templateDir = config.getString(
- (*g)->format() + Config::dot + CONFIG_TEMPLATEDIR);
+ foreach (const QString &name, names) {
+ text << classMap[name];
+ text << separator(index++, names.count());
+ }
+}
- if (!templateDir.isEmpty()) {
- QStringList noExts;
- QStringList searchDirs = QStringList() << templateDir;
- QStringList scripts =
- config.getCleanPathList((*g)->format()+Config::dot+CONFIG_SCRIPTS);
- e = scripts.begin();
- while (e != scripts.end()) {
- QString userFriendlyFilePath;
- QString filePath = Config::findFile(config.lastLocation(),
- scriptFiles,
- searchDirs,
- *e,
- noExts,
- userFriendlyFilePath);
- if (!filePath.isEmpty())
- Config::copyFile(config.lastLocation(),
- filePath,
- userFriendlyFilePath,
- (*g)->outputDir() +
- "/scripts");
- ++e;
- }
+/*!
+ Creates the file named \a fileName in the output directory.
+ Attaches a QTextStream to the created file, which is written
+ to all over the place using out().
+ */
+void Generator::beginSubPage(const InnerNode* node, const QString& fileName)
+{
+ QString path = outputDir() + QLatin1Char('/');
+ if (!node->outputSubdirectory().isEmpty())
+ path += node->outputSubdirectory() + QLatin1Char('/');
+ path += fileName;
+ QFile* outFile = new QFile(path);
+ if (!outFile->open(QFile::WriteOnly))
+ node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
+ QTextStream* out = new QTextStream(outFile);
+
+ if (outputCodec)
+ out->setCodec(outputCodec);
+ outStreamStack.push(out);
+ const_cast<InnerNode*>(node)->setOutputFileName(fileName);
+}
- QStringList styles =
- config.getCleanPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS);
- e = styles.begin();
- while (e != styles.end()) {
- QString userFriendlyFilePath;
- QString filePath = Config::findFile(config.lastLocation(),
- styleFiles,
- searchDirs,
- *e,
- noExts,
- userFriendlyFilePath);
- if (!filePath.isEmpty())
- Config::copyFile(config.lastLocation(),
- filePath,
- userFriendlyFilePath,
- (*g)->outputDir() +
- "/style");
- ++e;
- }
- }
+/*!
+ Flush the text stream associated with the subpage, and
+ then pop it off the text stream stack and delete it.
+ This terminates output of the subpage.
+ */
+void Generator::endSubPage()
+{
+ outStreamStack.top()->flush();
+ delete outStreamStack.top()->device();
+ delete outStreamStack.pop();
+}
+
+void Generator::endText(const Node * /* relative */,
+ CodeMarker * /* marker */)
+{
+}
+
+QString Generator::fileBase(const Node *node) const
+{
+ if (node->relates())
+ node = node->relates();
+ else if (!node->isInnerNode())
+ node = node->parent();
+ if (node->subType() == Node::QmlPropertyGroup) {
+ node = node->parent();
+ }
+
+ QString base = node->doc().baseName();
+ if (!base.isEmpty())
+ return base;
+
+ const Node *p = node;
+
+ forever {
+ const Node *pp = p->parent();
+ base.prepend(p->name());
+ if (!p->qmlModuleIdentifier().isEmpty())
+ base.prepend(p->qmlModuleIdentifier()+QChar('-'));
+ /*
+ To avoid file name conflicts in the html directory,
+ we prepend a prefix (by default, "qml-") to the file name of QML
+ element doc files.
+ */
+ if ((p->subType() == Node::QmlClass) ||
+ (p->subType() == Node::QmlBasicType)) {
+ base.prepend(outputPrefix(QLatin1String("QML")));
}
- ++g;
+ if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake)
+ break;
+ base.prepend(QLatin1Char('-'));
+ p = pp;
+ }
+ if (node->type() == Node::Fake) {
+ if (node->subType() == Node::Collision) {
+ const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
+ if (ncn->currentChild())
+ return fileBase(ncn->currentChild());
+ base.prepend("collision-");
+ }
+ //Was QDOC2_COMPAT, required for index.html
+ if (base.endsWith(".html"))
+ base.truncate(base.length() - 5);
}
- QRegExp secondParamAndAbove("[\2-\7]");
- QSet<QString> formattingNames = config.subVars(CONFIG_FORMATTING);
- QSet<QString>::ConstIterator n = formattingNames.begin();
- while (n != formattingNames.end()) {
- QString formattingDotName = CONFIG_FORMATTING + Config::dot + *n;
+ // the code below is effectively equivalent to:
+ // base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
+ // base = base.trimmed();
+ // base.replace(QLatin1Char(' '), QLatin1Char('-'));
+ // base = base.toLower();
+ // as this function accounted for ~8% of total running time
+ // we optimize a bit...
+
+ QString res;
+ // +5 prevents realloc in fileName() below
+ res.reserve(base.size() + 5);
+ bool begun = false;
+ for (int i = 0; i != base.size(); ++i) {
+ QChar c = base.at(i);
+ uint u = c.unicode();
+ if (u >= 'A' && u <= 'Z')
+ u -= 'A' - 'a';
+ if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) {
+ res += QLatin1Char(u);
+ begun = true;
+ }
+ else if (begun) {
+ res += QLatin1Char('-');
+ begun = false;
+ }
+ }
+ while (res.endsWith(QLatin1Char('-')))
+ res.chop(1);
+ return res;
+}
- QSet<QString> formats = config.subVars(formattingDotName);
- QSet<QString>::ConstIterator f = formats.begin();
- while (f != formats.end()) {
- QString def = config.getString(formattingDotName +
- Config::dot + *f);
- if (!def.isEmpty()) {
- int numParams = Config::numParams(def);
- int numOccs = def.count("\1");
+/*!
+ If the \a node has a URL, return the URL as the file name.
+ Otherwise, construct the file name from the fileBase() and
+ the fileExtension(), and return the constructed name.
+ */
+QString Generator::fileName(const Node* node) const
+{
+ if (!node->url().isEmpty())
+ return node->url();
- if (numParams != 1) {
- config.lastLocation().warning(tr("Formatting '%1' must "
- "have exactly one "
- "parameter (found %2)")
- .arg(*n).arg(numParams));
+ QString name = fileBase(node);
+ name += QLatin1Char('.');
+ name += fileExtension(node);
+ return name;
+}
+
+/*!
+ For generating the "New Classes... in x.y" section on the
+ What's New in Qt x.y" page.
+ */
+void Generator::findAllSince(const InnerNode *node)
+{
+ NodeList::const_iterator child = node->childNodes().constBegin();
+
+ // Traverse the tree, starting at the node supplied.
+
+ while (child != node->childNodes().constEnd()) {
+
+ QString sinceString = (*child)->since();
+
+ if (((*child)->access() != Node::Private) && !sinceString.isEmpty()) {
+
+ // Insert a new entry into each map for each new since string found.
+ NewSinceMaps::iterator nsmap = newSinceMaps.find(sinceString);
+ if (nsmap == newSinceMaps.end())
+ nsmap = newSinceMaps.insert(sinceString,NodeMultiMap());
+
+ NewClassMaps::iterator ncmap = newClassMaps.find(sinceString);
+ if (ncmap == newClassMaps.end())
+ ncmap = newClassMaps.insert(sinceString,NodeMap());
+
+ NewClassMaps::iterator nqcmap = newQmlClassMaps.find(sinceString);
+ if (nqcmap == newQmlClassMaps.end())
+ nqcmap = newQmlClassMaps.insert(sinceString,NodeMap());
+
+ if ((*child)->type() == Node::Function) {
+ // Insert functions into the general since map.
+ FunctionNode *func = static_cast<FunctionNode *>(*child);
+ if ((func->status() > Node::Obsolete) &&
+ (func->metaness() != FunctionNode::Ctor) &&
+ (func->metaness() != FunctionNode::Dtor)) {
+ nsmap.value().insert(func->name(),(*child));
}
- else if (numOccs > 1) {
- config.lastLocation().fatal(tr("Formatting '%1' must "
- "contain exactly one "
- "occurrence of '\\1' "
- "(found %2)")
- .arg(*n).arg(numOccs));
+ }
+ else if ((*child)->url().isEmpty()) {
+ if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) {
+ // Insert classes into the since and class maps.
+ QString className = (*child)->name();
+ if ((*child)->parent() &&
+ (*child)->parent()->type() == Node::Namespace &&
+ !(*child)->parent()->name().isEmpty())
+ className = (*child)->parent()->name()+"::"+className;
+
+ nsmap.value().insert(className,(*child));
+ ncmap.value().insert(className,(*child));
}
- else {
- int paramPos = def.indexOf("\1");
- fmtLeftMaps[*f].insert(*n, def.left(paramPos));
- fmtRightMaps[*f].insert(*n, def.mid(paramPos + 1));
+ else if ((*child)->subType() == Node::QmlClass) {
+ // Insert QML elements into the since and element maps.
+ QString className = (*child)->name();
+ if ((*child)->parent() &&
+ (*child)->parent()->type() == Node::Namespace &&
+ !(*child)->parent()->name().isEmpty())
+ className = (*child)->parent()->name()+"::"+className;
+
+ nsmap.value().insert(className,(*child));
+ nqcmap.value().insert(className,(*child));
+ }
+ else if ((*child)->type() == Node::QmlProperty) {
+ // Insert QML properties into the since map.
+ QString propertyName = (*child)->name();
+ nsmap.value().insert(propertyName,(*child));
}
}
- ++f;
- }
- ++n;
- }
+ else {
+ // Insert external documents into the general since map.
+ QString name = (*child)->name();
+ if ((*child)->parent() &&
+ (*child)->parent()->type() == Node::Namespace &&
+ !(*child)->parent()->name().isEmpty())
+ name = (*child)->parent()->name()+"::"+name;
- project = config.getString(CONFIG_PROJECT);
+ nsmap.value().insert(name,(*child));
+ }
- QStringList prefixes = config.getStringList(CONFIG_OUTPUTPREFIXES);
- if (!prefixes.isEmpty()) {
- foreach (QString prefix, prefixes)
- outputPrefixes[prefix] = config.getString(
- CONFIG_OUTPUTPREFIXES + Config::dot + prefix);
- } else
- outputPrefixes[QLatin1String("QML")] = QLatin1String("qml-");
+ // Find child nodes with since commands.
+ if ((*child)->isInnerNode()) {
+ findAllSince(static_cast<InnerNode *>(*child));
+ }
+ }
+ ++child;
+ }
}
-void Generator::terminate()
+QMap<QString, QString>& Generator::formattingLeftMap()
{
- QList<Generator *>::ConstIterator g = generators.begin();
- while (g != generators.end()) {
- if (outputFormats.contains((*g)->format()))
- (*g)->terminateGenerator();
- ++g;
- }
-
- fmtLeftMaps.clear();
- fmtRightMaps.clear();
- imgFileExts.clear();
- imageFiles.clear();
- imageDirs.clear();
- outDir_ = "";
- QmlClassNode::terminate();
- ExampleNode::terminate();
+ return fmtLeftMaps[format()];
}
-Generator *Generator::generatorForFormat(const QString& format)
+QMap<QString, QString>& Generator::formattingRightMap()
{
- QList<Generator *>::ConstIterator g = generators.begin();
- while (g != generators.end()) {
- if ((*g)->format() == format)
- return *g;
- ++g;
- }
- return 0;
+ return fmtRightMaps[format()];
}
-void Generator::startText(const Node * /* relative */,
- CodeMarker * /* marker */)
+QString Generator::fullName(const Node *node,
+ const Node *relative,
+ CodeMarker *marker) const
{
+ if (node->type() == Node::Fake) {
+ const FakeNode* fn = static_cast<const FakeNode *>(node);
+#if 0
+ // Removed for QTBUG-22870
+ if (!fn->qmlModuleIdentifier().isEmpty())
+ return fn->qmlModuleIdentifier() + QLatin1Char(' ') + fn->title();
+#endif
+ return fn->title();
+ }
+ else if (node->type() == Node::Class &&
+ !(static_cast<const ClassNode *>(node))->serviceName().isEmpty())
+ return (static_cast<const ClassNode *>(node))->serviceName();
+ else
+ return marker->plainFullName(node, relative);
}
-void Generator::endText(const Node * /* relative */,
- CodeMarker * /* marker */)
+void Generator::generateAlsoList(const Node *node, CodeMarker *marker)
{
+ QList<Text> alsoList = node->doc().alsoList();
+ supplementAlsoList(node, alsoList);
+
+ if (!alsoList.isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
+ << "See also "
+ << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
+
+ for (int i = 0; i < alsoList.size(); ++i)
+ text << alsoList.at(i) << separator(i, alsoList.size());
+
+ text << Atom::ParaRight;
+ generateText(text, node, marker);
+ }
}
int Generator::generateAtom(const Atom * /* atom */,
@@ -358,68 +486,65 @@ int Generator::generateAtom(const Atom * /* atom */,
return 0;
}
-void Generator::generateClassLikeNode(const InnerNode * /* classe */,
- CodeMarker * /* marker */)
-{
-}
-
-void Generator::generateFakeNode(const FakeNode * /* fake */,
- CodeMarker * /* marker */)
-{
-}
-
-bool Generator::generateText(const Text& text,
- const Node *relative,
- CodeMarker *marker)
+const Atom *Generator::generateAtomList(const Atom *atom,
+ const Node *relative,
+ CodeMarker *marker,
+ bool generate,
+ int &numAtoms)
{
- bool result = false;
- if (text.firstAtom() != 0) {
- int numAtoms = 0;
- startText(relative, marker);
- generateAtomList(text.firstAtom(),
- relative,
- marker,
- true,
- numAtoms);
- endText(relative, marker);
- result = true;
- }
- return result;
-}
+ while (atom) {
+ if (atom->type() == Atom::FormatIf) {
+ int numAtoms0 = numAtoms;
+ bool rightFormat = canHandleFormat(atom->string());
+ atom = generateAtomList(atom->next(),
+ relative,
+ marker,
+ generate && rightFormat,
+ numAtoms);
+ if (!atom)
+ return 0;
-#ifdef QDOC_QML
-/*!
- Extract sections of markup text surrounded by \e qmltext
- and \e endqmltext and output them.
- */
-bool Generator::generateQmlText(const Text& text,
- const Node *relative,
- CodeMarker *marker,
- const QString& /* qmlName */ )
-{
- const Atom* atom = text.firstAtom();
- bool result = false;
+ if (atom->type() == Atom::FormatElse) {
+ ++numAtoms;
+ atom = generateAtomList(atom->next(),
+ relative,
+ marker,
+ generate && !rightFormat,
+ numAtoms);
+ if (!atom)
+ return 0;
+ }
- if (atom != 0) {
- startText(relative, marker);
- while (atom) {
- if (atom->type() != Atom::QmlText)
- atom = atom->next();
- else {
- atom = atom->next();
- while (atom && (atom->type() != Atom::EndQmlText)) {
- int n = 1 + generateAtom(atom, relative, marker);
- while (n-- > 0)
- atom = atom->next();
+ if (atom->type() == Atom::FormatEndif) {
+ if (generate && numAtoms0 == numAtoms) {
+ relative->location().warning(tr("Output format %1 not handled %2")
+ .arg(format()).arg(outFileName()));
+ Atom unhandledFormatAtom(Atom::UnhandledFormat, format());
+ generateAtomList(&unhandledFormatAtom,
+ relative,
+ marker,
+ generate,
+ numAtoms);
}
+ atom = atom->next();
}
}
- endText(relative, marker);
- result = true;
+ else if (atom->type() == Atom::FormatElse ||
+ atom->type() == Atom::FormatEndif) {
+ return atom;
+ }
+ else {
+ int n = 1;
+ if (generate) {
+ n += generateAtom(atom, relative, marker);
+ numAtoms += n;
+ }
+ while (n-- > 0)
+ atom = atom->next();
+ }
}
- return result;
+ return 0;
}
-#endif
void Generator::generateBody(const Node *node, CodeMarker *marker)
{
@@ -568,105 +693,22 @@ void Generator::generateBody(const Node *node, CodeMarker *marker)
}
}
-void Generator::generateAlsoList(const Node *node, CodeMarker *marker)
-{
- QList<Text> alsoList = node->doc().alsoList();
- supplementAlsoList(node, alsoList);
-
- if (!alsoList.isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "See also "
- << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
-
- for (int i = 0; i < alsoList.size(); ++i)
- text << alsoList.at(i) << separator(i, alsoList.size());
-
- text << Atom::ParaRight;
- generateText(text, node, marker);
- }
-}
-
-/*!
- Generate a list of maintainers in the output
- */
-void Generator::generateMaintainerList(const InnerNode* node, CodeMarker* marker)
-{
- QStringList sl = getMetadataElements(node,"maintainer");
-
- if (!sl.isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "Maintained by: "
- << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
-
- for (int i = 0; i < sl.size(); ++i)
- text << sl.at(i) << separator(i, sl.size());
-
- text << Atom::ParaRight;
- generateText(text, node, marker);
- }
-}
-
-void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
+void Generator::generateClassLikeNode(const InnerNode * /* classe */,
+ CodeMarker * /* marker */)
{
- QList<RelatedClass>::ConstIterator r;
- int index;
-
- if (!classe->baseClasses().isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "Inherits: "
- << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
-
- r = classe->baseClasses().begin();
- index = 0;
- while (r != classe->baseClasses().end()) {
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
-
- if ((*r).access == Node::Protected) {
- text << " (protected)";
- }
- else if ((*r).access == Node::Private) {
- text << " (private)";
- }
- text << separator(index++, classe->baseClasses().count());
- ++r;
- }
- text << Atom::ParaRight;
- generateText(text, classe, marker);
- }
}
-#ifdef QDOC_QML
-/*!
- */
-void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* )
+void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker)
{
- // stub.
+ if (fake->childNodes().isEmpty())
+ return;
+ generateFileList(fake, marker, Node::File, QString("Files:"));
+ generateFileList(fake, marker, Node::Image, QString("Images:"));
}
-#endif
-void Generator::generateInheritedBy(const ClassNode *classe,
- CodeMarker *marker)
+void Generator::generateFakeNode(const FakeNode * /* fake */,
+ CodeMarker * /* marker */)
{
- if (!classe->derivedClasses().isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
- << "Inherited by: "
- << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
-
- appendSortedNames(text, classe, classe->derivedClasses(), marker);
- text << Atom::ParaRight;
- generateText(text, classe, marker);
- }
}
/*!
@@ -734,193 +776,250 @@ void Generator::generateFileList(const FakeNode* fake,
generateText(text, fake, marker);
}
-void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker)
+void Generator::generateInheritedBy(const ClassNode *classe,
+ CodeMarker *marker)
{
- if (fake->childNodes().isEmpty())
- return;
- generateFileList(fake, marker, Node::File, QString("Files:"));
- generateFileList(fake, marker, Node::Image, QString("Images:"));
+ if (!classe->derivedClasses().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
+ << "Inherited by: "
+ << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
+
+ appendSortedNames(text, classe, classe->derivedClasses(), marker);
+ text << Atom::ParaRight;
+ generateText(text, classe, marker);
+ }
}
-QString Generator::indent(int level, const QString& markedCode)
+void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker)
{
- if (level == 0)
- return markedCode;
+ QList<RelatedClass>::ConstIterator r;
+ int index;
- QString t;
- int column = 0;
+ if (!classe->baseClasses().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
+ << "Inherits: "
+ << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
- int i = 0;
- while (i < (int) markedCode.length()) {
- if (markedCode.at(i) == QLatin1Char('\n')) {
- column = 0;
- }
- else {
- if (column == 0) {
- for (int j = 0; j < level; j++)
- t += QLatin1Char(' ');
+ r = classe->baseClasses().begin();
+ index = 0;
+ while (r != classe->baseClasses().end()) {
+ text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node))
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << Atom(Atom::String, (*r).dataTypeWithTemplateArgs)
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+
+ if ((*r).access == Node::Protected) {
+ text << " (protected)";
}
- column++;
+ else if ((*r).access == Node::Private) {
+ text << " (private)";
+ }
+ text << separator(index++, classe->baseClasses().count());
+ ++r;
}
- t += markedCode.at(i++);
+ text << Atom::ParaRight;
+ generateText(text, classe, marker);
}
- return t;
}
-QString Generator::plainCode(const QString& markedCode)
-{
- QString t = markedCode;
- t.replace(tag, QString());
- t.replace(quot, QLatin1String("\""));
- t.replace(gt, QLatin1String(">"));
- t.replace(lt, QLatin1String("<"));
- t.replace(amp, QLatin1String("&"));
- return t;
-}
+/*!
+ Recursive writing of HTML files from the root \a node.
-QString Generator::typeString(const Node *node)
+ \note NameCollisionNodes are skipped here and processed
+ later. See HtmlGenerator::generateDisambiguationPages()
+ for more on this.
+ */
+void Generator::generateInnerNode(const InnerNode* node)
{
- switch (node->type()) {
- case Node::Namespace:
- return "namespace";
- case Node::Class:
- return "class";
- case Node::Fake:
- {
- switch (node->subType()) {
- case Node::QmlClass:
- return "element";
- case Node::QmlPropertyGroup:
- return "property group";
- case Node::QmlBasicType:
- return "type";
- default:
- return "documentation";
+ if (!node->url().isNull())
+ return;
+
+ if (node->type() == Node::Fake) {
+ const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
+ if (fakeNode->subType() == Node::ExternalPage)
+ return;
+ if (fakeNode->subType() == Node::Image)
+ return;
+ if (fakeNode->subType() == Node::QmlPropertyGroup)
+ return;
+ if (fakeNode->subType() == Node::Page) {
+ if (node->count() > 0)
+ qDebug("PAGE %s HAS CHILDREN", qPrintable(fakeNode->title()));
}
}
- case Node::Enum:
- return "enum";
- case Node::Typedef:
- return "typedef";
- case Node::Function:
- return "function";
- case Node::Property:
- return "property";
- default:
- return "documentation";
+
+ /*
+ Obtain a code marker for the source file.
+ */
+ CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
+
+ if (node->parent() != 0) {
+ /*
+ Skip name collision nodes here and process them
+ later in generateDisambiguationPages(). Each one
+ is appended to a list for later.
+ */
+ if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) {
+ const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
+ collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
+ }
+ else {
+ beginSubPage(node, fileName(node));
+ if (node->type() == Node::Namespace || node->type() == Node::Class) {
+ generateClassLikeNode(node, marker);
+ }
+ else if (node->type() == Node::Fake) {
+ generateFakeNode(static_cast<const FakeNode *>(node), marker);
+ }
+ endSubPage();
+ }
+ }
+
+ NodeList::ConstIterator c = node->childNodes().begin();
+ while (c != node->childNodes().end()) {
+ if ((*c)->isInnerNode() && (*c)->access() != Node::Private) {
+ generateInnerNode((const InnerNode *) *c);
+ }
+ ++c;
}
}
/*!
- Returns a relative path name for an image.
+ Generate a list of maintainers in the output
*/
-QString Generator::imageFileName(const Node *relative, const QString& fileBase)
+void Generator::generateMaintainerList(const InnerNode* node, CodeMarker* marker)
{
- QString userFriendlyFilePath;
- QString filePath = Config::findFile(
- relative->doc().location(), imageFiles, imageDirs, fileBase,
- imgFileExts[format()], userFriendlyFilePath);
+ QStringList sl = getMetadataElements(node,"maintainer");
- if (filePath.isEmpty())
- return QString();
+ if (!sl.isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD)
+ << "Maintained by: "
+ << Atom(Atom::FormattingRight,ATOM_FORMATTING_BOLD);
- QString path = Config::copyFile(relative->doc().location(),
- filePath,
- userFriendlyFilePath,
- outputDir() + QLatin1String("/images"));
- QString images = "images";
- if (path[0] != '/')
- images.append(QLatin1Char('/'));
- return images + path;
-}
+ for (int i = 0; i < sl.size(); ++i)
+ text << sl.at(i) << separator(i, sl.size());
-void Generator::setImageFileExtensions(const QStringList& extensions)
-{
- imgFileExts[format()] = extensions;
+ text << Atom::ParaRight;
+ generateText(text, node, marker);
+ }
}
-void Generator::unknownAtom(const Atom *atom)
+#ifdef QDOC_QML
+/*!
+ Output the "Inherit by" list for the QML element,
+ if it is inherited by any other elements.
+ */
+void Generator::generateQmlInheritedBy(const QmlClassNode* qcn,
+ CodeMarker* marker)
{
- Location::internalError(tr("unknown atom type '%1' in %2 generator")
- .arg(atom->typeString()).arg(format()));
+ if (qcn) {
+ NodeList subs;
+ QmlClassNode::subclasses(qcn->name(),subs);
+ if (!subs.isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft << "Inherited by ";
+ appendSortedQmlNames(text,qcn,subs,marker);
+ text << Atom::ParaRight;
+ generateText(text, qcn, marker);
+ }
+ }
}
+#endif
-bool Generator::matchAhead(const Atom *atom, Atom::Type expectedAtomType)
+#ifdef QDOC_QML
+/*!
+ */
+void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* )
{
- return atom->next() != 0 && atom->next()->type() == expectedAtomType;
+ // stub.
}
+#endif
-void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)
+#ifdef QDOC_QML
+/*!
+ Extract sections of markup text surrounded by \e qmltext
+ and \e endqmltext and output them.
+ */
+bool Generator::generateQmlText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker,
+ const QString& /* qmlName */ )
{
- if (node->type() == Node::Function) {
- const FunctionNode *func = static_cast<const FunctionNode *>(node);
- if (func->overloadNumber() == 1) {
- QString alternateName;
- const FunctionNode *alternateFunc = 0;
-
- if (func->name().startsWith("set") && func->name().size() >= 4) {
- alternateName = func->name()[3].toLower();
- alternateName += func->name().mid(4);
- alternateFunc = func->parent()->findFunctionNode(alternateName);
-
- if (!alternateFunc) {
- alternateName = "is" + func->name().mid(3);
- alternateFunc = func->parent()->findFunctionNode(alternateName);
- if (!alternateFunc) {
- alternateName = "has" + func->name().mid(3);
- alternateFunc = func->parent()->findFunctionNode(alternateName);
- }
- }
- }
- else if (!func->name().isEmpty()) {
- alternateName = "set";
- alternateName += func->name()[0].toUpper();
- alternateName += func->name().mid(1);
- alternateFunc = func->parent()->findFunctionNode(alternateName);
- }
-
- if (alternateFunc && alternateFunc->access() != Node::Private) {
- int i;
- for (i = 0; i < alsoList.size(); ++i) {
- if (alsoList.at(i).toString().contains(alternateName))
- break;
- }
-
- if (i == alsoList.size()) {
- alternateName += "()";
+ const Atom* atom = text.firstAtom();
+ bool result = false;
- Text also;
- also << Atom(Atom::Link, alternateName)
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << alternateName
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
- alsoList.prepend(also);
+ if (atom != 0) {
+ startText(relative, marker);
+ while (atom) {
+ if (atom->type() != Atom::QmlText)
+ atom = atom->next();
+ else {
+ atom = atom->next();
+ while (atom && (atom->type() != Atom::EndQmlText)) {
+ int n = 1 + generateAtom(atom, relative, marker);
+ while (n-- > 0)
+ atom = atom->next();
}
}
}
+ endText(relative, marker);
+ result = true;
}
+ return result;
}
+#endif
-QMap<QString, QString>& Generator::formattingLeftMap()
+void Generator::generateReimplementedFrom(const FunctionNode *func,
+ CodeMarker *marker)
{
- return fmtLeftMaps[format()];
+ if (func->reimplementedFrom() != 0) {
+ const FunctionNode *from = func->reimplementedFrom();
+ if (from->access() != Node::Private &&
+ from->parent()->access() != Node::Private) {
+ Text text;
+ text << Atom::ParaLeft << "Reimplemented from ";
+ QString fullName = from->parent()->name() + "::" + from->name() + "()";
+ appendFullName(text, from->parent(), fullName, from);
+ text << "." << Atom::ParaRight;
+ generateText(text, func, marker);
+ }
+ }
}
-QMap<QString, QString>& Generator::formattingRightMap()
+void Generator::generateSince(const Node *node, CodeMarker *marker)
{
- return fmtRightMaps[format()];
-}
+ if (!node->since().isEmpty()) {
+ Text text;
+ text << Atom::ParaLeft
+ << "This "
+ << typeString(node);
+ if (node->type() == Node::Enum)
+ text << " was introduced or modified in ";
+ else
+ text << " was introduced in ";
-/*
- Trims trailimng whitespace off the \a string and returns
- the trimmed string.
- */
-QString Generator::trimmedTrailing(const QString& string)
-{
- QString trimmed = string;
- while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace())
- trimmed.truncate(trimmed.length() - 1);
- return trimmed;
+ QStringList since = node->since().split(QLatin1Char(' '));
+ if (since.count() == 1) {
+ // Handle legacy use of \since <version>.
+ if (project.isEmpty())
+ text << "version";
+ else
+ text << project;
+ text << " " << since[0];
+ } else {
+ // Reconstruct the <project> <version> string.
+ text << " " << since.join(" ");
+ }
+
+ text << "." << Atom::ParaRight;
+ generateText(text, node, marker);
+ }
}
void Generator::generateStatus(const Node *node, CodeMarker *marker)
@@ -967,13 +1066,10 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker)
<< Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
<< "This "
<< typeString(node)
- << " is part of the Qt 3 compatibility layer."
+ << " is part of the Qt compatibility layer."
<< Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
<< " It is provided to keep old source code working. "
- << "We strongly advise against "
- << "using it in new code. See "
- << Atom(Atom::AutoLink, "Porting to Qt 4")
- << " for more information."
+ << "We strongly advise against using it in new code."
<< Atom::ParaRight;
}
break;
@@ -984,10 +1080,28 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker)
generateText(text, node, marker);
}
+bool Generator::generateText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker)
+{
+ bool result = false;
+ if (text.firstAtom() != 0) {
+ int numAtoms = 0;
+ startText(relative, marker);
+ generateAtomList(text.firstAtom(),
+ relative,
+ marker,
+ true,
+ numAtoms);
+ endText(relative, marker);
+ result = true;
+ }
+ return result;
+}
+
void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
{
Text text;
- Text theStockLink;
Node::ThreadSafeness threadSafeness = node->threadSafeness();
Text rlink;
@@ -1125,208 +1239,438 @@ void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker)
generateText(text,node,marker);
}
-void Generator::generateSince(const Node *node, CodeMarker *marker)
+/*!
+ This function is recursive.
+ */
+void Generator::generateTree(const Tree *tree)
{
- if (!node->since().isEmpty()) {
- Text text;
- text << Atom::ParaLeft
- << "This "
- << typeString(node);
- if (node->type() == Node::Enum)
- text << " was introduced or modified in ";
- else
- text << " was introduced in ";
+ generateInnerNode(tree->root());
+}
- QStringList since = node->since().split(QLatin1Char(' '));
- if (since.count() == 1) {
- // Handle legacy use of \since <version>.
- if (project.isEmpty())
- text << "version";
- else
- text << project;
- text << " " << since[0];
- } else {
- // Reconstruct the <project> <version> string.
- text << " " << since.join(" ");
- }
+Generator *Generator::generatorForFormat(const QString& format)
+{
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if ((*g)->format() == format)
+ return *g;
+ ++g;
+ }
+ return 0;
+}
- text << "." << Atom::ParaRight;
- generateText(text, node, marker);
+/*!
+ Looks up the tag \a t in the map of metadata values for the
+ current topic in \a inner. If a value for the tag is found,
+ the value is returned.
+
+ \note If \a t is found in the metadata map, it is erased.
+ i.e. Once you call this function for a particular \a t,
+ you consume \a t.
+ */
+QString Generator::getMetadataElement(const InnerNode* inner, const QString& t)
+{
+ QString s;
+ QStringMultiMap& metaTagMap = const_cast<QStringMultiMap&>(inner->doc().metaTagMap());
+ QStringMultiMap::iterator i = metaTagMap.find(t);
+ if (i != metaTagMap.end()) {
+ s = i.value();
+ metaTagMap.erase(i);
}
+ return s;
}
-void Generator::generateReimplementedFrom(const FunctionNode *func,
- CodeMarker *marker)
+/*!
+ Looks up the tag \a t in the map of metadata values for the
+ current topic in \a inner. If values for the tag are found,
+ they are returned in a string list.
+
+ \note If \a t is found in the metadata map, all the pairs
+ having the key \a t are erased. i.e. Once you call this
+ function for a particular \a t, you consume \a t.
+ */
+QStringList Generator::getMetadataElements(const InnerNode* inner, const QString& t)
{
- if (func->reimplementedFrom() != 0) {
- const FunctionNode *from = func->reimplementedFrom();
- if (from->access() != Node::Private &&
- from->parent()->access() != Node::Private) {
- Text text;
- text << Atom::ParaLeft << "Reimplemented from ";
- QString fullName = from->parent()->name() + "::" + from->name() + "()";
- appendFullName(text, from->parent(), fullName, from);
- text << "." << Atom::ParaRight;
- generateText(text, func, marker);
+ QStringList s;
+ QStringMultiMap& metaTagMap = const_cast<QStringMultiMap&>(inner->doc().metaTagMap());
+ s = metaTagMap.values(t);
+ if (!s.isEmpty())
+ metaTagMap.remove(t);
+ return s;
+}
+
+/*!
+ Returns a relative path name for an image.
+ */
+QString Generator::imageFileName(const Node *relative, const QString& fileBase)
+{
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(
+ relative->doc().location(), imageFiles, imageDirs, fileBase,
+ imgFileExts[format()], userFriendlyFilePath);
+
+ if (filePath.isEmpty())
+ return QString();
+
+ QString path = Config::copyFile(relative->doc().location(),
+ filePath,
+ userFriendlyFilePath,
+ outputDir() + QLatin1String("/images"));
+ QString images = "images";
+ if (path[0] != '/')
+ images.append(QLatin1Char('/'));
+ return images + path;
+}
+
+QString Generator::indent(int level, const QString& markedCode)
+{
+ if (level == 0)
+ return markedCode;
+
+ QString t;
+ int column = 0;
+
+ int i = 0;
+ while (i < (int) markedCode.length()) {
+ if (markedCode.at(i) == QLatin1Char('\n')) {
+ column = 0;
}
+ else {
+ if (column == 0) {
+ for (int j = 0; j < level; j++)
+ t += QLatin1Char(' ');
+ }
+ column++;
+ }
+ t += markedCode.at(i++);
}
+ return t;
}
-const Atom *Generator::generateAtomList(const Atom *atom,
- const Node *relative,
- CodeMarker *marker,
- bool generate,
- int &numAtoms)
+void Generator::initialize(const Config &config)
{
- while (atom) {
- if (atom->type() == Atom::FormatIf) {
- int numAtoms0 = numAtoms;
- bool rightFormat = canHandleFormat(atom->string());
- atom = generateAtomList(atom->next(),
- relative,
- marker,
- generate && rightFormat,
- numAtoms);
- if (!atom)
- return 0;
+ outputFormats = config.getOutputFormats();
+ if (!outputFormats.isEmpty()) {
+ outDir_ = config.getOutputDir();
+ baseDir_ = config.getString(CONFIG_BASEDIR);
+ if (!baseDir_.isEmpty())
+ config.location().warning(tr("\"basedir\" specified in config file. "
+ "All output will be in module directories of the output directory"));
+ if (outDir_.isEmpty())
+ config.lastLocation().fatal(tr("No output directory specified in configuration file or on the command line"));
- if (atom->type() == Atom::FormatElse) {
- ++numAtoms;
- atom = generateAtomList(atom->next(),
- relative,
- marker,
- generate && !rightFormat,
- numAtoms);
- if (!atom)
- return 0;
+ QDir dirInfo;
+ if (dirInfo.exists(outDir_)) {
+ if (!Config::removeDirContents(outDir_))
+ config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir_));
+ }
+ else {
+ if (!dirInfo.mkpath(outDir_))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir_));
+ }
+
+ if (!dirInfo.mkdir(outDir_ + "/images"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir_ + "/images"));
+ if (!dirInfo.mkdir(outDir_ + "/images/used-in-examples"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir_ + "/images/used-in-examples"));
+ if (!dirInfo.mkdir(outDir_ + "/scripts"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir_ + "/scripts"));
+ if (!dirInfo.mkdir(outDir_ + "/style"))
+ config.lastLocation().fatal(tr("Cannot create output directory '%1'")
+ .arg(outDir_ + "/style"));
+ }
+
+ imageFiles = config.getCleanPathList(CONFIG_IMAGES);
+ imageDirs = config.getCleanPathList(CONFIG_IMAGEDIRS);
+ scriptFiles = config.getCleanPathList(CONFIG_SCRIPTS);
+ scriptDirs = config.getCleanPathList(CONFIG_SCRIPTDIRS);
+ styleFiles = config.getCleanPathList(CONFIG_STYLES);
+ styleDirs = config.getCleanPathList(CONFIG_STYLEDIRS);
+ exampleDirs = config.getCleanPathList(CONFIG_EXAMPLEDIRS);
+ exampleImgExts = config.getStringList(CONFIG_EXAMPLES + Config::dot +
+ CONFIG_IMAGEEXTENSIONS);
+
+ QString imagesDotFileExtensions =
+ CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS;
+ QSet<QString> formats = config.subVars(imagesDotFileExtensions);
+ QSet<QString>::ConstIterator f = formats.begin();
+ while (f != formats.end()) {
+ imgFileExts[*f] = config.getStringList(imagesDotFileExtensions +
+ Config::dot + *f);
+ ++f;
+ }
+
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if (outputFormats.contains((*g)->format())) {
+ (*g)->initializeGenerator(config);
+ QStringList extraImages =
+ config.getCleanPathList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format());
+ QStringList::ConstIterator e = extraImages.begin();
+ while (e != extraImages.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(),
+ imageFiles,
+ imageDirs,
+ *e,
+ imgFileExts[(*g)->format()],
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/images");
+ ++e;
}
- if (atom->type() == Atom::FormatEndif) {
- if (generate && numAtoms0 == numAtoms) {
- relative->location().warning(tr("Output format %1 not handled %2")
- .arg(format()).arg(outFileName()));
- Atom unhandledFormatAtom(Atom::UnhandledFormat, format());
- generateAtomList(&unhandledFormatAtom,
- relative,
- marker,
- generate,
- numAtoms);
+ // Documentation template handling
+ QString templateDir = config.getString(
+ (*g)->format() + Config::dot + CONFIG_TEMPLATEDIR);
+
+ if (!templateDir.isEmpty()) {
+ QStringList noExts;
+ QStringList searchDirs = QStringList() << templateDir;
+ QStringList scripts =
+ config.getCleanPathList((*g)->format()+Config::dot+CONFIG_SCRIPTS);
+ e = scripts.begin();
+ while (e != scripts.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(),
+ scriptFiles,
+ searchDirs,
+ *e,
+ noExts,
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/scripts");
+ ++e;
+ }
+
+ QStringList styles =
+ config.getCleanPathList((*g)->format()+Config::dot+CONFIG_STYLESHEETS);
+ e = styles.begin();
+ while (e != styles.end()) {
+ QString userFriendlyFilePath;
+ QString filePath = Config::findFile(config.lastLocation(),
+ styleFiles,
+ searchDirs,
+ *e,
+ noExts,
+ userFriendlyFilePath);
+ if (!filePath.isEmpty())
+ Config::copyFile(config.lastLocation(),
+ filePath,
+ userFriendlyFilePath,
+ (*g)->outputDir() +
+ "/style");
+ ++e;
}
- atom = atom->next();
}
}
- else if (atom->type() == Atom::FormatElse ||
- atom->type() == Atom::FormatEndif) {
- return atom;
- }
- else {
- int n = 1;
- if (generate) {
- n += generateAtom(atom, relative, marker);
- numAtoms += n;
+ ++g;
+ }
+
+ QRegExp secondParamAndAbove("[\2-\7]");
+ QSet<QString> formattingNames = config.subVars(CONFIG_FORMATTING);
+ QSet<QString>::ConstIterator n = formattingNames.begin();
+ while (n != formattingNames.end()) {
+ QString formattingDotName = CONFIG_FORMATTING + Config::dot + *n;
+
+ QSet<QString> formats = config.subVars(formattingDotName);
+ QSet<QString>::ConstIterator f = formats.begin();
+ while (f != formats.end()) {
+ QString def = config.getString(formattingDotName +
+ Config::dot + *f);
+ if (!def.isEmpty()) {
+ int numParams = Config::numParams(def);
+ int numOccs = def.count("\1");
+
+ if (numParams != 1) {
+ config.lastLocation().warning(tr("Formatting '%1' must "
+ "have exactly one "
+ "parameter (found %2)")
+ .arg(*n).arg(numParams));
+ }
+ else if (numOccs > 1) {
+ config.lastLocation().fatal(tr("Formatting '%1' must "
+ "contain exactly one "
+ "occurrence of '\\1' "
+ "(found %2)")
+ .arg(*n).arg(numOccs));
+ }
+ else {
+ int paramPos = def.indexOf("\1");
+ fmtLeftMaps[*f].insert(*n, def.left(paramPos));
+ fmtRightMaps[*f].insert(*n, def.mid(paramPos + 1));
+ }
}
- while (n-- > 0)
- atom = atom->next();
+ ++f;
}
+ ++n;
}
- return 0;
+
+ project = config.getString(CONFIG_PROJECT);
+
+ QStringList prefixes = config.getStringList(CONFIG_OUTPUTPREFIXES);
+ if (!prefixes.isEmpty()) {
+ foreach (QString prefix, prefixes)
+ outputPrefixes[prefix] = config.getString(
+ CONFIG_OUTPUTPREFIXES + Config::dot + prefix);
+ } else
+ outputPrefixes[QLatin1String("QML")] = QLatin1String("qml-");
}
-void Generator::appendFullName(Text& text,
- const Node *apparentNode,
- const Node *relative,
- CodeMarker *marker,
- const Node *actualNode)
+void Generator::initializeGenerator(const Config & /* config */)
{
- if (actualNode == 0)
- actualNode = apparentNode;
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, marker->plainFullName(apparentNode, relative))
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
}
-void Generator::appendFullName(Text& text,
- const Node *apparentNode,
- const QString& fullName,
- const Node *actualNode)
+bool Generator::matchAhead(const Atom *atom, Atom::Type expectedAtomType)
{
- if (actualNode == 0)
- actualNode = apparentNode;
- text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode))
- << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
- << Atom(Atom::String, fullName)
- << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ return atom->next() != 0 && atom->next()->type() == expectedAtomType;
}
-void Generator::appendFullNames(Text& text,
- const NodeList& nodes,
- const Node* relative,
- CodeMarker* marker)
+/*!
+ Used for writing to the current output stream. Returns a
+ reference to the current output stream, which is then used
+ with the \c {<<} operator for writing.
+ */
+QTextStream &Generator::out()
{
- NodeList::ConstIterator n = nodes.begin();
- int index = 0;
- while (n != nodes.end()) {
- appendFullName(text,*n,relative,marker);
- text << comma(index++,nodes.count());
- ++n;
- }
+ return *outStreamStack.top();
}
-void Generator::appendSortedNames(Text& text,
- const ClassNode *classe,
- const QList<RelatedClass> &classes,
- CodeMarker *marker)
+QString Generator::outputPrefix(const QString &nodeType)
{
- QList<RelatedClass>::ConstIterator r;
- QMap<QString,Text> classMap;
- int index = 0;
+ return outputPrefixes[nodeType];
+}
- r = classes.begin();
- while (r != classes.end()) {
- if ((*r).node->access() == Node::Public &&
- (*r).node->status() != Node::Internal
- && !(*r).node->doc().isEmpty()) {
- Text className;
- appendFullName(className, (*r).node, classe, marker);
- classMap[className.toString().toLower()] = className;
+bool Generator::parseArg(const QString& src,
+ const QString& tag,
+ int* pos,
+ int n,
+ QStringRef* contents,
+ QStringRef* par1,
+ bool debug)
+{
+#define SKIP_CHAR(c) \
+ if (debug) \
+ qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \
+ if (i >= n || src[i] != c) { \
+ if (debug) \
+ qDebug() << " char '" << c << "' not found"; \
+ return false; \
+} \
+ ++i;
+
+
+#define SKIP_SPACE \
+ while (i < n && src[i] == ' ') \
+ ++i;
+
+ int i = *pos;
+ int j = i;
+
+ // assume "<@" has been parsed outside
+ //SKIP_CHAR('<');
+ //SKIP_CHAR('@');
+
+ if (tag != QStringRef(&src, i, tag.length())) {
+ if (0 && debug)
+ qDebug() << "tag " << tag << " not found at " << i;
+ return false;
+ }
+
+ if (debug)
+ qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i;
+
+ // skip tag
+ i += tag.length();
+
+ // parse stuff like: linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
+ if (par1) {
+ SKIP_SPACE;
+ // read parameter name
+ j = i;
+ while (i < n && src[i].isLetter())
+ ++i;
+ if (src[i] == '=') {
+ if (debug)
+ qDebug() << "read parameter" << QString(src.data() + j, i - j);
+ SKIP_CHAR('=');
+ SKIP_CHAR('"');
+ // skip parameter name
+ j = i;
+ while (i < n && src[i] != '"')
+ ++i;
+ *par1 = QStringRef(&src, j, i - j);
+ SKIP_CHAR('"');
+ SKIP_SPACE;
+ } else {
+ if (debug)
+ qDebug() << "no optional parameter found";
}
- ++r;
+ }
+ SKIP_SPACE;
+ SKIP_CHAR('>');
+
+ // find contents up to closing "</@tag>
+ j = i;
+ for (; true; ++i) {
+ if (i + 4 + tag.length() > n)
+ return false;
+ if (src[i] != '<')
+ continue;
+ if (src[i + 1] != '/')
+ continue;
+ if (src[i + 2] != '@')
+ continue;
+ if (tag != QStringRef(&src, i + 3, tag.length()))
+ continue;
+ if (src[i + 3 + tag.length()] != '>')
+ continue;
+ break;
}
- QStringList classNames = classMap.keys();
- classNames.sort();
+ *contents = QStringRef(&src, j, i - j);
- foreach (const QString &className, classNames) {
- text << classMap[className];
- text << separator(index++, classNames.count());
- }
+ i += tag.length() + 4;
+
+ *pos = i;
+ if (debug)
+ qDebug() << " tag " << tag << " found: pos now: " << i;
+ return true;
+#undef SKIP_CHAR
}
-void Generator::appendSortedQmlNames(Text& text,
- const Node* base,
- const NodeList& subs,
- CodeMarker *marker)
+QString Generator::plainCode(const QString& markedCode)
{
- QMap<QString,Text> classMap;
- int index = 0;
-
- for (int i = 0; i < subs.size(); ++i) {
- Text t;
- if (!base->isQtQuickNode() || !subs[i]->isQtQuickNode() ||
- (base->qmlModuleIdentifier() == subs[i]->qmlModuleIdentifier())) {
- appendFullName(t, subs[i], base, marker);
- classMap[t.toString().toLower()] = t;
- }
- }
+ QString t = markedCode;
+ t.replace(tag, QString());
+ t.replace(quot, QLatin1String("\""));
+ t.replace(gt, QLatin1String(">"));
+ t.replace(lt, QLatin1String("<"));
+ t.replace(amp, QLatin1String("&"));
+ return t;
+}
- QStringList names = classMap.keys();
- names.sort();
+void Generator::setImageFileExtensions(const QStringList& extensions)
+{
+ imgFileExts[format()] = extensions;
+}
- foreach (const QString &name, names) {
- text << classMap[name];
- text << separator(index++, names.count());
- }
+void Generator::singularPlural(Text& text, const NodeList& nodes)
+{
+ if (nodes.count() == 1)
+ text << " is";
+ else
+ text << " are";
}
int Generator::skipAtoms(const Atom *atom, Atom::Type type) const
@@ -1340,156 +1684,134 @@ int Generator::skipAtoms(const Atom *atom, Atom::Type type) const
return skipAhead;
}
-QString Generator::fullName(const Node *node,
- const Node *relative,
- CodeMarker *marker) const
+void Generator::startText(const Node * /* relative */,
+ CodeMarker * /* marker */)
{
- if (node->type() == Node::Fake) {
- const FakeNode* fn = static_cast<const FakeNode *>(node);
-#if 0
- // Removed for QTBUG-22870
- if (!fn->qmlModuleIdentifier().isEmpty())
- return fn->qmlModuleIdentifier() + QLatin1Char(' ') + fn->title();
-#endif
- return fn->title();
- }
- else if (node->type() == Node::Class &&
- !(static_cast<const ClassNode *>(node))->serviceName().isEmpty())
- return (static_cast<const ClassNode *>(node))->serviceName();
- else
- return marker->plainFullName(node, relative);
}
-QString Generator::outputPrefix(const QString &nodeType)
+void Generator::supplementAlsoList(const Node *node, QList<Text> &alsoList)
{
- return outputPrefixes[nodeType];
-}
+ if (node->type() == Node::Function) {
+ const FunctionNode *func = static_cast<const FunctionNode *>(node);
+ if (func->overloadNumber() == 1) {
+ QString alternateName;
+ const FunctionNode *alternateFunc = 0;
-/*!
- Looks up the tag \a t in the map of metadata values for the
- current topic in \a inner. If a value for the tag is found,
- the value is returned.
+ if (func->name().startsWith("set") && func->name().size() >= 4) {
+ alternateName = func->name()[3].toLower();
+ alternateName += func->name().mid(4);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
- \note If \a t is found in the metadata map, it is erased.
- i.e. Once you call this function for a particular \a t,
- you consume \a t.
- */
-QString Generator::getMetadataElement(const InnerNode* inner, const QString& t)
-{
- QString s;
- QStringMultiMap& metaTagMap = const_cast<QStringMultiMap&>(inner->doc().metaTagMap());
- QStringMultiMap::iterator i = metaTagMap.find(t);
- if (i != metaTagMap.end()) {
- s = i.value();
- metaTagMap.erase(i);
+ if (!alternateFunc) {
+ alternateName = "is" + func->name().mid(3);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ if (!alternateFunc) {
+ alternateName = "has" + func->name().mid(3);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ }
+ }
+ }
+ else if (!func->name().isEmpty()) {
+ alternateName = "set";
+ alternateName += func->name()[0].toUpper();
+ alternateName += func->name().mid(1);
+ alternateFunc = func->parent()->findFunctionNode(alternateName);
+ }
+
+ if (alternateFunc && alternateFunc->access() != Node::Private) {
+ int i;
+ for (i = 0; i < alsoList.size(); ++i) {
+ if (alsoList.at(i).toString().contains(alternateName))
+ break;
+ }
+
+ if (i == alsoList.size()) {
+ alternateName += "()";
+
+ Text also;
+ also << Atom(Atom::Link, alternateName)
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK)
+ << alternateName
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK);
+ alsoList.prepend(also);
+ }
+ }
+ }
}
- return s;
}
-/*!
- Looks up the tag \a t in the map of metadata values for the
- current topic in \a inner. If values for the tag are found,
- they are returned in a string list.
+void Generator::terminate()
+{
+ QList<Generator *>::ConstIterator g = generators.begin();
+ while (g != generators.end()) {
+ if (outputFormats.contains((*g)->format()))
+ (*g)->terminateGenerator();
+ ++g;
+ }
- \note If \a t is found in the metadata map, all the pairs
- having the key \a t are erased. i.e. Once you call this
- function for a particular \a t, you consume \a t.
- */
-QStringList Generator::getMetadataElements(const InnerNode* inner, const QString& t)
+ fmtLeftMaps.clear();
+ fmtRightMaps.clear();
+ imgFileExts.clear();
+ imageFiles.clear();
+ imageDirs.clear();
+ outDir_ = "";
+ QmlClassNode::terminate();
+ ExampleNode::terminate();
+}
+
+void Generator::terminateGenerator()
{
- QStringList s;
- QStringMultiMap& metaTagMap = const_cast<QStringMultiMap&>(inner->doc().metaTagMap());
- s = metaTagMap.values(t);
- if (!s.isEmpty())
- metaTagMap.remove(t);
- return s;
}
/*!
- For generating the "New Classes... in 4.6" section on the
- What's New in 4.6" page.
+ Trims trailing whitespace off the \a string and returns
+ the trimmed string.
*/
-void Generator::findAllSince(const InnerNode *node)
+QString Generator::trimmedTrailing(const QString& string)
{
- NodeList::const_iterator child = node->childNodes().constBegin();
-
- // Traverse the tree, starting at the node supplied.
-
- while (child != node->childNodes().constEnd()) {
-
- QString sinceString = (*child)->since();
-
- if (((*child)->access() != Node::Private) && !sinceString.isEmpty()) {
-
- // Insert a new entry into each map for each new since string found.
- NewSinceMaps::iterator nsmap = newSinceMaps.find(sinceString);
- if (nsmap == newSinceMaps.end())
- nsmap = newSinceMaps.insert(sinceString,NodeMultiMap());
-
- NewClassMaps::iterator ncmap = newClassMaps.find(sinceString);
- if (ncmap == newClassMaps.end())
- ncmap = newClassMaps.insert(sinceString,NodeMap());
-
- NewClassMaps::iterator nqcmap = newQmlClassMaps.find(sinceString);
- if (nqcmap == newQmlClassMaps.end())
- nqcmap = newQmlClassMaps.insert(sinceString,NodeMap());
-
- if ((*child)->type() == Node::Function) {
- // Insert functions into the general since map.
- FunctionNode *func = static_cast<FunctionNode *>(*child);
- if ((func->status() > Node::Obsolete) &&
- (func->metaness() != FunctionNode::Ctor) &&
- (func->metaness() != FunctionNode::Dtor)) {
- nsmap.value().insert(func->name(),(*child));
- }
- }
- else if ((*child)->url().isEmpty()) {
- if ((*child)->type() == Node::Class && !(*child)->doc().isEmpty()) {
- // Insert classes into the since and class maps.
- QString className = (*child)->name();
- if ((*child)->parent() &&
- (*child)->parent()->type() == Node::Namespace &&
- !(*child)->parent()->name().isEmpty())
- className = (*child)->parent()->name()+"::"+className;
-
- nsmap.value().insert(className,(*child));
- ncmap.value().insert(className,(*child));
- }
- else if ((*child)->subType() == Node::QmlClass) {
- // Insert QML elements into the since and element maps.
- QString className = (*child)->name();
- if ((*child)->parent() &&
- (*child)->parent()->type() == Node::Namespace &&
- !(*child)->parent()->name().isEmpty())
- className = (*child)->parent()->name()+"::"+className;
-
- nsmap.value().insert(className,(*child));
- nqcmap.value().insert(className,(*child));
- }
- else if ((*child)->type() == Node::QmlProperty) {
- // Insert QML properties into the since map.
- QString propertyName = (*child)->name();
- nsmap.value().insert(propertyName,(*child));
- }
- }
- else {
- // Insert external documents into the general since map.
- QString name = (*child)->name();
- if ((*child)->parent() &&
- (*child)->parent()->type() == Node::Namespace &&
- !(*child)->parent()->name().isEmpty())
- name = (*child)->parent()->name()+"::"+name;
-
- nsmap.value().insert(name,(*child));
- }
+ QString trimmed = string;
+ while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace())
+ trimmed.truncate(trimmed.length() - 1);
+ return trimmed;
+}
- // Find child nodes with since commands.
- if ((*child)->isInnerNode()) {
- findAllSince(static_cast<InnerNode *>(*child));
- }
+QString Generator::typeString(const Node *node)
+{
+ switch (node->type()) {
+ case Node::Namespace:
+ return "namespace";
+ case Node::Class:
+ return "class";
+ case Node::Fake:
+ {
+ switch (node->subType()) {
+ case Node::QmlClass:
+ return "type";
+ case Node::QmlPropertyGroup:
+ return "property group";
+ case Node::QmlBasicType:
+ return "type";
+ default:
+ return "documentation";
}
- ++child;
}
+ case Node::Enum:
+ return "enum";
+ case Node::Typedef:
+ return "typedef";
+ case Node::Function:
+ return "function";
+ case Node::Property:
+ return "property";
+ default:
+ return "documentation";
+ }
+}
+
+void Generator::unknownAtom(const Atom *atom)
+{
+ Location::internalError(tr("unknown atom type '%1' in %2 generator")
+ .arg(atom->typeString()).arg(format()));
}
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h
index 4021a85f61..bc1b12b958 100644
--- a/src/tools/qdoc/generator.h
+++ b/src/tools/qdoc/generator.h
@@ -46,22 +46,23 @@
#ifndef GENERATOR_H
#define GENERATOR_H
-#include <qlist.h>
-#include <qmap.h>
-#include <qregexp.h>
-#include <qstring.h>
-#include <qstringlist.h>
+#include <QList>
+#include <QMap>
+#include <QRegExp>
+#include <QString>
+#include <QStringList>
+#include <QTextStream>
#include "node.h"
#include "text.h"
QT_BEGIN_NAMESPACE
+typedef QMap<QString, NodeMap> NewClassMaps;
+typedef QMap<QString, NodeMultiMap> NewSinceMaps;
typedef QMap<QString, const Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap;
-typedef QMap<QString, NodeMultiMap> NewSinceMaps;
typedef QMap<Node*, NodeMultiMap> ParentMaps;
-typedef QMap<QString, NodeMap> NewClassMaps;
class ClassNode;
class Config;
@@ -80,87 +81,124 @@ public:
Generator();
virtual ~Generator();
+ virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
+ virtual QString format() = 0;
+ virtual void generateTree(const Tree *tree);
virtual void initializeGenerator(const Config &config);
virtual void terminateGenerator();
- virtual QString format() = 0;
- virtual bool canHandleFormat(const QString &format) { return format == this->format(); }
- virtual void generateTree(const Tree *tree) = 0;
- static void initialize(const Config& config);
- static void terminate();
+ static const QString& baseDir() { return baseDir_; }
static Generator *generatorForFormat(const QString& format);
+ static void initialize(const Config& config);
static const QString& outputDir() { return outDir_; }
- static const QString& baseDir() { return baseDir_; }
+ static void terminate();
protected:
- virtual void startText(const Node *relative, CodeMarker *marker);
+ virtual void beginSubPage(const InnerNode* node, const QString& fileName);
+ virtual void endSubPage();
virtual void endText(const Node *relative, CodeMarker *marker);
+ virtual QString fileBase(const Node* node) const;
+ virtual QString fileExtension(const Node* node) const = 0;
+ virtual QString fullName(const Node *node,
+ const Node *relative,
+ CodeMarker *marker) const;
+ virtual void generateAlsoList(const Node *node, CodeMarker *marker);
virtual int generateAtom(const Atom *atom,
const Node *relative,
CodeMarker *marker);
+ virtual void generateBody(const Node *node, CodeMarker *marker);
virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker);
virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker);
-
- virtual bool generateText(const Text& text,
- const Node *relative,
- CodeMarker *marker);
+ virtual void generateInheritedBy(const ClassNode *classe,
+ CodeMarker *marker);
+ virtual void generateInherits(const ClassNode *classe,
+ CodeMarker *marker);
+ virtual void generateInnerNode(const InnerNode *node);
+ virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
+ virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
+ virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
virtual bool generateQmlText(const Text& text,
const Node *relative,
CodeMarker *marker,
const QString& qmlName);
- virtual void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
- virtual void generateBody(const Node *node, CodeMarker *marker);
- virtual void generateAlsoList(const Node *node, CodeMarker *marker);
- virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
- virtual void generateInherits(const ClassNode *classe,
- CodeMarker *marker);
- virtual void generateInheritedBy(const ClassNode *classe,
- CodeMarker *marker);
+ virtual bool generateText(const Text& text,
+ const Node *relative,
+ CodeMarker *marker);
+ virtual QString imageFileName(const Node *relative, const QString& fileBase);
+ virtual QString outFileName() { return QString(); }
+ virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
+ virtual void startText(const Node *relative, CodeMarker *marker);
+ virtual QString typeString(const Node *node);
- void generateThreadSafeness(const Node *node, CodeMarker *marker);
- void generateSince(const Node *node, CodeMarker *marker);
- void generateStatus(const Node *node, CodeMarker *marker);
+ static bool matchAhead(const Atom *atom, Atom::Type expectedAtomType);
+ static QString outputPrefix(const QString &nodeType);
+ static void singularPlural(Text& text, const NodeList& nodes);
+ static void supplementAlsoList(const Node *node, QList<Text> &alsoList);
+ static QString trimmedTrailing(const QString &string);
+ static QString sinceTitles[];
+
+ QString fileName(const Node* node) const;
+ void findAllSince(const InnerNode *node);
+ QMap<QString, QString> &formattingLeftMap();
+ QMap<QString, QString> &formattingRightMap();
const Atom* generateAtomList(const Atom *atom,
const Node *relative,
CodeMarker *marker,
bool generate,
int& numGeneratedAtoms);
+ void generateExampleFiles(const FakeNode *fake, CodeMarker *marker);
void generateFileList(const FakeNode* fake,
CodeMarker* marker,
Node::SubType subtype,
const QString& tag);
- void generateExampleFiles(const FakeNode *fake, CodeMarker *marker);
-
- virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
- virtual QString fullName(const Node *node,
- const Node *relative,
- CodeMarker *marker) const;
-
- virtual QString outFileName() { return QString(); }
-
+ void generateSince(const Node *node, CodeMarker *marker);
+ void generateStatus(const Node *node, CodeMarker *marker);
+ void generateThreadSafeness(const Node *node, CodeMarker *marker);
+ QString getMetadataElement(const InnerNode* inner, const QString& t);
+ QStringList getMetadataElements(const InnerNode* inner, const QString& t);
QString indent(int level, const QString& markedCode);
+ QTextStream& out();
+ bool parseArg(const QString& src,
+ const QString& tag,
+ int* pos,
+ int n,
+ QStringRef* contents,
+ QStringRef* par1 = 0,
+ bool debug = false);
QString plainCode(const QString& markedCode);
- virtual QString typeString(const Node *node);
- virtual QString imageFileName(const Node *relative, const QString& fileBase);
void setImageFileExtensions(const QStringList& extensions);
void unknownAtom(const Atom *atom);
- QMap<QString, QString> &formattingLeftMap();
- QMap<QString, QString> &formattingRightMap();
- QMap<QString, QStringList> editionModuleMap;
- QMap<QString, QStringList> editionGroupMap;
-
- static QString trimmedTrailing(const QString &string);
- static bool matchAhead(const Atom *atom, Atom::Type expectedAtomType);
- static void supplementAlsoList(const Node *node, QList<Text> &alsoList);
- static QString outputPrefix(const QString &nodeType);
- QString getMetadataElement(const InnerNode* inner, const QString& t);
- QStringList getMetadataElements(const InnerNode* inner, const QString& t);
- void findAllSince(const InnerNode *node);
+ QList<NameCollisionNode*> collisionNodes;
+ QMap<QString, QStringList> editionGroupMap;
+ QMap<QString, QStringList> editionModuleMap;
+ QString naturalLanguage;
+ QTextCodec* outputCodec;
+ QString outputEncoding;
+ QStack<QTextStream*> outStreamStack;
+ NewClassMaps newClassMaps;
+ NewClassMaps newQmlClassMaps;
+ NewSinceMaps newSinceMaps;
private:
- void generateReimplementedFrom(const FunctionNode *func,
- CodeMarker *marker);
+ static QString baseDir_;
+ static QStringList exampleDirs;
+ static QStringList exampleImgExts;
+ static QMap<QString, QMap<QString, QString> > fmtLeftMaps;
+ static QMap<QString, QMap<QString, QString> > fmtRightMaps;
+ static QList<Generator *> generators;
+ static QStringList imageDirs;
+ static QStringList imageFiles;
+ static QMap<QString, QStringList> imgFileExts;
+ static QString project;
+ static QString outDir_;
+ static QSet<QString> outputFormats;
+ static QHash<QString, QString> outputPrefixes;
+ static QStringList scriptDirs;
+ static QStringList scriptFiles;
+ static QStringList styleDirs;
+ static QStringList styleFiles;
+
void appendFullName(Text& text,
const Node *apparentNode,
const Node *relative,
@@ -178,42 +216,18 @@ private:
const ClassNode *classe,
const QList<RelatedClass> &classes,
CodeMarker *marker);
-
-protected:
void appendSortedQmlNames(Text& text,
const Node* base,
const NodeList& subs,
CodeMarker *marker);
+ void generateReimplementedFrom(const FunctionNode *func,
+ CodeMarker *marker);
- static QString sinceTitles[];
- NewSinceMaps newSinceMaps;
- NewClassMaps newClassMaps;
- NewClassMaps newQmlClassMaps;
-
-private:
QString amp;
- QString lt;
QString gt;
+ QString lt;
QString quot;
QRegExp tag;
-
- static QList<Generator *> generators;
- static QMap<QString, QMap<QString, QString> > fmtLeftMaps;
- static QMap<QString, QMap<QString, QString> > fmtRightMaps;
- static QMap<QString, QStringList> imgFileExts;
- static QSet<QString> outputFormats;
- static QStringList imageFiles;
- static QStringList imageDirs;
- static QStringList exampleDirs;
- static QStringList exampleImgExts;
- static QStringList scriptFiles;
- static QStringList scriptDirs;
- static QStringList styleFiles;
- static QStringList styleDirs;
- static QString outDir_;
- static QString baseDir_;
- static QString project;
- static QHash<QString, QString> outputPrefixes;
};
QT_END_NAMESPACE
diff --git a/src/tools/qdoc/helpprojectwriter.cpp b/src/tools/qdoc/helpprojectwriter.cpp
index 096877211d..5efd6ef928 100644
--- a/src/tools/qdoc/helpprojectwriter.cpp
+++ b/src/tools/qdoc/helpprojectwriter.cpp
@@ -506,10 +506,10 @@ void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer
project.files.insert(membersPath);
}
if (project.memberStatus[node].contains(Node::Compat)) {
- QString compatPath = href.left(href.size()-5) + "-qt3.html";
+ QString compatPath = href.left(href.size()-5) + "-compat.html";
writer.writeStartElement("section");
writer.writeAttribute("ref", compatPath);
- writer.writeAttribute("title", tr("Qt 3 support members"));
+ writer.writeAttribute("title", tr("Compatibility members"));
writer.writeEndElement(); // section
project.files.insert(compatPath);
}
@@ -553,10 +553,10 @@ void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer
project.files.insert(membersPath);
}
if (project.memberStatus[node].contains(Node::Compat)) {
- QString compatPath = href.left(href.size()-5) + "-qt3.html";
+ QString compatPath = href.left(href.size()-5) + "-compat.html";
writer.writeStartElement("section");
writer.writeAttribute("ref", compatPath);
- writer.writeAttribute("title", tr("Qt 3 support members"));
+ writer.writeAttribute("title", tr("Compatibility members"));
writer.writeEndElement(); // section
project.files.insert(compatPath);
}
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 9b886564c4..b8ad119466 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -273,13 +273,12 @@ void HtmlGenerator::generateTree(const Tree *tree)
findAllNamespaces(tree->root());
findAllSince(tree->root());
- PageGenerator::generateTree(tree);
+ Generator::generateTree(tree);
reportOrphans(tree->root());
generateDisambiguationPages();
QString fileBase = project.toLower().simplified().replace(" ", "-");
generateIndex(fileBase, projectUrl, projectDescription);
- generatePageIndex(outputDir() + QLatin1Char('/') + fileBase + ".pageindex");
helpProjectWriter->generate(myTree);
generateManifestFiles();
@@ -1223,7 +1222,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
CodeMarker::Compat);
if (!compatLink.isEmpty())
out() << "<li><a href=\"" << compatLink << "\">"
- << "Qt 3 support members</a></li>\n";
+ << "Compatibility members</a></li>\n";
out() << "</ul>\n";
@@ -1331,6 +1330,8 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
names << prop->setters().first()->name();
if (!prop->resetters().isEmpty())
names << prop->resetters().first()->name();
+ if (!prop->notifiers().isEmpty())
+ names << prop->notifiers().first()->name();
}
else if ((*m)->type() == Node::Enum) {
const EnumNode *enume = reinterpret_cast<const EnumNode*>(*m);
@@ -1375,7 +1376,7 @@ void HtmlGenerator::generateDisambiguationPages()
for (int i=0; i<collisionNodes.size(); ++i) {
NameCollisionNode* ncn = collisionNodes.at(i);
ncn->clearCurrentChild();
- beginSubPage(ncn, PageGenerator::fileName(ncn));
+ beginSubPage(ncn, Generator::fileName(ncn));
QString fullTitle = "Name Collision: " + ncn->fullTitle();
QString htmlTitle = fullTitle;
CodeMarker* marker = CodeMarker::markerForFileName(ncn->location().filePath());
@@ -1529,7 +1530,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
CodeMarker::Compat);
if (!compatLink.isEmpty())
out() << "<li><a href=\"" << compatLink << "\">"
- << "Qt 3 support members</a></li>\n";
+ << "Compatibility members</a></li>\n";
out() << "</ul>\n";
}
@@ -2138,8 +2139,8 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner,
QString fileName;
if (status == CodeMarker::Compat) {
- title = "Qt 3 Support Members for " + inner->name();
- fileName = fileBase(inner) + "-qt3." + fileExtension(inner);
+ title = "Compatibility Members for " + inner->name();
+ fileName = fileBase(inner) + "-compat." + fileExtension(inner);
}
else {
title = "Obsolete Members for " + inner->name();
@@ -2152,8 +2153,7 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner,
if (status == CodeMarker::Compat) {
out() << "<p><b>The following class members are part of the "
- "<a href=\"qt3support.html\">Qt 3 support layer</a>.</b> "
- "They are provided to help you port old code to Qt 4. We advise against "
+ "Qt compatibility layer.</b> We advise against "
"using them in new code.</p>\n";
}
else {
@@ -3270,12 +3270,12 @@ QString HtmlGenerator::fileBase(const Node *node) const
{
QString result;
- result = PageGenerator::fileBase(node);
+ result = Generator::fileBase(node);
if (!node->isInnerNode()) {
switch (node->status()) {
case Node::Compat:
- result += "-qt3";
+ result += "-compat";
break;
case Node::Obsolete:
result += "-obsolete";
@@ -3295,7 +3295,7 @@ QString HtmlGenerator::fileName(const Node *node)
if (static_cast<const FakeNode *>(node)->subType() == Node::Image)
return node->name();
}
- return PageGenerator::fileName(node);
+ return Generator::fileName(node);
}
QString HtmlGenerator::refForNode(const Node *node)
@@ -3719,7 +3719,7 @@ const QPair<QString,QString> HtmlGenerator::anchorForNode(const Node *node)
{
QPair<QString,QString> anchorPair;
- anchorPair.first = PageGenerator::fileName(node);
+ anchorPair.first = Generator::fileName(node);
if (node->type() == Node::Fake) {
const FakeNode *fakeNode = static_cast<const FakeNode*>(node);
anchorPair.second = fakeNode->title();
@@ -4228,25 +4228,6 @@ void HtmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* mar
}
/*!
- Output the "Inherit by" list for the QML element,
- if it is inherited by any other elements.
- */
-void HtmlGenerator::generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker)
-{
- if (qcn) {
- NodeList subs;
- QmlClassNode::subclasses(qcn->name(),subs);
- if (!subs.isEmpty()) {
- Text text;
- text << Atom::ParaLeft << "Inherited by ";
- appendSortedQmlNames(text,qcn,subs,marker);
- text << Atom::ParaRight;
- generateText(text, qcn, marker);
- }
- }
-}
-
-/*!
Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]"
line for the QML element, if there should be one.
@@ -4307,225 +4288,6 @@ void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn, CodeMarker* mark
}
}
-/*!
- Generate the <page> element for the given \a node using the \a writer.
- Return true if a <page> element was written; otherwise return false.
- */
-bool HtmlGenerator::generatePageElement(QXmlStreamWriter& writer,
- const Node* node,
- CodeMarker* marker) const
-{
- if (node->pageType() == Node::NoPageType)
- return false;
- if (node->name().isEmpty())
- return true;
- if (node->access() == Node::Private)
- return false;
-
- QString guid = QUuid::createUuid().toString();
- QString title;
- QString rawTitle;
- QString fullTitle;
- QStringList pageWords;
- QXmlStreamAttributes attributes;
-
- QString url = node->outputSubdirectory();
- if (!url.isEmpty())
- url.append(QLatin1Char('/'));
- url.append(PageGenerator::fileName(node));
-
- writer.writeStartElement("page");
-
- if (node->isInnerNode()) {
- const InnerNode* inner = static_cast<const InnerNode*>(node);
- if (!inner->pageKeywords().isEmpty())
- pageWords << inner->pageKeywords();
-
- switch (node->type()) {
- case Node::Fake:
- {
- const FakeNode* fake = static_cast<const FakeNode*>(node);
- title = fake->fullTitle();
- pageWords << title;
- break;
- }
- case Node::Class:
- {
- title = node->name() + " Class";
- pageWords << node->name() << "class" << "reference";
- break;
- }
- case Node::Namespace:
- {
- rawTitle = marker->plainName(inner);
- fullTitle = marker->plainFullName(inner);
- title = rawTitle + " Namespace";
- pageWords << rawTitle << "namespace" << "reference";
- break;
- }
- default:
- title = node->name();
- pageWords << title;
- break;
- }
- }
- else {
- switch (node->type()) {
- case Node::Enum:
- {
- title = node->name() + " Enum";
- pageWords << node->name() << "enum" << "type";
- url += QLatin1Char('#') + node->name() + "-enum";
- break;
- }
- case Node::Function:
- {
- title = node->name() + " Function";
- pageWords << node->name() << "function";
- url += QLatin1Char('#') + node->name();
- break;
- }
- case Node::Property:
- {
- title = node->name() + " Property";
- pageWords << node->name() << "property";
- url += QLatin1Char('#') + node->name() + "-prop";
- break;
- }
- case Node::Typedef:
- {
- title = node->name() + " Type";
- pageWords << node->name() << "typedef" << "type";
- url += QLatin1Char('#') + node->name();
- break;
- }
- default:
- title = node->name();
- pageWords << title;
- break;
- }
-
- Node* parent = node->parent();
- if (parent && ((parent->type() == Node::Class) ||
- (parent->type() == Node::Namespace))) {
- pageWords << parent->name();
- }
- }
-
- writer.writeAttribute("id",guid);
- writer.writeStartElement("pageWords");
- writer.writeCharacters(pageWords.join(" "));
-
- writer.writeEndElement();
- writer.writeStartElement("pageTitle");
- writer.writeCharacters(title);
- writer.writeEndElement();
- writer.writeStartElement("pageUrl");
- writer.writeCharacters(url);
- writer.writeEndElement();
- writer.writeStartElement("pageType");
- QString ptype = "Article";
- switch (node->pageType()) {
- case Node::ApiPage:
- ptype = "APIPage";
- break;
- case Node::ArticlePage:
- ptype = "Article";
- break;
- case Node::ExamplePage:
- ptype = "Example";
- break;
- case Node::HowToPage:
- ptype = "HowTo";
- break;
- case Node::OverviewPage:
- ptype = "Overview";
- break;
- case Node::TutorialPage:
- ptype = "Tutorial";
- break;
- case Node::FAQPage:
- ptype = "FAQ";
- break;
- default:
- break;
- }
- writer.writeCharacters(ptype);
- writer.writeEndElement();
- writer.writeEndElement();
-
- if (node->type() == Node::Fake && node->doc().hasTableOfContents()) {
- QList<Atom*> toc = node->doc().tableOfContents();
- if (!toc.isEmpty()) {
- for (int i = 0; i < toc.size(); ++i) {
- Text headingText = Text::sectionHeading(toc.at(i));
- QString s = headingText.toString();
- writer.writeStartElement("page");
- guid = QUuid::createUuid().toString();
- QString internalUrl = url + QLatin1Char('#') + Doc::canonicalTitle(s);
- writer.writeAttribute("id",guid);
- writer.writeStartElement("pageWords");
- writer.writeCharacters(pageWords.join(" "));
- writer.writeCharacters(" ");
- writer.writeCharacters(s);
- writer.writeEndElement();
- writer.writeStartElement("pageTitle");
- writer.writeCharacters(s);
- writer.writeEndElement();
- writer.writeStartElement("pageUrl");
- writer.writeCharacters(internalUrl);
- writer.writeEndElement();
- writer.writeStartElement("pageType");
- writer.writeCharacters("Article");
- writer.writeEndElement();
- writer.writeEndElement();
- }
- }
- }
- return true;
-}
-
-/*!
- Traverse the tree recursively and generate the <keyword>
- elements.
- */
-void HtmlGenerator::generatePageElements(QXmlStreamWriter& writer, const Node* node, CodeMarker* marker) const
-{
- if (generatePageElement(writer, node, marker)) {
-
- if (node->isInnerNode()) {
- const InnerNode *inner = static_cast<const InnerNode *>(node);
-
- // Recurse to write an element for this child node and all its children.
- foreach (const Node *child, inner->childNodes())
- generatePageElements(writer, child, marker);
- }
- }
-}
-
-/*!
- Outputs the file containing the index used for searching the html docs.
- */
-void HtmlGenerator::generatePageIndex(const QString& fileName) const
-{
- QFile file(fileName);
- if (!file.open(QFile::WriteOnly | QFile::Text))
- return ;
-
- CodeMarker *marker = CodeMarker::markerForFileName(fileName);
-
- QXmlStreamWriter writer(&file);
- writer.setAutoFormatting(true);
- writer.writeStartDocument();
- writer.writeStartElement("qtPageIndex");
-
- generatePageElements(writer, myTree->root(), marker);
-
- writer.writeEndElement(); // qtPageIndex
- writer.writeEndDocument();
- file.close();
-}
-
void HtmlGenerator::generateExtractionMark(const Node *node, ExtractionMarkType markType)
{
if (markType != EndMark) {
@@ -4719,7 +4481,7 @@ QString HtmlGenerator::fullDocumentLocation(const Node *node, bool subdir)
if (node->type() != Node::Class && node->type() != Node::Namespace) {
switch (node->status()) {
case Node::Compat:
- parentName.replace(".html", "-qt3.html");
+ parentName.replace(".html", "-compat.html");
break;
case Node::Obsolete:
parentName.replace(".html", "-obsolete.html");
@@ -5042,7 +4804,7 @@ QXmlStreamWriter& HtmlGenerator::xmlWriter()
*/
void HtmlGenerator::beginDitamapPage(const InnerNode* node, const QString& fileName)
{
- PageGenerator::beginSubPage(node,fileName);
+ Generator::beginSubPage(node,fileName);
QXmlStreamWriter* writer = new QXmlStreamWriter(out().device());
xmlWriterStack.push(writer);
writer->setAutoFormatting(true);
@@ -5061,7 +4823,7 @@ void HtmlGenerator::endDitamapPage()
{
xmlWriter().writeEndDocument();
delete xmlWriterStack.pop();
- PageGenerator::endSubPage();
+ Generator::endSubPage();
}
/*!
diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h
index 24c5fb7179..1ba88f83df 100644
--- a/src/tools/qdoc/htmlgenerator.h
+++ b/src/tools/qdoc/htmlgenerator.h
@@ -46,18 +46,18 @@
#ifndef HTMLGENERATOR_H
#define HTMLGENERATOR_H
-#include <qmap.h>
-#include <qregexp.h>
+#include <QMap>
+#include <QRegExp>
#include <QXmlStreamWriter>
#include "codemarker.h"
#include "config.h"
-#include "pagegenerator.h"
+#include "generator.h"
QT_BEGIN_NAMESPACE
class HelpProjectWriter;
-class HtmlGenerator : public PageGenerator
+class HtmlGenerator : public Generator
{
public:
enum SinceType {
@@ -180,7 +180,6 @@ private:
const InnerNode *relative,
CodeMarker *marker);
void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker);
- void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
void generateQmlInstantiates(const QmlClassNode* qcn, CodeMarker* marker);
void generateInstantiatedBy(const ClassNode* cn, CodeMarker* marker);
@@ -240,13 +239,6 @@ private:
const Node *relative,
CodeMarker *marker);
void endLink();
- bool generatePageElement(QXmlStreamWriter& writer,
- const Node* node,
- CodeMarker* marker) const;
- void generatePageElements(QXmlStreamWriter& writer,
- const Node* node,
- CodeMarker* marker) const;
- void generatePageIndex(const QString& fileName) const;
void generateExtractionMark(const Node *node, ExtractionMarkType markType);
void reportOrphans(const InnerNode* parent);
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index e4350f1d9e..fb4a3fe271 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -1171,8 +1171,6 @@ QString Node::moduleName() const
return "QtNetwork";
else if (moduleName == "opengl")
return "QtOpenGL";
- else if (moduleName == "qt3support")
- return "Qt3Support";
else if (moduleName == "svg")
return "QtSvg";
else if (moduleName == "sql")
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 8c6eb673cd..5b1eb21113 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -907,6 +907,7 @@ inline void PropertyNode::addFunction(FunctionNode* function, FunctionRole role)
inline void PropertyNode::addSignal(FunctionNode* function, FunctionRole role)
{
funcs[(int)role].append(function);
+ function->setAssociatedProperty(this);
}
inline NodeList PropertyNode::functions() const
diff --git a/src/tools/qdoc/pagegenerator.cpp b/src/tools/qdoc/pagegenerator.cpp
deleted file mode 100644
index 6a52b7755a..0000000000
--- a/src/tools/qdoc/pagegenerator.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*
- pagegenerator.cpp
-*/
-
-#include <qfile.h>
-#include <qfileinfo.h>
-#include <qdebug.h>
-#include "codemarker.h"
-#include "pagegenerator.h"
-#include "tree.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- Nothing to do in the constructor.
- */
-PageGenerator::PageGenerator()
- : outputCodec(0)
-{
- // nothing.
-}
-
-/*!
- The destructor
- */
-PageGenerator::~PageGenerator()
-{
- while (!outStreamStack.isEmpty())
- endSubPage();
-}
-
-bool PageGenerator::parseArg(const QString& src,
- const QString& tag,
- int* pos,
- int n,
- QStringRef* contents,
- QStringRef* par1,
- bool debug)
-{
-#define SKIP_CHAR(c) \
- if (debug) \
- qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \
- if (i >= n || src[i] != c) { \
- if (debug) \
- qDebug() << " char '" << c << "' not found"; \
- return false; \
-} \
- ++i;
-
-
-#define SKIP_SPACE \
- while (i < n && src[i] == ' ') \
- ++i;
-
- int i = *pos;
- int j = i;
-
- // assume "<@" has been parsed outside
- //SKIP_CHAR('<');
- //SKIP_CHAR('@');
-
- if (tag != QStringRef(&src, i, tag.length())) {
- if (0 && debug)
- qDebug() << "tag " << tag << " not found at " << i;
- return false;
- }
-
- if (debug)
- qDebug() << "haystack:" << src << "needle:" << tag << "i:" <<i;
-
- // skip tag
- i += tag.length();
-
- // parse stuff like: linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)");
- if (par1) {
- SKIP_SPACE;
- // read parameter name
- j = i;
- while (i < n && src[i].isLetter())
- ++i;
- if (src[i] == '=') {
- if (debug)
- qDebug() << "read parameter" << QString(src.data() + j, i - j);
- SKIP_CHAR('=');
- SKIP_CHAR('"');
- // skip parameter name
- j = i;
- while (i < n && src[i] != '"')
- ++i;
- *par1 = QStringRef(&src, j, i - j);
- SKIP_CHAR('"');
- SKIP_SPACE;
- } else {
- if (debug)
- qDebug() << "no optional parameter found";
- }
- }
- SKIP_SPACE;
- SKIP_CHAR('>');
-
- // find contents up to closing "</@tag>
- j = i;
- for (; true; ++i) {
- if (i + 4 + tag.length() > n)
- return false;
- if (src[i] != '<')
- continue;
- if (src[i + 1] != '/')
- continue;
- if (src[i + 2] != '@')
- continue;
- if (tag != QStringRef(&src, i + 3, tag.length()))
- continue;
- if (src[i + 3 + tag.length()] != '>')
- continue;
- break;
- }
-
- *contents = QStringRef(&src, j, i - j);
-
- i += tag.length() + 4;
-
- *pos = i;
- if (debug)
- qDebug() << " tag " << tag << " found: pos now: " << i;
- return true;
-#undef SKIP_CHAR
-}
-
-/*!
- This function is recursive.
- */
-void PageGenerator::generateTree(const Tree *tree)
-{
- generateInnerNode(tree->root());
-}
-
-QString PageGenerator::fileBase(const Node *node) const
-{
- if (node->relates())
- node = node->relates();
- else if (!node->isInnerNode())
- node = node->parent();
- if (node->subType() == Node::QmlPropertyGroup) {
- node = node->parent();
- }
-
- QString base = node->doc().baseName();
- if (!base.isEmpty())
- return base;
-
- const Node *p = node;
-
- forever {
- const Node *pp = p->parent();
- base.prepend(p->name());
- if (!p->qmlModuleIdentifier().isEmpty())
- base.prepend(p->qmlModuleIdentifier()+QChar('-'));
- /*
- To avoid file name conflicts in the html directory,
- we prepend a prefix (by default, "qml-") to the file name of QML
- element doc files.
- */
- if ((p->subType() == Node::QmlClass) ||
- (p->subType() == Node::QmlBasicType)) {
- base.prepend(outputPrefix(QLatin1String("QML")));
- }
- if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake)
- break;
- base.prepend(QLatin1Char('-'));
- p = pp;
- }
- if (node->type() == Node::Fake) {
- if (node->subType() == Node::Collision) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
- if (ncn->currentChild())
- return fileBase(ncn->currentChild());
- base.prepend("collision-");
- }
-#ifdef QDOC2_COMPAT
- if (base.endsWith(".html"))
- base.truncate(base.length() - 5);
-#endif
- }
-
- // the code below is effectively equivalent to:
- // base.replace(QRegExp("[^A-Za-z0-9]+"), " ");
- // base = base.trimmed();
- // base.replace(QLatin1Char(' '), QLatin1Char('-'));
- // base = base.toLower();
- // as this function accounted for ~8% of total running time
- // we optimize a bit...
-
- QString res;
- // +5 prevents realloc in fileName() below
- res.reserve(base.size() + 5);
- bool begun = false;
- for (int i = 0; i != base.size(); ++i) {
- QChar c = base.at(i);
- uint u = c.unicode();
- if (u >= 'A' && u <= 'Z')
- u -= 'A' - 'a';
- if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) {
- res += QLatin1Char(u);
- begun = true;
- }
- else if (begun) {
- res += QLatin1Char('-');
- begun = false;
- }
- }
- while (res.endsWith(QLatin1Char('-')))
- res.chop(1);
- return res;
-}
-
-/*!
- If the \a node has a URL, return the URL as the file name.
- Otherwise, construct the file name from the fileBase() and
- the fileExtension(), and return the constructed name.
- */
-QString PageGenerator::fileName(const Node* node) const
-{
- if (!node->url().isEmpty())
- return node->url();
-
- QString name = fileBase(node);
- name += QLatin1Char('.');
- name += fileExtension(node);
- return name;
-}
-
-/*!
- Return the current output file name.
- */
-QString PageGenerator::outFileName()
-{
- return QFileInfo(static_cast<QFile*>(out().device())->fileName()).fileName();
-}
-
-/*!
- Creates the file named \a fileName in the output directory.
- Attaches a QTextStream to the created file, which is written
- to all over the place using out().
- */
-void PageGenerator::beginSubPage(const InnerNode* node, const QString& fileName)
-{
- QString path = outputDir() + QLatin1Char('/');
- if (!node->outputSubdirectory().isEmpty())
- path += node->outputSubdirectory() + QLatin1Char('/');
- path += fileName;
- QFile* outFile = new QFile(path);
- if (!outFile->open(QFile::WriteOnly))
- node->location().fatal(tr("Cannot open output file '%1'").arg(outFile->fileName()));
- QTextStream* out = new QTextStream(outFile);
-
- if (outputCodec)
- out->setCodec(outputCodec);
- outStreamStack.push(out);
- const_cast<InnerNode*>(node)->setOutputFileName(fileName);
-}
-
-/*!
- Flush the text stream associated with the subpage, and
- then pop it off the text stream stack and delete it.
- This terminates output of the subpage.
- */
-void PageGenerator::endSubPage()
-{
- outStreamStack.top()->flush();
- delete outStreamStack.top()->device();
- delete outStreamStack.pop();
-}
-
-/*!
- Used for writing to the current output stream. Returns a
- reference to the crrent output stream, which is then used
- with the \c {<<} operator for writing.
- */
-QTextStream &PageGenerator::out()
-{
- return *outStreamStack.top();
-}
-
-/*!
- Recursive writing of HTML files from the root \a node.
-
- \note NameCollisionNodes are skipped here and processed
- later. See HtmlGenerator::generateDisambiguationPages()
- for more on this.
- */
-void
-PageGenerator::generateInnerNode(const InnerNode* node)
-{
- if (!node->url().isNull())
- return;
-
- if (node->type() == Node::Fake) {
- const FakeNode *fakeNode = static_cast<const FakeNode *>(node);
- if (fakeNode->subType() == Node::ExternalPage)
- return;
- if (fakeNode->subType() == Node::Image)
- return;
- if (fakeNode->subType() == Node::QmlPropertyGroup)
- return;
- if (fakeNode->subType() == Node::Page) {
- if (node->count() > 0)
- qDebug("PAGE %s HAS CHILDREN", qPrintable(fakeNode->title()));
- }
- }
-
- /*
- Obtain a code marker for the source file.
- */
- CodeMarker *marker = CodeMarker::markerForFileName(node->location().filePath());
-
- if (node->parent() != 0) {
- /*
- Skip name collision nodes here and process them
- later in generateDisambiguationPages(). Each one
- is appended to a list for later.
- */
- if ((node->type() == Node::Fake) && (node->subType() == Node::Collision)) {
- const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
- collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
- }
- else {
- beginSubPage(node, fileName(node));
- if (node->type() == Node::Namespace || node->type() == Node::Class) {
- generateClassLikeNode(node, marker);
- }
- else if (node->type() == Node::Fake) {
- generateFakeNode(static_cast<const FakeNode *>(node), marker);
- }
- endSubPage();
- }
- }
-
- NodeList::ConstIterator c = node->childNodes().begin();
- while (c != node->childNodes().end()) {
- if ((*c)->isInnerNode() && (*c)->access() != Node::Private) {
- generateInnerNode((const InnerNode *) *c);
- }
- ++c;
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/tools/qdoc/pagegenerator.h b/src/tools/qdoc/pagegenerator.h
deleted file mode 100644
index da0d32d2ff..0000000000
--- a/src/tools/qdoc/pagegenerator.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*
- pagegenerator.h
-*/
-
-#ifndef PAGEGENERATOR_H
-#define PAGEGENERATOR_H
-
-#include <QStack>
-#include <qtextstream.h>
-#include "generator.h"
-#include "location.h"
-
-QT_BEGIN_NAMESPACE
-
-class QTextCodec;
-class ClassNode;
-class InnerNode;
-class NamespaceNode;
-class NameCollisionNode;
-
-class PageGenerator : public Generator
-{
-public:
- PageGenerator();
- ~PageGenerator();
-
- virtual void generateTree(const Tree *tree);
- virtual void generateDisambiguationPages() { }
-
-protected:
- virtual QString fileBase(const Node* node) const;
- virtual QString fileExtension(const Node* node) const = 0;
- QString fileName(const Node* node) const;
- QString outFileName();
- virtual void beginSubPage(const InnerNode* node, const QString& fileName);
- virtual void endSubPage();
- virtual void generateInnerNode(const InnerNode *node);
- QTextStream& out();
-
- QString naturalLanguage;
- QString outputEncoding;
- QTextCodec* outputCodec;
- bool parseArg(const QString& src,
- const QString& tag,
- int* pos,
- int n,
- QStringRef* contents,
- QStringRef* par1 = 0,
- bool debug = false);
-
-protected:
- QStack<QTextStream*> outStreamStack;
- QList<NameCollisionNode*> collisionNodes;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/tools/qdoc/qdoc.pro b/src/tools/qdoc/qdoc.pro
index 03de9f91df..09f9b7a0c1 100644
--- a/src/tools/qdoc/qdoc.pro
+++ b/src/tools/qdoc/qdoc.pro
@@ -39,7 +39,6 @@ HEADERS += atom.h \
location.h \
node.h \
openedlist.h \
- pagegenerator.h \
plaincodemarker.h \
puredocparser.h \
quoter.h \
@@ -65,7 +64,6 @@ SOURCES += atom.cpp \
main.cpp \
node.cpp \
openedlist.cpp \
- pagegenerator.cpp \
plaincodemarker.cpp \
puredocparser.cpp \
quoter.cpp \
diff --git a/src/tools/qdoc/qmlvisitor.cpp b/src/tools/qdoc/qmlvisitor.cpp
index 9c934ebcd1..956f874cbf 100644
--- a/src/tools/qdoc/qmlvisitor.cpp
+++ b/src/tools/qdoc/qmlvisitor.cpp
@@ -266,6 +266,7 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
if (!topic.isEmpty()) {
args = doc.metaCommandArgs(topic);
if (topic == COMMAND_QMLCLASS) {
+ // do nothing.
}
else if (topic == COMMAND_QMLPROPERTY) {
if (node->type() == Node::QmlProperty) {
@@ -320,7 +321,6 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
if (node->name() == args[0])
doc.location().warning(tr("%1 tries to inherit itself").arg(args[0]));
else {
- qDebug() << "QML Component:" << node->name() << "inherits:" << args[0];
CodeParser::setLink(node, Node::InheritsLink, args[0]);
if (node->subType() == Node::QmlClass) {
QmlClassNode::addInheritedBy(args[0],node);
@@ -339,8 +339,12 @@ void QmlDocVisitor::applyMetacommands(QQmlJS::AST::SourceLocation,
qpn->setReadOnly(1);
}
}
- else if (command == COMMAND_INGROUP) {
- tree->addToGroup(node, args[0]);
+ else if ((command == COMMAND_INGROUP) && !args.isEmpty()) {
+ QStringList::ConstIterator arg = args.begin();
+ while (arg != args.end()) {
+ tree->addToGroup(node, *arg);
+ ++arg;
+ }
}
else if (command == COMMAND_INTERNAL) {
node->setAccess(Node::Private);
diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp
index 4b2a8ba55c..450f2d777c 100644
--- a/src/tools/qdoc/tree.cpp
+++ b/src/tools/qdoc/tree.cpp
@@ -1739,7 +1739,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer,
const FunctionNode* functionNode = static_cast<const FunctionNode*>(fnNode);
writer.writeStartElement("setter");
writer.writeAttribute("name", functionNode->name());
- writer.writeEndElement(); // getter
+ writer.writeEndElement(); // setter
}
}
foreach (const Node* fnNode, propertyNode->resetters()) {
@@ -1747,7 +1747,15 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer,
const FunctionNode* functionNode = static_cast<const FunctionNode*>(fnNode);
writer.writeStartElement("resetter");
writer.writeAttribute("name", functionNode->name());
- writer.writeEndElement(); // getter
+ writer.writeEndElement(); // resetter
+ }
+ }
+ foreach (const Node* fnNode, propertyNode->notifiers()) {
+ if (fnNode) {
+ const FunctionNode* functionNode = static_cast<const FunctionNode*>(fnNode);
+ writer.writeStartElement("notifier");
+ writer.writeAttribute("name", functionNode->name());
+ writer.writeEndElement(); // notifier
}
}
}