diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/moc/generator.cpp | 30 | ||||
-rw-r--r-- | src/tools/moc/outputrevision.h | 2 | ||||
-rw-r--r-- | src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp | 2 | ||||
-rw-r--r-- | src/tools/qdoc/config.cpp | 1 | ||||
-rw-r--r-- | src/tools/qdoc/config.h | 2 | ||||
-rw-r--r-- | src/tools/qdoc/ditaxmlgenerator.cpp | 505 | ||||
-rw-r--r-- | src/tools/qdoc/ditaxmlgenerator.h | 49 | ||||
-rw-r--r-- | src/tools/qdoc/generator.cpp | 180 | ||||
-rw-r--r-- | src/tools/qdoc/generator.h | 13 | ||||
-rw-r--r-- | src/tools/qdoc/helpprojectwriter.cpp | 30 | ||||
-rw-r--r-- | src/tools/qdoc/htmlgenerator.cpp | 182 | ||||
-rw-r--r-- | src/tools/qdoc/htmlgenerator.h | 3 | ||||
-rw-r--r-- | src/tools/qdoc/main.cpp | 62 | ||||
-rw-r--r-- | src/tools/qdoc/node.cpp | 127 | ||||
-rw-r--r-- | src/tools/qdoc/node.h | 25 | ||||
-rw-r--r-- | src/tools/qdoc/puredocparser.cpp | 2 | ||||
-rw-r--r-- | src/tools/qdoc/qdoc.pro | 10 | ||||
-rw-r--r-- | src/tools/qdoc/tree.cpp | 31 |
18 files changed, 751 insertions, 505 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 74cdc5874c..5680dcba70 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -415,22 +415,6 @@ void Generator::generateCode() fprintf(out, " 0\n};\n\n"); } - bool hasExtraData = (cdef->hasQObject && !isQt) || !extraList.isEmpty(); - if (hasExtraData) { - fprintf(out, "const QMetaObjectExtraData %s::staticMetaObjectExtraData = {\n ", - cdef->qualified.constData()); - if (extraList.isEmpty()) - fprintf(out, "0, "); - else - fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData()); - - if (cdef->hasQObject && !isQt) - fprintf(out, " qt_static_metacall"); - else - fprintf(out, " 0"); - fprintf(out, " \n};\n\n"); - } - // // Finally create and initialize the static meta object // @@ -448,16 +432,20 @@ void Generator::generateCode() fprintf(out, "qt_meta_stringdata_%s.data,\n" " qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); - if (!hasExtraData) - fprintf(out, "0 }\n"); + if (cdef->hasQObject && !isQt) + fprintf(out, " qt_static_metacall, "); else - fprintf(out, "&staticMetaObjectExtraData }\n"); - fprintf(out, "};\n"); + fprintf(out, " 0, "); + + if (extraList.isEmpty()) + fprintf(out, "0, "); + else + fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData()); + fprintf(out, "0}\n};\n\n"); if(isQt) return; - if (!cdef->hasQObject) return; diff --git a/src/tools/moc/outputrevision.h b/src/tools/moc/outputrevision.h index cff0f98fca..590728db6c 100644 --- a/src/tools/moc/outputrevision.h +++ b/src/tools/moc/outputrevision.h @@ -43,6 +43,6 @@ #define OUTPUTREVISION_H // if the output revision changes, you MUST change it in qobjectdefs.h too -enum { mocOutputRevision = 65 }; // moc format output revision +enum { mocOutputRevision = 66 }; // moc format output revision #endif // OUTPUTREVISION_H diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp index 8c75c8a27b..f9d6864567 100644 --- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -353,7 +353,7 @@ static QByteArray qtTypeName(const QString &signature, const QDBusIntrospection: QString oldAnnotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName"); if (paramId >= 0) oldAnnotationName += QString::fromLatin1(".%1%2").arg(QLatin1String(direction)).arg(paramId); - qttype = annotations.value(annotationName); + qttype = annotations.value(oldAnnotationName); if (qttype.isEmpty()) { fprintf(stderr, "Got unknown type `%s'\n", qPrintable(signature)); diff --git a/src/tools/qdoc/config.cpp b/src/tools/qdoc/config.cpp index 8b356d1536..e715ea1112 100644 --- a/src/tools/qdoc/config.cpp +++ b/src/tools/qdoc/config.cpp @@ -150,6 +150,7 @@ QStringList MetaStack::getExpanded(const Location& location) QT_STATIC_CONST_IMPL QString Config::dot = QLatin1String("."); bool Config::generateExamples = true; QString Config::overrideOutputDir; +QString Config::installDir; QSet<QString> Config::overrideOutputFormats; QMap<QString, QString> Config::extractedDirs; int Config::numInstances; diff --git a/src/tools/qdoc/config.h b/src/tools/qdoc/config.h index f36389eb32..6ed37fce03 100644 --- a/src/tools/qdoc/config.h +++ b/src/tools/qdoc/config.h @@ -111,6 +111,7 @@ public: QT_STATIC_CONST QString dot; static bool generateExamples; + static QString installDir; static QString overrideOutputDir; static QSet<QString> overrideOutputFormats; @@ -135,6 +136,7 @@ private: #define CONFIG_BASEDIR "basedir" #define CONFIG_CODEINDENT "codeindent" #define CONFIG_DEFINES "defines" +#define CONFIG_DEPENDS "depends" #define CONFIG_DESCRIPTION "description" #define CONFIG_EDITION "edition" #define CONFIG_ENDHEADER "endheader" diff --git a/src/tools/qdoc/ditaxmlgenerator.cpp b/src/tools/qdoc/ditaxmlgenerator.cpp index 1f986e35ff..0c88cbc529 100644 --- a/src/tools/qdoc/ditaxmlgenerator.cpp +++ b/src/tools/qdoc/ditaxmlgenerator.cpp @@ -70,9 +70,15 @@ QString DitaXmlGenerator::ditaTags[] = { "", "alt", + "apiData", + "apiDef", + "apiDefItem", "apiDesc", + "apiDetail", + "apiItemName", "APIMap", "apiName", + "apiRef", "apiRelation", "audience", "author", @@ -215,6 +221,34 @@ QString DitaXmlGenerator::ditaTags[] = "prodname", "prolog", "publisher", + "qmlAttached", + "qmlDetail", + "qmlImportModule", + "qmlInheritedBy", + "qmlInherits", + "qmlInstantiates", + "qmlMethod", + "qmlMethodDef", + "qmlMethodDetail", + "qmlName", + "qmlProperty", + "qmlPropertyDef", + "qmlPropertyDetail", + "qmlPropertyGroup", + "qmlPropertyGroupDef", + "qmlPropertyGroupDetail", + "qmlQualifier", + "qmlSignal", + "qmlSignalDef", + "qmlSignalDetail", + "qmlSignalHandler", + "qmlSignalHandlerDef", + "qmlSignalHandlerDetail", + "qmlSignature", + "qmlSince", + "qmlType", + "qmlTypeDef", + "qmlTypeDetail", "related-links", "resourceid", "revised", @@ -335,18 +369,18 @@ 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. + Write the start \a tag. if \a title is not empty, generate + a GUID from it and write the GUID as the value of the \e{id} + attribute. Then if \a outputclass is not empty, write it as the value of the \a outputclass attribute. Fiunally, set the section nesting level to 1 and return 1. */ -int DitaXmlGenerator::enterApiDesc(const QString& outputclass, const QString& title) +int DitaXmlGenerator::enterDesc(DitaTag tag, const QString& outputclass, const QString& title) { - writeStartTag(DT_apiDesc); + writeStartTag(tag); if (!title.isEmpty()) { writeGuidAttribute(title); //Are there cases where the spectitle is required? @@ -646,6 +680,10 @@ void DitaXmlGenerator::generateTree(Tree *tree) Generator::generateTree(tree); generateCollisionPages(); + + QString fileBase = project.toLower().simplified().replace(" ", "-"); + generateIndex(fileBase, projectUrl, projectDescription); + writeDitaMap(tree); } @@ -1797,7 +1835,7 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) writeLocation(nsn); writeEndTag(); // <cxxClassDefinition> - enterApiDesc(QString(),title); + enterDesc(DT_apiDesc,QString(),title); #if 0 // To be removed, if really not needed. Text brief = nsn->doc().briefText(); // zzz @@ -1933,7 +1971,7 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) writeLocation(cn); writeEndTag(); // <cxxClassDefinition> - enterApiDesc(QString(),title); + enterDesc(DT_apiDesc,QString(),title); #if 0 // To be removed, if really not needed. Text brief = cn->doc().briefText(); // zzz @@ -2059,7 +2097,7 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) writeProlog(inner); writeStartTag(DT_cxxClassDetail); - enterApiDesc(QString(),title); + enterDesc(DT_apiDesc,QString(),title); #if 0 // To be removed, if really not needed. Text brief = fn->doc().briefText(); // zzz @@ -2173,15 +2211,20 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) rawTitle = marker->plainName(inner); fullTitle = marker->plainFullName(inner); title = rawTitle + " Element"; - //QString fullTitle = fake->fullTitle(); - //QString htmlTitle = fullTitle; + Node::clearPropertyGroupCount(); generateHeader(inner, fullTitle); generateBrief(inner, marker); // <shortdesc> writeProlog(inner); - writeStartTag(DT_cxxClassDetail); - enterApiDesc(QString(),title); + writeStartTag(DT_qmlTypeDetail); + generateQmlModuleDef(qcn); + generateQmlInherits(qcn,marker); + generateQmlInstantiates(qcn,marker); + generateQmlInheritedBy(qcn, marker); + generateQmlSince(qcn); + + enterDesc(DT_apiDesc,QString(),title); #if 0 // To be removed, if really not needed. Text brief = qcn->doc().briefText(); // zzz @@ -2191,10 +2234,6 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) writeEndTag(); // </p> } #endif - generateQmlInstantiates(qcn, marker); - generateQmlInherits(qcn, marker); - generateQmlInheritedBy(qcn, marker); - generateSince(qcn, marker); enterSection("",""); generateBody(qcn, marker); if (cn) { @@ -2203,42 +2242,13 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) } leaveSection(); leaveSection(); // </apiDesc> + writeEndTag(); // </qmlTypeDetail> - QList<Section> summarySections; - summarySections = marker->qmlSections(qcn,CodeMarker::Summary); - if (!summarySections.isEmpty()) { - enterSection("redundant",QString()); - s = summarySections.begin(); - while (s != summarySections.end()) { - QString attr; - if (!s->members.isEmpty()) { - writeStartTag(DT_p); - attr = cleanRef((*s).name).toLower() + " h2"; - xmlWriter().writeAttribute("outputclass",attr); - writeCharacters(protectEnc((*s).name)); - writeEndTag(); // </p> - generateQmlSummary(*s,qcn,marker); - //generateSection(s->members, inner, marker, CodeMarker::Summary); - //generateSectionInheritedList(*s, inner, marker); - } - ++s; - } - leaveSection(); - } - - QList<Section> detailSections; - detailSections = marker->qmlSections(qcn,CodeMarker::Detailed); - if (!detailSections.isEmpty()) { - enterSection("details",QString()); - s = detailSections.begin(); - while (s != detailSections.end()) { + QList<Section> members = marker->qmlSections(qcn,CodeMarker::Detailed); + if (!members.isEmpty()) { + s = members.begin(); + while (s != members.end()) { if (!s->members.isEmpty()) { - QString attr; - writeStartTag(DT_p); - attr = cleanRef((*s).name).toLower() + " h2"; - xmlWriter().writeAttribute("outputclass",attr); - writeCharacters(protectEnc((*s).name)); - writeEndTag(); // </p> NodeList::ConstIterator m = (*s).members.begin(); while (m != (*s).members.end()) { generateDetailedQmlMember(*m, qcn, marker); @@ -2247,14 +2257,11 @@ DitaXmlGenerator::generateClassLikeNode(InnerNode* inner, CodeMarker* marker) } ++s; } - leaveSection(); } - writeEndTag(); // </cxxClassDetail> - writeEndTag(); // </cxxClass> + writeEndTag(); // </apiRef> } } - /*! Write a list item for a \a link with the given \a text. */ @@ -2429,7 +2436,7 @@ void DitaXmlGenerator::writeRelatedLinks(const FakeNode* node, CodeMarker* marke /*! Returns "dita" for this subclass of class Generator. */ -QString DitaXmlGenerator::fileExtension(const Node * /* node */) const +QString DitaXmlGenerator::fileExtension() const { return "dita"; } @@ -2487,14 +2494,14 @@ void DitaXmlGenerator::generateHeader(const Node* node, outputclass = "headerfile"; } else if (node->subType() == Node::QmlClass) { - mainTag = DT_cxxClass; + mainTag = DT_qmlType; nameTag = DT_apiName; - dtd = "dtd/cxxClass.dtd"; - version = "0.7.0"; + dtd = "dtd/qmlType.dtd"; + version = "0.1.0"; doctype = "<!DOCTYPE " + ditaTags[mainTag] + - " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" + - version + "//EN\" \"" + dtd + "\">"; - outputclass = "QML-class"; + " PUBLIC \"-//NOKIA//DTD DITA QML Type" + + "//EN\" \"" + dtd + "\">"; + outputclass = "QML-type"; } else { mainTag = DT_topic; @@ -4426,6 +4433,50 @@ void DitaXmlGenerator::generateQmlSummary(const Section& section, } /*! + Writes the QML property \a qpn to the current DITA XML file. + Assumes that the correct start tag has already been written, + but nothing has been written inside that tag. This function + begins by writing the GUID id attribute for the property. + */ +void DitaXmlGenerator::startQmlProperty(QmlPropertyNode* qpn, + const InnerNode* relative, + CodeMarker* marker) +{ + writeStartTag(DT_qmlProperty); + writeGuidAttribute((Node*)qpn); + writeStartTag(DT_apiName); + writeCharacters(qpn->name()); + writeEndTag(); // </apiName> + generateBrief(qpn, marker); // <shortdesc> + writeStartTag(DT_qmlPropertyDetail); + writeStartTag(DT_qmlPropertyDef); + if (!qpn->isReadOnlySet()) + qpn->setReadOnly(!qpn->isWritable(tree_)); + if (qpn->isReadOnly()) { + writeStartTag(DT_qmlQualifier); + xmlWriter().writeAttribute("name","read-only"); + xmlWriter().writeAttribute("value","read-only"); + writeEndTag(); // </qmlQualifier> + } + if (qpn->isDefault()) { + writeStartTag(DT_qmlQualifier); + xmlWriter().writeAttribute("name","default"); + xmlWriter().writeAttribute("value","default"); + writeEndTag(); // </qmlQualifier> + } + if (qpn->isAttached()) { + writeStartTag(DT_qmlAttached); + xmlWriter().writeAttribute("name","attached"); + xmlWriter().writeAttribute("value","yes"); + writeEndTag(); // </qmlAttached> + } + writeStartTag(DT_apiData); + generateQmlItem(qpn, relative, marker, false); + writeEndTag(); // </apiData> + writeEndTag(); // </qmlPropertyDef> +} + +/*! Outputs the DITA detailed documentation for a section on a QML element reference page. */ @@ -4435,71 +4486,57 @@ void DitaXmlGenerator::generateDetailedQmlMember(Node* node, { QString marked; QmlPropertyNode* qpn = 0; + if (node->subType() == Node::QmlPropertyGroup) { const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node); NodeList::ConstIterator p = qpgn->childNodes().begin(); - writeStartTag(DT_ul); - while (p != qpgn->childNodes().end()) { - if ((*p)->type() == Node::QmlProperty) { - qpn = static_cast<QmlPropertyNode*>(*p); - writeStartTag(DT_li); - writeGuidAttribute((Node*)qpn); - QString attr; - if (!qpn->isReadOnlySet()) - qpn->setReadOnly(!qpn->isWritable(tree_)); - if (qpn->isReadOnly()) - attr = "read-only"; - if (qpn->isDefault()) { - if (!attr.isEmpty()) - attr += QLatin1Char(' '); - attr += "default"; + if (qpgn->childNodes().size() == 1) { + qpn = static_cast<QmlPropertyNode*>(*p); + startQmlProperty(qpn,relative,marker); + writeQmlDesc(node, marker); + writeEndTag(); // </qmlPropertyDetail> + writeEndTag(); // </qmlProperty> + } + else { + writeStartTag(DT_qmlPropertyGroup); + QString id = "id-qml-propertygroup-" + node->name(); + id.replace('.','-'); + xmlWriter().writeAttribute("id",id); + writeStartTag(DT_apiName); + //writeCharacters("..."); + writeEndTag(); // </apiName> + writeStartTag(DT_qmlPropertyGroupDetail); + writeQmlDesc(node, marker); + writeEndTag(); // </qmlPropertyGroupDetail> + while (p != qpgn->childNodes().end()) { + if ((*p)->type() == Node::QmlProperty) { + qpn = static_cast<QmlPropertyNode*>(*p); + startQmlProperty(qpn,relative,marker); + writeEndTag(); // </qmlPropertyDetail> + writeEndTag(); // </qmlProperty> } - if (!attr.isEmpty()) - xmlWriter().writeAttribute("outputclass",attr); - generateQmlItem(qpn, relative, marker, false); - writeEndTag(); // </li> + ++p; } - ++p; + writeEndTag(); // </qmlPropertyGroup } - writeEndTag(); // </ul> } else if (node->type() == Node::QmlProperty) { qpn = static_cast<QmlPropertyNode*>(node); - /* - If the QML property node has a single subproperty, - override, replace qpn with that override node and - proceed as normal. - */ - if (qpn->qmlPropNodes().size() == 1) { + if (qpn->qmlPropNodes().isEmpty()) { + startQmlProperty(qpn,relative,marker); + writeQmlDesc(node, marker); + writeEndTag(); // </qmlPropertyDetail> + writeEndTag(); // </qmlProperty> + } + else if (qpn->qmlPropNodes().size() == 1) { Node* n = qpn->qmlPropNodes().at(0); - if (n->type() == Node::QmlProperty) + if (n->type() == Node::QmlProperty) { qpn = static_cast<QmlPropertyNode*>(n); - } - /* - Now qpn either has no overrides, or it has more - than 1. If it has none, proceed to output as nortmal. - */ - if (qpn->qmlPropNodes().isEmpty()) { - writeStartTag(DT_ul); - writeStartTag(DT_li); - writeGuidAttribute((Node*)qpn); - QString attr; - if (!qpn->isReadOnlySet()) { - if (qpn->declarativeCppNode()) - qpn->setReadOnly(!qpn->isWritable(tree_)); - } - if (qpn->isReadOnly()) - attr = "read-only"; - if (qpn->isDefault()) { - if (!attr.isEmpty()) - attr += QLatin1Char(' '); - attr += "default"; - } - if (!attr.isEmpty()) - xmlWriter().writeAttribute("outputclass",attr); - generateQmlItem(qpn, relative, marker, false); - writeEndTag(); // </li> - writeEndTag(); // </ul> + startQmlProperty(qpn,relative,marker); + writeQmlDesc(node, marker); + writeEndTag(); // </qmlPropertyDetail> + writeEndTag(); // </qmlProperty> + } } else { /* @@ -4507,68 +4544,99 @@ void DitaXmlGenerator::generateDetailedQmlMember(Node* node, Process the whole list as we would for a QML property group. */ + writeStartTag(DT_qmlPropertyGroup); + QString id = "id-qml-propertygroup-" + node->name(); + id.replace('.','-'); + xmlWriter().writeAttribute("id",id); + writeStartTag(DT_apiName); + //writeCharacters("..."); + writeEndTag(); // </apiName> + writeStartTag(DT_qmlPropertyGroupDetail); + writeQmlDesc(node, marker); + writeEndTag(); // </qmlPropertyGroupDetail> NodeList::ConstIterator p = qpn->qmlPropNodes().begin(); - writeStartTag(DT_ul); while (p != qpn->qmlPropNodes().end()) { if ((*p)->type() == Node::QmlProperty) { QmlPropertyNode* q = static_cast<QmlPropertyNode*>(*p); - writeStartTag(DT_li); - writeGuidAttribute((Node*)q); - QString attr; - if (!qpn->isReadOnlySet()) - qpn->setReadOnly(!qpn->isWritable(tree_)); - if (qpn->isReadOnly()) - attr = "read-only"; - if (qpn->isDefault()) { - if (!attr.isEmpty()) - attr += QLatin1Char(' '); - attr += "default"; - } - if (!attr.isEmpty()) - xmlWriter().writeAttribute("outputclass",attr); - generateQmlItem(q, relative, marker, false); - writeEndTag(); // </li> + startQmlProperty(q,relative,marker); + writeEndTag(); // </qmlPropertyDetail> + writeEndTag(); // </qmlProperty> } ++p; } - writeEndTag(); // </ul> + writeEndTag(); // </qmlPropertyGroup } } - else if (node->type() == Node::QmlSignal) { - Node* n = const_cast<Node*>(node); - writeStartTag(DT_ul); - writeStartTag(DT_li); - writeGuidAttribute(n); - marked = getMarkedUpSynopsis(n, relative, marker, CodeMarker::Detailed); - writeText(marked, marker, relative); - writeEndTag(); // </li> - writeEndTag(); // </ul> - } - else if (node->type() == Node::QmlSignalHandler) { - Node* n = const_cast<Node*>(node); - writeStartTag(DT_ul); - writeStartTag(DT_li); - writeGuidAttribute(n); - marked = getMarkedUpSynopsis(n, relative, marker, CodeMarker::Detailed); - writeText(marked, marker, relative); - writeEndTag(); // </li> - writeEndTag(); // </ul> - } - else if (node->type() == Node::QmlMethod) { - Node* n = const_cast<Node*>(node); - writeStartTag(DT_ul); - writeStartTag(DT_li); - writeGuidAttribute(n); - marked = getMarkedUpSynopsis(n, relative, marker, CodeMarker::Detailed); - writeText(marked, marker, relative); - writeEndTag(); // </li> - writeEndTag(); // </ul> - } + else if (node->type() == Node::QmlSignal) + writeQmlRef(DT_qmlSignal,node,relative,marker); + else if (node->type() == Node::QmlSignalHandler) + writeQmlRef(DT_qmlSignalHandler,node,relative,marker); + else if (node->type() == Node::QmlMethod) + writeQmlRef(DT_qmlMethod,node,relative,marker); +} + +/*! + Outputs the DITA detailed documentation for a section + on a QML element reference page. + */ +void DitaXmlGenerator::writeQmlRef(DitaTag tag, + Node* node, + const InnerNode* relative, + CodeMarker* marker) +{ + writeStartTag(tag); + Node* n = const_cast<Node*>(node); + writeGuidAttribute(n); + writeStartTag(DT_apiName); + writeCharacters(n->name()); + writeEndTag(); // </apiName> + writeStartTag((DitaTag)((int)tag+2)); + writeStartTag((DitaTag)((int)tag+1)); + writeStartTag(DT_apiData); + QString marked = getMarkedUpSynopsis(n, relative, marker, CodeMarker::Detailed); + writeText(marked, marker, relative); + writeEndTag(); // </apiData> + if (node->isAttached()) { + writeStartTag(DT_qmlAttached); + xmlWriter().writeAttribute("name","attached"); + xmlWriter().writeAttribute("value","yes"); + writeEndTag(); // </qmlAttached> + } + writeEndTag(); // </qmlXxxDef> + writeQmlDesc(node, marker); + writeEndTag(); // </qmlXxxDetail> + writeEndTag(); // tag +} + +/*! + Writes the <apiDesc> tag and its contents for the \a node. + The \a marker is used for markeing up the text body. + */ +void DitaXmlGenerator::writeQmlDesc(Node* node, CodeMarker* marker) +{ + writeStartTag(DT_apiDesc); generateStatus(node, marker); generateBody(node, marker); generateThreadSafeness(node, marker); generateSince(node, marker); generateAlsoList(node, marker); + writeEndTag(); // </apiDesc> +} + +/*! + This generates a <qmlTypeDef> in which the + QML module name and version number are specified. + */ +void DitaXmlGenerator::generateQmlModuleDef(QmlClassNode* qcn) +{ + writeStartTag(DT_qmlImportModule); + writeStartTag(DT_apiItemName); + writeCharacters(qcn->qmlModuleName()); + writeEndTag(); // </apiItemName> + writeStartTag(DT_apiData); + writeCharacters(qcn->qmlModuleVersion()); + writeEndTag(); // </apiData> + writeEndTag(); // </qmlImportModule> } /*! @@ -4581,17 +4649,42 @@ void DitaXmlGenerator::generateQmlInherits(const QmlClassNode* qcn, CodeMarker* return; const FakeNode* base = qcn->qmlBase(); if (base) { - writeStartTag(DT_p); - xmlWriter().writeAttribute("outputclass","inherits"); + writeStartTag(DT_qmlInherits); + //writeStartTag(DT_qmlTypeDef); + //xmlWriter().writeAttribute("outputclass","inherits"); + writeStartTag(DT_apiData); Text text; - text << "[Inherits "; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(base)); text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); text << Atom(Atom::String, base->name()); text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); - text << "]"; generateText(text, qcn, marker); - writeEndTag(); // </p> + writeEndTag(); // </apiData> + writeEndTag(); // </qmlInherits> + } +} + +/*! + Output the "Inherit by" list for the QML element, + if it is inherited by any other elements. + */ +void DitaXmlGenerator::generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker) +{ + if (qcn) { + NodeList subs; + QmlClassNode::subclasses(qcn->name(),subs); + if (!subs.isEmpty()) { + writeStartTag(DT_qmlInheritedBy); + //writeStartTag(DT_qmlTypeDef); + //xmlWriter().writeAttribute("outputclass","inherited-by"); + writeStartTag(DT_apiData); + Text text; + appendSortedQmlNames(text,qcn,subs,marker); + text << Atom::ParaRight; + generateText(text, qcn, marker); + writeEndTag(); // </apiData> + writeEndTag(); // </qmlIneritedBy> + } } } @@ -4606,22 +4699,39 @@ void DitaXmlGenerator::generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* ma { ClassNode* cn = qcn->classNode(); if (cn && (cn->status() != Node::Internal)) { - writeStartTag(DT_p); - xmlWriter().writeAttribute("outputclass","instantiates"); + writeStartTag(DT_qmlInstantiates); + //writeStartTag(DT_qmlTypeDef); + //xmlWriter().writeAttribute("outputclass","instantiates"); + writeStartTag(DT_apiData); Text text; - text << "["; - text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); - text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); - text << Atom(Atom::String, qcn->name()); - text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); - text << " instantiates the C++ class "; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn)); text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); text << Atom(Atom::String, cn->name()); text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); - text << "]"; generateText(text, qcn, marker); - writeEndTag(); // </p> + writeEndTag(); // </apiData> + writeEndTag(); // </qmlInstantiates> + } +} + +/*! + Generate a <qmlXxxDef> for the "since" version string, if there is one. + */ +void DitaXmlGenerator::generateQmlSince(const Node* node) +{ + if (!node->since().isEmpty()) { + writeStartTag(DT_qmlSince); + //writeStartTag(DT_qmlTypeDef); + //xmlWriter().writeAttribute("outputclass","since"); + writeStartTag(DT_apiItemName); + QStringList pieces = node->since().split(QLatin1Char(' ')); + writeCharacters(pieces[0]); + writeEndTag(); // </apiItemName> + writeStartTag(DT_apiData); + if (pieces.size() > 1) + writeCharacters(pieces[1]); + writeEndTag(); // </apiData> + writeEndTag(); // </qmlSince> } } @@ -5589,7 +5699,7 @@ void DitaXmlGenerator::writeApiDesc(const Node* node, { if (!node->doc().isEmpty()) { inDetailedDescription = true; - enterApiDesc(QString(),title); + enterDesc(DT_apiDesc,QString(),title); generateBody(node, marker); generateAlsoList(node, marker); leaveSection(); @@ -5690,7 +5800,7 @@ DitaXmlGenerator::generateInnerNode(InnerNode* node) } /*! - Returns true if \a format is "XML" or "HTML" . + Returns true if \a format is "DITAXML" or "HTML" . */ bool DitaXmlGenerator::canHandleFormat(const QString& format) { @@ -6048,23 +6158,32 @@ void DitaXmlGenerator::writeTopicrefs(NodeMultiMap* nmm, const QString& navtitle xmlWriter().writeAttribute("navtitle",i.key()); xmlWriter().writeAttribute("href",fileName(i.value())); switch (i.value()->type()) { - case Node::Class: { - const NamespaceNode* nn = static_cast<const NamespaceNode*>(i.value()); - const NodeList& c = nn->childNodes(); - for (int j=0; j<c.size(); ++j) { - if (c[j]->isInternal() || c[j]->access() == Node::Private || c[j]->doc().isEmpty()) - continue; - if (c[j]->type() == Node::Class) { + case Node::Class: + case Node::Namespace: { + const NamespaceNode* nn = static_cast<const NamespaceNode*>(i.value()); + const NodeList& c = nn->childNodes(); + QMap<QString, const Node*> tempMap; + for (int j=0; j<c.size(); ++j) { + if (c[j]->isInternal() || c[j]->access() == Node::Private || c[j]->doc().isEmpty()) + continue; + if (c[j]->type() == Node::Class) { + tempMap.insert(c[j]->name(), c[j]); + } + } + QMap<QString, const Node*>::iterator classIterator = tempMap.begin(); + while (classIterator != tempMap.end()) { + const Node* currentNode = static_cast<const Node*>(classIterator.value()); writeStartTag(DT_topicref); - xmlWriter().writeAttribute("navtitle",c[j]->name()); - xmlWriter().writeAttribute("href",fileName(c[j])); + xmlWriter().writeAttribute("navtitle",currentNode->name()); + xmlWriter().writeAttribute("href",fileName(currentNode)); writeEndTag(); // </topicref> + ++classIterator; } + + break; } - break; - } - default: - break; + default: + break; } writeEndTag(); // </topicref> ++i; diff --git a/src/tools/qdoc/ditaxmlgenerator.h b/src/tools/qdoc/ditaxmlgenerator.h index 6ce42fc0b1..538a667849 100644 --- a/src/tools/qdoc/ditaxmlgenerator.h +++ b/src/tools/qdoc/ditaxmlgenerator.h @@ -79,9 +79,15 @@ public: enum DitaTag { DT_NONE, DT_alt, + DT_apiData, + DT_apiDef, + DT_apiDefItem, DT_apiDesc, + DT_apiDetail, + DT_apiItemName, DT_APIMap, DT_apiName, + DT_apiRef, DT_apiRelation, DT_audience, DT_author, @@ -224,6 +230,34 @@ public: DT_prodname, DT_prolog, DT_publisher, + DT_qmlAttached, + DT_qmlDetail, + DT_qmlImportModule, + DT_qmlInheritedBy, + DT_qmlInherits, + DT_qmlInstantiates, + DT_qmlMethod, + DT_qmlMethodDef, + DT_qmlMethodDetail, + DT_qmlName, + DT_qmlProperty, + DT_qmlPropertyDef, + DT_qmlPropertyDetail, + DT_qmlPropertyGroup, + DT_qmlPropertyGroupDef, + DT_qmlPropertyGroupDetail, + DT_qmlQualifier, + DT_qmlSignal, + DT_qmlSignalDef, + DT_qmlSignalDetail, + DT_qmlSignalHandler, + DT_qmlSignalHandlerDEf, + DT_qmlSignalHandlerDetail, + DT_qmlSignature, + DT_qmlSince, + DT_qmlType, + DT_qmlTypeDef, + DT_qmlTypeDetail, DT_relatedLinks, DT_resourceid, DT_revised, @@ -281,7 +315,7 @@ protected: CodeMarker* marker); virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker); virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker); - virtual QString fileExtension(const Node* node) const; + virtual QString fileExtension() const; virtual QString guidForNode(const Node* node); virtual QString linkForNode(const Node* node, const Node* relative); virtual QString refForAtom(Atom* atom, const Node* node); @@ -377,12 +411,23 @@ private: const Node* relative, CodeMarker* marker, bool summary); + void startQmlProperty(QmlPropertyNode* qpn, + const InnerNode* relative, + CodeMarker* marker); + void writeQmlRef(DitaTag tag, + Node* node, + const InnerNode* relative, + CodeMarker* marker); + void writeQmlDesc(Node* node, CodeMarker* marker); void generateDetailedQmlMember(Node* node, const InnerNode* relative, CodeMarker* marker); void generateQmlInherits(const QmlClassNode* qcn, CodeMarker* marker); + void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker); void generateQmlInstantiates(QmlClassNode* qcn, CodeMarker* marker); void generateInstantiatedBy(ClassNode* cn, CodeMarker* marker); + void generateQmlModuleDef(QmlClassNode* qcn); + void generateQmlSince(const Node* node); void generateSection(const NodeList& nl, const Node* relative, @@ -446,7 +491,7 @@ private: bool writeEndTag(DitaTag t=DT_NONE); DitaTag currentTag(); void clearSectionNesting() { sectionNestingLevel = 0; } - int enterApiDesc(const QString& outputclass, const QString& title); + int enterDesc(DitaTag tag, const QString& outputclass, const QString& title); int enterSection(const QString& outputclass, const QString& title); int leaveSection(); bool inSection() const { return (sectionNestingLevel > 0); } diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp index 4258bc69d0..fb08c7e609 100644 --- a/src/tools/qdoc/generator.cpp +++ b/src/tools/qdoc/generator.cpp @@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE QString Generator::baseDir_; +Generator* Generator::currentGenerator_; QStringList Generator::exampleDirs; QStringList Generator::exampleImgExts; QMap<QString, QMap<QString, QString> > Generator::fmtLeftMaps; @@ -346,7 +347,7 @@ QString Generator::fileName(const Node* node) const QString name = fileBase(node); name += QLatin1Char('.'); - name += fileExtension(node); + name += fileExtension(); return name; } @@ -447,6 +448,173 @@ QMap<QString, QString>& Generator::formattingRightMap() return fmtRightMaps[format()]; } +/*! + Returns the full document location. + */ +QString Generator::fullDocumentLocation(const Node *node, bool subdir) +{ + if (!node) + return ""; + if (!node->url().isEmpty()) + return node->url(); + + QString parentName; + QString anchorRef; + QString fdl = ""; + + /* + If the output is being sent to subdirectories of the + output directory, and if the subdir parameter is set, + prepend the subdirectory name + '/' to the result. + */ + if (subdir) { + fdl = node->outputSubdirectory(); + if (!fdl.isEmpty()) + fdl.append(QLatin1Char('/')); + } + if (node->type() == Node::Namespace) { + + // The root namespace has no name - check for this before creating + // an attribute containing the location of any documentation. + + if (!node->fileBase().isEmpty()) + parentName = node->fileBase() + "." + currentGenerator()->fileExtension(); + else + return ""; + } + else if (node->type() == Node::Fake) { + if ((node->subType() == Node::QmlClass) || + (node->subType() == Node::QmlBasicType)) { + QString fb = node->fileBase(); + if (fb.startsWith(Generator::outputPrefix(QLatin1String("QML")))) + return fb + "." + currentGenerator()->fileExtension(); + else { + QString mq = ""; + if (!node->qmlModuleName().isEmpty()) { + mq = node->qmlModuleIdentifier().replace(QChar('.'),QChar('-')); + mq = mq.toLower() + "-"; + } + return fdl+ Generator::outputPrefix(QLatin1String("QML")) + mq + + node->fileBase() + "." + currentGenerator()->fileExtension(); + } + } + else + parentName = node->fileBase() + "." + currentGenerator()->fileExtension(); + } + else if (node->fileBase().isEmpty()) + return ""; + + Node *parentNode = 0; + + if ((parentNode = node->relates())) { + parentName = fullDocumentLocation(node->relates()); + } + else if ((parentNode = node->parent())) { + if (parentNode->subType() == Node::QmlPropertyGroup) { + parentNode = parentNode->parent(); + parentName = fullDocumentLocation(parentNode); + } + else + parentName = fullDocumentLocation(node->parent()); + } + + switch (node->type()) { + case Node::Class: + case Node::Namespace: + if (parentNode && !parentNode->name().isEmpty()) { + parentName.remove("." + currentGenerator()->fileExtension()); + parentName += QLatin1Char('-') + + node->fileBase().toLower() + "." + currentGenerator()->fileExtension(); + } else { + parentName = node->fileBase() + "." + currentGenerator()->fileExtension(); + } + break; + case Node::Function: + { + /* + Functions can be destructors, overloaded, or + have associated properties. + */ + const FunctionNode *functionNode = + static_cast<const FunctionNode *>(node); + + if (functionNode->metaness() == FunctionNode::Dtor) + anchorRef = "#dtor." + functionNode->name().mid(1); + + else if (functionNode->associatedProperty()) + return fullDocumentLocation(functionNode->associatedProperty()); + + else if (functionNode->overloadNumber() > 1) + anchorRef = QLatin1Char('#') + functionNode->name() + + "-" + QString::number(functionNode->overloadNumber()); + else + anchorRef = QLatin1Char('#') + functionNode->name(); + } + + /* + Use node->name() instead of node->fileBase() as + the latter returns the name in lower-case. For + HTML anchors, we need to preserve the case. + */ + break; + case Node::Enum: + anchorRef = QLatin1Char('#') + node->name() + "-enum"; + break; + case Node::Typedef: + anchorRef = QLatin1Char('#') + node->name() + "-typedef"; + break; + case Node::Property: + anchorRef = QLatin1Char('#') + node->name() + "-prop"; + break; + case Node::QmlProperty: + anchorRef = QLatin1Char('#') + node->name() + "-prop"; + break; + case Node::QmlSignal: + anchorRef = QLatin1Char('#') + node->name() + "-signal"; + break; + case Node::QmlSignalHandler: + anchorRef = QLatin1Char('#') + node->name() + "-signal-handler"; + break; + case Node::QmlMethod: + anchorRef = QLatin1Char('#') + node->name() + "-method"; + break; + case Node::Variable: + anchorRef = QLatin1Char('#') + node->name() + "-var"; + break; + case Node::Fake: + { + /* + Use node->fileBase() for fake nodes because they are represented + by pages whose file names are lower-case. + */ + parentName = node->fileBase(); + parentName.replace(QLatin1Char('/'), "-").replace(".", "-"); + parentName += "." + currentGenerator()->fileExtension(); + } + break; + default: + break; + } + + // Various objects can be compat (deprecated) or obsolete. + if (node->type() != Node::Class && node->type() != Node::Namespace) { + switch (node->status()) { + case Node::Compat: + parentName.replace("." + currentGenerator()->fileExtension(), + "-compat." + currentGenerator()->fileExtension()); + break; + case Node::Obsolete: + parentName.replace("." + currentGenerator()->fileExtension(), + "-obsolete." + currentGenerator()->fileExtension()); + break; + default: + ; + } + } + + return fdl + parentName.toLower() + anchorRef; +} + QString Generator::fullName(const Node *node, const Node *relative, CodeMarker *marker) const @@ -785,8 +953,7 @@ void Generator::generateFileList(const FakeNode* fake, generateText(text, fake, marker); } -void Generator::generateInheritedBy(const ClassNode *classe, - CodeMarker *marker) +void Generator::generateInheritedBy(const ClassNode *classe, CodeMarker *marker) { if (!classe->derivedClasses().isEmpty()) { Text text; @@ -919,7 +1086,6 @@ void Generator::generateMaintainerList(const InnerNode* node, CodeMarker* marker } } -#ifdef QDOC_QML /*! Output the "Inherit by" list for the QML element, if it is inherited by any other elements. @@ -939,18 +1105,14 @@ void Generator::generateQmlInheritedBy(const QmlClassNode* qcn, } } } -#endif -#ifdef QDOC_QML /*! */ void Generator::generateQmlInherits(const QmlClassNode* , CodeMarker* ) { // stub. } -#endif -#ifdef QDOC_QML /*! Extract sections of markup text surrounded by \e qmltext and \e endqmltext and output them. @@ -982,7 +1144,6 @@ bool Generator::generateQmlText(const Text& text, } return result; } -#endif void Generator::generateReimplementedFrom(const FunctionNode *func, CodeMarker *marker) @@ -1449,6 +1610,7 @@ void Generator::initialize(const Config &config) QList<Generator *>::ConstIterator g = generators.begin(); while (g != generators.end()) { if (outputFormats.contains((*g)->format())) { + currentGenerator_ = (*g); (*g)->initializeGenerator(config); QStringList extraImages = config.getCleanPathList(CONFIG_EXTRAIMAGES+Config::dot+(*g)->format()); diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h index c97e59602d..59df66b4a7 100644 --- a/src/tools/qdoc/generator.h +++ b/src/tools/qdoc/generator.h @@ -90,6 +90,8 @@ public: virtual void terminateGenerator(); static const QString& baseDir() { return baseDir_; } + static Generator *currentGenerator() { return currentGenerator_; } + static QString fullDocumentLocation(const Node *node, bool subdir = false); static Generator *generatorForFormat(const QString& format); static void initialize(const Config& config); static const QString& outputDir() { return outDir_; } @@ -100,7 +102,7 @@ protected: 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 fileExtension() const = 0; virtual QString fullName(const Node *node, const Node *relative, CodeMarker *marker) const; @@ -171,6 +173,10 @@ protected: QString plainCode(const QString& markedCode); void setImageFileExtensions(const QStringList& extensions); void unknownAtom(const Atom *atom); + void appendSortedQmlNames(Text& text, + const Node* base, + const NodeList& subs, + CodeMarker *marker); QList<NameCollisionNode*> collisionNodes; QMap<QString, QStringList> editionGroupMap; @@ -185,6 +191,7 @@ protected: private: static QString baseDir_; + static Generator* currentGenerator_; static QStringList exampleDirs; static QStringList exampleImgExts; static QMap<QString, QMap<QString, QString> > fmtLeftMaps; @@ -219,10 +226,6 @@ private: const ClassNode *classe, const QList<RelatedClass> &classes, CodeMarker *marker); - void appendSortedQmlNames(Text& text, - const Node* base, - const NodeList& subs, - CodeMarker *marker); void generateReimplementedFrom(const FunctionNode *func, CodeMarker *marker); diff --git a/src/tools/qdoc/helpprojectwriter.cpp b/src/tools/qdoc/helpprojectwriter.cpp index da2a43d7e8..590feba166 100644 --- a/src/tools/qdoc/helpprojectwriter.cpp +++ b/src/tools/qdoc/helpprojectwriter.cpp @@ -211,7 +211,7 @@ QStringList HelpProjectWriter::keywordDetails(const Node *node) const details << node->name(); details << node->name(); } - details << HtmlGenerator::fullDocumentLocation(node,true); + details << Generator::fullDocumentLocation(node,true); return details; } @@ -271,12 +271,12 @@ bool HelpProjectWriter::generateSection(HelpProject &project, case Node::Class: project.keywords.append(keywordDetails(node)); - project.files.insert(HtmlGenerator::fullDocumentLocation(node,true)); + project.files.insert(Generator::fullDocumentLocation(node,true)); break; case Node::Namespace: project.keywords.append(keywordDetails(node)); - project.files.insert(HtmlGenerator::fullDocumentLocation(node,true)); + project.files.insert(Generator::fullDocumentLocation(node,true)); break; case Node::Enum: @@ -296,7 +296,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, details << item.name(); // "name" details << item.name(); // "id" } - details << HtmlGenerator::fullDocumentLocation(node,true); + details << Generator::fullDocumentLocation(node,true); project.keywords.append(details); } } @@ -328,7 +328,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, if (node->relates()) { project.memberStatus[node->relates()].insert(node->status()); - project.files.insert(HtmlGenerator::fullDocumentLocation(node->relates(),true)); + project.files.insert(Generator::fullDocumentLocation(node->relates(),true)); } else if (node->parent()) project.memberStatus[node->parent()].insert(node->status()); } @@ -342,7 +342,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, // Use the location of any associated enum node in preference // to that of the typedef. if (enumNode) - typedefDetails[2] = HtmlGenerator::fullDocumentLocation(enumNode,true); + typedefDetails[2] = Generator::fullDocumentLocation(enumNode,true); project.keywords.append(typedefDetails); } @@ -350,7 +350,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, case Node::Variable: { - QString location = HtmlGenerator::fullDocumentLocation(node,true); + QString location = Generator::fullDocumentLocation(node,true); project.files.insert(location.left(location.lastIndexOf(QLatin1Char('#')))); project.keywords.append(keywordDetails(node)); } @@ -370,12 +370,12 @@ bool HelpProjectWriter::generateSection(HelpProject &project, QStringList details; details << keyword->string() << keyword->string() - << HtmlGenerator::fullDocumentLocation(node,true) + + << Generator::fullDocumentLocation(node,true) + QLatin1Char('#') + Doc::canonicalTitle(keyword->string()); project.keywords.append(details); } else fakeNode->doc().location().warning( - tr("Bad keyword in %1").arg(HtmlGenerator::fullDocumentLocation(node,true)) + tr("Bad keyword in %1").arg(Generator::fullDocumentLocation(node,true)) ); } } @@ -398,7 +398,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, } } */ - project.files.insert(HtmlGenerator::fullDocumentLocation(node,true)); + project.files.insert(Generator::fullDocumentLocation(node,true)); } break; } @@ -477,7 +477,7 @@ void HelpProjectWriter::generate(const Tree *tre) void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer, const Node *node) { - QString href = HtmlGenerator::fullDocumentLocation(node,true); + QString href = Generator::fullDocumentLocation(node,true); QString objName = node->name(); switch (node->type()) { @@ -625,12 +625,12 @@ void HelpProjectWriter::generateProject(HelpProject &project) node = tree->findNode(QStringList("index.html")); QString indexPath; if (node) - indexPath = HtmlGenerator::fullDocumentLocation(node,true); + indexPath = Generator::fullDocumentLocation(node,true); else indexPath = "index.html"; writer.writeAttribute("ref", indexPath); writer.writeAttribute("title", project.indexTitle); - project.files.insert(HtmlGenerator::fullDocumentLocation(rootNode)); + project.files.insert(Generator::fullDocumentLocation(rootNode)); generateSections(project, writer, rootNode); @@ -668,7 +668,7 @@ void HelpProjectWriter::generateProject(HelpProject &project) const FakeNode *page = tree->findFakeNodeByTitle(atom->string()); writer.writeStartElement("section"); - QString indexPath = HtmlGenerator::fullDocumentLocation(page,true); + QString indexPath = Generator::fullDocumentLocation(page,true); writer.writeAttribute("ref", indexPath); writer.writeAttribute("title", atom->string()); project.files.insert(indexPath); @@ -693,7 +693,7 @@ void HelpProjectWriter::generateProject(HelpProject &project) if (!name.isEmpty()) { writer.writeStartElement("section"); - QString indexPath = HtmlGenerator::fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle),true); + QString indexPath = Generator::fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle),true); writer.writeAttribute("ref", indexPath); writer.writeAttribute("title", subproject.title); project.files.insert(indexPath); diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 24dd31e0b5..806be0a3c6 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -1690,7 +1690,7 @@ void HtmlGenerator::generateFakeNode(FakeNode* fake, CodeMarker* marker) /*! Returns "html" for this subclass of Generator. */ -QString HtmlGenerator::fileExtension(const Node * /* node */) const +QString HtmlGenerator::fileExtension() const { return "html"; } @@ -1876,12 +1876,12 @@ void HtmlGenerator::generateHeader(const QString& title, out() << " <link rel=\"prev\" href=\"" << anchorPair.first << "\" />\n"; - navigationLinks += "[Previous: <a href=\"" + anchorPair.first + "\">"; + navigationLinks += "<a class=\"prevPage\" href=\"" + anchorPair.first + "\">"; if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty()) navigationLinks += protect(anchorPair.second); else navigationLinks += protect(linkPair.second); - navigationLinks += "</a>]\n"; + navigationLinks += "</a>\n"; } if (node->links().contains(Node::NextLink)) { linkPair = node->links()[Node::NextLink]; @@ -1894,12 +1894,12 @@ void HtmlGenerator::generateHeader(const QString& title, out() << " <link rel=\"next\" href=\"" << anchorPair.first << "\" />\n"; - navigationLinks += "[Next: <a href=\"" + anchorPair.first + "\">"; + navigationLinks += "<a class=\"nextPage\" href=\"" + anchorPair.first + "\">"; if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty()) navigationLinks += protect(anchorPair.second); else navigationLinks += protect(linkPair.second); - navigationLinks += "</a>]\n"; + navigationLinks += "</a>\n"; } if (node->links().contains(Node::StartLink)) { linkPair = node->links()[Node::StartLink]; @@ -2110,7 +2110,7 @@ QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, if (sections.isEmpty()) return QString(); - QString fileName = fileBase(inner) + "-members." + fileExtension(inner); + QString fileName = fileBase(inner) + "-members." + fileExtension(); beginSubPage(inner, fileName); QString title = "List of All Members for " + inner->name(); generateHeader(title, inner, marker); @@ -2142,7 +2142,7 @@ QString HtmlGenerator::generateAllQmlMembersFile(const QmlClassNode* qml_cn, if (sections.isEmpty()) return QString(); - QString fileName = fileBase(qml_cn) + "-members." + fileExtension(qml_cn); + QString fileName = fileBase(qml_cn) + "-members." + fileExtension(); beginSubPage(qml_cn, fileName); QString title = "List of All Members for " + qml_cn->name(); generateHeader(title, qml_cn, marker); @@ -2181,11 +2181,11 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, if (status == CodeMarker::Compat) { title = "Compatibility Members for " + inner->name(); - fileName = fileBase(inner) + "-compat." + fileExtension(inner); + fileName = fileBase(inner) + "-compat." + fileExtension(); } else { title = "Obsolete Members for " + inner->name(); - fileName = fileBase(inner) + "-obsolete." + fileExtension(inner); + fileName = fileBase(inner) + "-obsolete." + fileExtension(); } beginSubPage(inner, fileName); @@ -4319,170 +4319,6 @@ void HtmlGenerator::generateExtractionMark(const Node *node, ExtractionMarkType } } -/*! - Returns the full document location for HTML-based documentation. - */ -QString HtmlGenerator::fullDocumentLocation(const Node *node, bool subdir) -{ - if (!node) - return ""; - if (!node->url().isEmpty()) - return node->url(); - - QString parentName; - QString anchorRef; - QString fdl = ""; - - /* - If the output is being sent to subdirectories of the - output directory, and if the subdir parameter is set, - prepend the subdirectory name + '/' to the result. - */ - if (subdir) { - fdl = node->outputSubdirectory(); - if (!fdl.isEmpty()) - fdl.append(QLatin1Char('/')); - } - if (node->type() == Node::Namespace) { - - // The root namespace has no name - check for this before creating - // an attribute containing the location of any documentation. - - if (!node->fileBase().isEmpty()) - parentName = node->fileBase() + ".html"; - else - return ""; - } - else if (node->type() == Node::Fake) { - if ((node->subType() == Node::QmlClass) || - (node->subType() == Node::QmlBasicType)) { - QString fb = node->fileBase(); - if (fb.startsWith(Generator::outputPrefix(QLatin1String("QML")))) - return fb + ".html"; - else { - QString mq = ""; - if (!node->qmlModuleName().isEmpty()) { - mq = node->qmlModuleIdentifier().replace(QChar('.'),QChar('-')); - mq = mq.toLower() + "-"; - } - return fdl+ Generator::outputPrefix(QLatin1String("QML")) + mq + - node->fileBase() + QLatin1String(".html"); - } - } - else - parentName = node->fileBase() + ".html"; - } - else if (node->fileBase().isEmpty()) - return ""; - - Node *parentNode = 0; - - if ((parentNode = node->relates())) { - parentName = fullDocumentLocation(node->relates()); - } - else if ((parentNode = node->parent())) { - if (parentNode->subType() == Node::QmlPropertyGroup) { - parentNode = parentNode->parent(); - parentName = fullDocumentLocation(parentNode); - } - else - parentName = fullDocumentLocation(node->parent()); - } - - switch (node->type()) { - case Node::Class: - case Node::Namespace: - if (parentNode && !parentNode->name().isEmpty()) { - parentName.remove(".html"); - parentName += QLatin1Char('-') - + node->fileBase().toLower() + ".html"; - } else { - parentName = node->fileBase() + ".html"; - } - break; - case Node::Function: - { - /* - Functions can be destructors, overloaded, or - have associated properties. - */ - const FunctionNode *functionNode = - static_cast<const FunctionNode *>(node); - - if (functionNode->metaness() == FunctionNode::Dtor) - anchorRef = "#dtor." + functionNode->name().mid(1); - - else if (functionNode->associatedProperty()) - return fullDocumentLocation(functionNode->associatedProperty()); - - else if (functionNode->overloadNumber() > 1) - anchorRef = QLatin1Char('#') + functionNode->name() - + "-" + QString::number(functionNode->overloadNumber()); - else - anchorRef = QLatin1Char('#') + functionNode->name(); - } - - /* - Use node->name() instead of node->fileBase() as - the latter returns the name in lower-case. For - HTML anchors, we need to preserve the case. - */ - break; - case Node::Enum: - anchorRef = QLatin1Char('#') + node->name() + "-enum"; - break; - case Node::Typedef: - anchorRef = QLatin1Char('#') + node->name() + "-typedef"; - break; - case Node::Property: - anchorRef = QLatin1Char('#') + node->name() + "-prop"; - break; - case Node::QmlProperty: - anchorRef = QLatin1Char('#') + node->name() + "-prop"; - break; - case Node::QmlSignal: - anchorRef = QLatin1Char('#') + node->name() + "-signal"; - break; - case Node::QmlSignalHandler: - anchorRef = QLatin1Char('#') + node->name() + "-signal-handler"; - break; - case Node::QmlMethod: - anchorRef = QLatin1Char('#') + node->name() + "-method"; - break; - case Node::Variable: - anchorRef = QLatin1Char('#') + node->name() + "-var"; - break; - case Node::Fake: - { - /* - Use node->fileBase() for fake nodes because they are represented - by pages whose file names are lower-case. - */ - parentName = node->fileBase(); - parentName.replace(QLatin1Char('/'), "-").replace(".", "-"); - parentName += ".html"; - } - break; - default: - break; - } - - // Various objects can be compat (deprecated) or obsolete. - if (node->type() != Node::Class && node->type() != Node::Namespace) { - switch (node->status()) { - case Node::Compat: - parentName.replace(".html", "-compat.html"); - break; - case Node::Obsolete: - parentName.replace(".html", "-obsolete.html"); - break; - default: - ; - } - } - - return fdl + parentName.toLower() + anchorRef; -} /*! This function outputs one or more manifest files in XML. diff --git a/src/tools/qdoc/htmlgenerator.h b/src/tools/qdoc/htmlgenerator.h index 403c1f0899..a4e6c2f368 100644 --- a/src/tools/qdoc/htmlgenerator.h +++ b/src/tools/qdoc/htmlgenerator.h @@ -94,7 +94,6 @@ public: static QString protect(const QString &string, const QString &encoding = "ISO-8859-1"); static QString cleanRef(const QString& ref); static QString sinceTitle(int i) { return sinceTitles[i]; } - static QString fullDocumentLocation(const Node *node, bool subdir = false); protected: virtual void startText(const Node *relative, CodeMarker *marker); @@ -103,7 +102,7 @@ protected: CodeMarker *marker); virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker); virtual void generateFakeNode(FakeNode* fake, CodeMarker* marker); - virtual QString fileExtension(const Node *node) const; + virtual QString fileExtension() const; virtual QString refForNode(const Node *node); virtual QString linkForNode(const Node *node, const Node *relative); virtual QString refForAtom(Atom *atom, const Node *node); diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp index f7985bd389..f230f92f06 100644 --- a/src/tools/qdoc/main.cpp +++ b/src/tools/qdoc/main.cpp @@ -64,6 +64,7 @@ #include "qmlcodeparser.h" #endif +#include <qdatetime.h> #include <qdebug.h> #include "qtranslator.h" @@ -99,6 +100,7 @@ static bool highlighting = false; static bool showInternal = false; static bool obsoleteLinks = false; static QStringList defines; +static QStringList indexDirs; static QHash<QString, Tree *> trees; /*! @@ -114,6 +116,10 @@ static void printHelp() "Display this information and exit\n" " -highlighting " "Turn on syntax highlighting (makes qdoc run slower)\n" + " -indexdir " + "Specify a directory where QDoc should search for indices to link to\n" + " -installdir " + "Specify the directory where the output will be after running \"make install\"\n" " -no-examples " "Do not generate documentation for examples\n" " -obsoletelinks " @@ -245,6 +251,48 @@ static void processQdocconfFile(const QString &fileName) Read some XML indexes containing definitions from other documentation sets. */ QStringList indexFiles = config.getStringList(CONFIG_INDEXES); + + QStringList dependModules = config.getStringList(CONFIG_DEPENDS); + + if (dependModules.size() > 0) { + if (indexDirs.size() > 0) { + for (int i = 0; i < dependModules.size(); i++) { + QMultiMap<uint, QFileInfo> foundIndices; + for (int j = 0; j < indexDirs.size(); j++) { + QString fileToLookFor = indexDirs[j] + "/" + dependModules[i] + + "/" + dependModules[i] + ".index"; + if (QFile::exists(fileToLookFor)) { + QFileInfo tempFileInfo(fileToLookFor); + foundIndices.insert(tempFileInfo.lastModified().toTime_t(), tempFileInfo); + } + } + if (foundIndices.size() > 1) { + /* + QDoc should always use the last entry in the multimap when there are + multiple index files for a module, since the last modified file has the + highest UNIX timestamp. + */ + qDebug() << "Multiple indices found for dependency:" << dependModules[i]; + qDebug() << "Using" << foundIndices.value( + foundIndices.keys()[foundIndices.size() - 1]).absoluteFilePath() + << "as index for" << dependModules[i]; + indexFiles << foundIndices.value( + foundIndices.keys()[foundIndices.size() - 1]).absoluteFilePath(); + } + else if (foundIndices.size() == 1) { + indexFiles << foundIndices.value(foundIndices.keys()[0]).absoluteFilePath(); + } + else { + qDebug() << "No indices for" << dependModules[i] << + "could be found in the specified index directories."; + } + } + } + else { + qDebug() << "Dependant modules specified, but not index directories were set." + << "There will probably be errors for missing links."; + } + } tree->readIndexes(indexFiles); QSet<QString> excludedDirs; @@ -432,6 +480,20 @@ int main(int argc, char **argv) else if (opt == "-no-examples") { Config::generateExamples = false; } + else if (opt == "-indexdir") { + if (QFile::exists(argv[i])) { + indexDirs += argv[i]; + } + else { + qDebug() << "Cannot find index directory" << argv[i]; + return EXIT_FAILURE; + } + i++; + } + else if (opt == "-installdir") { + Config::installDir = argv[i]; + i++; + } else if (opt == "-obsoletelinks") { obsoleteLinks = true; } diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index 24c0006dae..4d6c58a8a3 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -48,10 +48,23 @@ QT_BEGIN_NAMESPACE +int Node::propertyGroupCount_ = 0; ExampleNodeMap ExampleNode::exampleNodeMap; QStringMap Node::operators_; /*! + Increment the number of property groups seen in the current + file, and return the new value. + */ +int Node::incPropertyGroupCount() { return ++propertyGroupCount_; } + +/*! + Reset the number of property groups seen in the current file + to 0, because we are starting a new file. + */ +void Node::clearPropertyGroupCount() { propertyGroupCount_ = 0; } + +/*! \class Node \brief The Node class is a node in the Tree. @@ -2182,17 +2195,26 @@ QmlBasicTypeNode::QmlBasicTypeNode(InnerNode *parent, always a QmlClassNode. */ QmlPropGroupNode::QmlPropGroupNode(QmlClassNode* parent, const QString& name) - //bool attached) : FakeNode(parent, name, QmlPropertyGroup, Node::ApiPage) -#if 0 - isdefault_(false), - attached_(attached), - readOnly_(-1) -#endif { - // nothing. + idNumber_ = -1; +} + +/*! + Return the property group node's id number for use in + constructing an id attribute for the property group. + If the id number is currently -1, increment the global + property group count and set the id number to the new + value. + */ +QString QmlPropGroupNode::idNumber() +{ + if (idNumber_ == -1) + idNumber_ = incPropertyGroupCount(); + return QString().setNum(idNumber_); } + /*! Constructor for the QML property node, when the \a parent is QML property group node. This constructor is only used @@ -2632,7 +2654,7 @@ QString Node::idForNode() const str += "-" + tail; } else - qDebug() << "qdoc3 internal error: Operator missing from operators_ map:" << op; + qDebug() << "qdoc internal error: Operator missing from operators_ map:" << op; } else { str += op; @@ -2649,11 +2671,11 @@ QString Node::idForNode() const if (parent_->subType() == QmlClass) str = "qml-method-" + func->name(); else - qDebug() << "qdoc3 internal error: Node subtype not handled:" + qDebug() << "qdoc internal error: Node subtype not handled:" << parent_->subType() << func->name(); } else - qDebug() << "qdoc3 internal error: Node type not handled:" + qDebug() << "qdoc internal error: Node type not handled:" << parent_->type() << func->name(); } @@ -2662,50 +2684,53 @@ QString Node::idForNode() const } break; case Node::Fake: - { - switch (subType()) { - case Node::QmlClass: - str = "qml-class-" + name(); - break; - case Node::QmlPropertyGroup: - str = "qml-property-" + name(); - break; - case Node::Page: - case Node::Group: - case Node::Module: - case Node::HeaderFile: - str = title(); - if (str.isEmpty()) { + { + switch (subType()) { + case Node::QmlClass: + str = "qml-class-" + name(); + break; + case Node::QmlPropertyGroup: + { + Node* n = const_cast<Node*>(this); + str = "qml-propertygroup-" + n->name(); + } + break; + case Node::Page: + case Node::Group: + case Node::Module: + case Node::HeaderFile: + str = title(); + if (str.isEmpty()) { + str = name(); + if (str.endsWith(".html")) + str.remove(str.size()-5,5); + } + str.replace("/","-"); + break; + case Node::File: + str = name(); + str.replace("/","-"); + break; + case Node::Example: str = name(); - if (str.endsWith(".html")) - str.remove(str.size()-5,5); + str.replace("/","-"); + break; + case Node::QmlBasicType: + str = "qml-basic-type-" + name(); + break; + case Node::QmlModule: + str = "qml-module-" + name(); + break; + case Node::Collision: + str = title(); + str.replace(": ","-"); + break; + default: + qDebug() << "ERROR: A case was not handled in Node::idForNode():" + << "subType():" << subType() << "type():" << type(); + break; } - str.replace("/","-"); - break; - case Node::File: - str = name(); - str.replace("/","-"); - break; - case Node::Example: - str = name(); - str.replace("/","-"); - break; - case Node::QmlBasicType: - str = "qml-basic-type-" + name(); - break; - case Node::QmlModule: - str = "qml-module-" + name(); - break; - case Node::Collision: - str = title(); - str.replace(": ","-"); - break; - default: - qDebug() << "ERROR: A case was not handled in Node::idForNode():" - << "subType():" << subType() << "type():" << type(); - break; } - } break; case Node::QmlProperty: str = "qml-property-" + name(); diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index 45b5ded640..b0be5f0be8 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -190,6 +190,7 @@ public: virtual bool isAbstract() const { return false; } virtual bool isQmlPropertyGroup() const { return false; } virtual bool isCollisionNode() const { return false; } + virtual bool isAttached() const { return false; } virtual void setAbstract(bool ) { } virtual QString title() const { return QString(); } bool isInternal() const; @@ -238,6 +239,7 @@ public: virtual const ImportList* importList() const { return 0; } virtual void setImportList(const ImportList& ) { } virtual const Node* applyModuleIdentifier(const Node* ) const { return 0; } + virtual QString idNumber() { return "0"; } QmlClassNode* qmlClassNode(); ClassNode* declarativeCppNode(); const QString& outputSubdirectory() const { return outSubDir_; } @@ -251,6 +253,8 @@ public: static QString pageTypeString(unsigned t); static QString nodeTypeString(unsigned t); static QString nodeSubtypeString(unsigned t); + static int incPropertyGroupCount(); + static void clearPropertyGroupCount(); protected: Node(Type type, InnerNode* parent, const QString& name); @@ -288,6 +292,7 @@ private: QString qmlModuleName_; QString qmlModuleVersion_; static QStringMap operators_; + static int propertyGroupCount_; }; class FunctionNode; @@ -563,28 +568,18 @@ class QmlPropGroupNode : public FakeNode { public: QmlPropGroupNode(QmlClassNode* parent, const QString& name); - //bool attached); virtual ~QmlPropGroupNode() { } virtual bool isQmlNode() const { return true; } virtual bool isQtQuickNode() const { return parent()->isQtQuickNode(); } virtual QString qmlModuleName() const { return parent()->qmlModuleName(); } virtual QString qmlModuleVersion() const { return parent()->qmlModuleVersion(); } virtual QString qmlModuleIdentifier() const { return parent()->qmlModuleIdentifier(); } + virtual QString idNumber(); const QString& element() const { return parent()->name(); } -#if 0 - void setDefault() { isdefault_ = true; } - void setReadOnly(int ro) { readOnly_ = ro; } - int getReadOnly() const { return readOnly_; } - bool isDefault() const { return isdefault_; } - bool isAttached() const { return attached_; } - bool isReadOnly() const { return (readOnly_ > 0); } -private: - bool isdefault_; - bool attached_; - int readOnly_; -#endif + private: + int idNumber_; }; class QmlPropertyNode; @@ -619,8 +614,8 @@ public: bool isStored() const { return fromFlagValue(stored_,true); } bool isDesignable() const { return fromFlagValue(designable_,false); } bool isWritable(Tree* tree); - bool isAttached() const { return attached_; } bool isReadOnly() const { return fromFlagValue(readOnly_,false); } + virtual bool isAttached() const { return attached_; } virtual bool isQmlNode() const { return true; } virtual bool isQtQuickNode() const { return parent()->isQtQuickNode(); } virtual QString qmlModuleName() const { return parent()->qmlModuleName(); } @@ -794,7 +789,7 @@ public: QStringList reconstructParams(bool values = false) const; QString signature(bool values = false) const; const QString& element() const { return parent()->name(); } - bool isAttached() const { return attached_; } + virtual bool isAttached() const { return attached_; } virtual bool isQmlNode() const { return ((type() == QmlSignal) || (type() == QmlMethod) || diff --git a/src/tools/qdoc/puredocparser.cpp b/src/tools/qdoc/puredocparser.cpp index 2303591974..072e6331a0 100644 --- a/src/tools/qdoc/puredocparser.cpp +++ b/src/tools/qdoc/puredocparser.cpp @@ -57,7 +57,7 @@ PureDocParser::~PureDocParser() QStringList PureDocParser::sourceFileNameFilter() { - return QStringList("*.qdoc"); + return QStringList() << "*.qdoc" << "*.qtx" << "*.qtt"; } QT_END_NAMESPACE diff --git a/src/tools/qdoc/qdoc.pro b/src/tools/qdoc/qdoc.pro index 09f9b7a0c1..484b0c6ba1 100644 --- a/src/tools/qdoc/qdoc.pro +++ b/src/tools/qdoc/qdoc.pro @@ -92,9 +92,9 @@ SOURCES += jscodemarker.cpp \ qmlmarkupvisitor.cpp \ qmlvisitor.cpp -### Documentation for qdoc3 ### +### Documentation for qdoc ### -qtPrepareTool(QDOC, qdoc3) +qtPrepareTool(QDOC, qdoc) qtPrepareTool(QHELPGENERATOR, qhelpgenerator) equals(QMAKE_DIR_SEP, /) { @@ -104,11 +104,11 @@ equals(QMAKE_DIR_SEP, /) { QDOC = $$replace(QDOC, "/", "\\") } -html-docs.commands = cd \"$$QT_BUILD_TREE/doc\" && $$QDOC $$QT_SOURCE_TREE/tools/qdoc3/doc/config/qdoc.qdocconf +html-docs.commands = cd \"$$QT_BUILD_TREE/doc\" && $$QDOC $$QT_SOURCE_TREE/tools/qdoc/doc/config/qdoc.qdocconf html-docs.files = $$QT_BUILD_TREE/doc/html -qch-docs.commands = cd \"$$QT_BUILD_TREE/doc\" && $$QHELPGENERATOR $$QT_BUILD_TREE/tools/qdoc3/doc/html/qdoc.qhp -o $$QT_BUILD_TREE/tools/qdoc3/doc/qch/qdoc.qch -qch-docs.files = $$QT_BUILD_TREE/tools/qdoc3/doc/qch +qch-docs.commands = cd \"$$QT_BUILD_TREE/doc\" && $$QHELPGENERATOR $$QT_BUILD_TREE/tools/qdoc/doc/html/qdoc.qhp -o $$QT_BUILD_TREE/tools/qdoc/doc/qch/qdoc.qch +qch-docs.files = $$QT_BUILD_TREE/tools/qdoc/doc/qch qch-docs.path = $$[QT_INSTALL_DOCS] qch-docs.CONFIG += no_check_exist directory diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index 3dfcfea48b..ac55cb7318 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -967,7 +967,18 @@ void Tree::readIndexFile(const QString& path) file.close(); QDomElement indexElement = document.documentElement(); - QString indexUrl = indexElement.attribute("url", ""); + + // Generate a relative URL between the install dir and the index file + // when the -installdir command line option is set. + QString indexUrl; + if (Config::installDir.isEmpty()) { + indexUrl = indexElement.attribute("url", ""); + } + else { + QDir installDir(Config::installDir); + indexUrl = installDir.relativeFilePath(path).section('/', 0, -2); + } + priv->basesList.clear(); priv->relatedList.clear(); @@ -1513,7 +1524,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter& writer, QString href = node->outputSubdirectory(); if (!href.isEmpty()) href.append(QLatin1Char('/')); - href.append(HtmlGenerator::fullDocumentLocation(node)); + href.append(Generator::fullDocumentLocation(node)); writer.writeAttribute("href", href); if ((node->type() != Node::Fake) && (!node->isQmlNode())) writer.writeAttribute("location", node->location().fileName()); @@ -2026,7 +2037,7 @@ void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, const InnerNode* i if (node->type() == Node::Class) { writer.writeTextElement("name", node->fullDocumentName()); - writer.writeTextElement("filename", HtmlGenerator::fullDocumentLocation(node,true)); + writer.writeTextElement("filename", Generator::fullDocumentLocation(node,true)); // Classes contain information about their base classes. const ClassNode* classNode = static_cast<const ClassNode*>(node); @@ -2044,7 +2055,7 @@ void Tree::generateTagFileCompounds(QXmlStreamWriter& writer, const InnerNode* i generateTagFileCompounds(writer, static_cast<const InnerNode*>(node)); } else { writer.writeTextElement("name", node->fullDocumentName()); - writer.writeTextElement("filename", HtmlGenerator::fullDocumentLocation(node,true)); + writer.writeTextElement("filename", Generator::fullDocumentLocation(node,true)); // Recurse to write all members. generateTagFileMembers(writer, static_cast<const InnerNode*>(node)); @@ -2163,7 +2174,7 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer, const InnerNode* inn "virtual " + functionNode->returnType()); writer.writeTextElement("name", objName); - QStringList pieces = HtmlGenerator::fullDocumentLocation(node,true).split(QLatin1Char('#')); + QStringList pieces = Generator::fullDocumentLocation(node,true).split(QLatin1Char('#')); writer.writeTextElement("anchorfile", pieces[0]); writer.writeTextElement("anchor", pieces[1]); @@ -2202,7 +2213,7 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer, const InnerNode* inn const PropertyNode* propertyNode = static_cast<const PropertyNode*>(node); writer.writeAttribute("type", propertyNode->dataType()); writer.writeTextElement("name", objName); - QStringList pieces = HtmlGenerator::fullDocumentLocation(node,true).split(QLatin1Char('#')); + QStringList pieces = Generator::fullDocumentLocation(node,true).split(QLatin1Char('#')); writer.writeTextElement("anchorfile", pieces[0]); writer.writeTextElement("anchor", pieces[1]); writer.writeTextElement("arglist", ""); @@ -2214,7 +2225,7 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer, const InnerNode* inn { const EnumNode* enumNode = static_cast<const EnumNode*>(node); writer.writeTextElement("name", objName); - QStringList pieces = HtmlGenerator::fullDocumentLocation(node).split(QLatin1Char('#')); + QStringList pieces = Generator::fullDocumentLocation(node).split(QLatin1Char('#')); writer.writeTextElement("anchor", pieces[1]); writer.writeTextElement("arglist", ""); writer.writeEndElement(); // member @@ -2238,7 +2249,7 @@ void Tree::generateTagFileMembers(QXmlStreamWriter& writer, const InnerNode* inn else writer.writeAttribute("type", ""); writer.writeTextElement("name", objName); - QStringList pieces = HtmlGenerator::fullDocumentLocation(node,true).split(QLatin1Char('#')); + QStringList pieces = Generator::fullDocumentLocation(node,true).split(QLatin1Char('#')); writer.writeTextElement("anchorfile", pieces[0]); writer.writeTextElement("anchor", pieces[1]); writer.writeTextElement("arglist", ""); @@ -2382,9 +2393,7 @@ Node* Tree::findNodeRecursive(const QStringList& path, else if (n->isCollisionNode()) { if (acceptCollision) return n; - return n = findNodeRecursive(path, pathIndex, n, type, subtype); - if (n) - return n; + return findNodeRecursive(path, pathIndex, n, type, subtype); } else return 0; |