diff options
Diffstat (limited to 'src/tools/qdoc/htmlgenerator.cpp')
-rw-r--r-- | src/tools/qdoc/htmlgenerator.cpp | 391 |
1 files changed, 216 insertions, 175 deletions
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index b4ea771fcc..7c94b83fda 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -268,7 +268,6 @@ QString HtmlGenerator::format() */ void HtmlGenerator::generateDocs() { - qdb_->buildCollections(); Node* qflags = qdb_->findNodeByNameAndType(QStringList("QFlags"), Node::Class, Node::NoSubType); if (qflags) qflagsHref_ = linkForNode(qflags,0); @@ -488,9 +487,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark break; case Atom::AnnotatedList: { - DocNode* dn = qdb_->getGroup(atom->string()); - if (dn) - generateAnnotatedList(relative, marker, dn->members()); + GroupNode* gn = qdb_->getGroup(atom->string()); + if (gn) + generateList(gn, marker, atom->string()); } break; case Atom::GeneratedList: @@ -507,10 +506,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark QString arg = atom->string().trimmed(); QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed(); QDocDatabase* qdb = QDocDatabase::qdocDB(); - DocNode* dn = qdb->findModule(moduleName); - if (dn) { + ModuleNode* mn = qdb->findModule(moduleName); + if (mn) { NodeMap m; - dn->getMemberClasses(m); + mn->getMemberClasses(m); if (!m.isEmpty()) { generateAnnotatedList(relative, marker, m); } @@ -553,16 +552,25 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark generateCompactList(Generic, relative, qdb_->getServiceClasses(), false, QStringLiteral("Q")); } else if (atom->string() == "overviews") { - generateOverviewList(relative); + generateList(relative, marker, "overviews"); + } + else if (atom->string() == "cpp-modules") { + generateList(relative, marker, "cpp-modules"); + } + else if (atom->string() == "qml-modules") { + generateList(relative, marker, "qml-modules"); } else if (atom->string() == "namespaces") { generateAnnotatedList(relative, marker, qdb_->getNamespaces()); } else if (atom->string() == "related") { - const DocNode *dn = static_cast<const DocNode *>(relative); - if (dn) - generateAnnotatedList(dn, marker, dn->members()); + generateList(relative, marker, "related"); } +#if 0 + /* + This is not used in Qt5, as of 10/02/2014 + Remove permanently if it is not missed. + */ else if (atom->string() == "relatedinline") { const DocNode *dn = static_cast<const DocNode *>(relative); if (dn && !dn->members().isEmpty()) { @@ -576,6 +584,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark generateBody(node, marker); } } +#endif break; case Atom::SinceList: { @@ -1473,29 +1482,7 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker) dn, marker); - if (dn->subType() == Node::Module) { - // Generate brief text and status for modules. - generateBrief(dn, marker); - generateStatus(dn, marker); - generateSince(dn, marker); - - NodeMap nm; - dn->getMemberNamespaces(nm); - if (!nm.isEmpty()) { - out() << "<a name=\"" << registerRef("namespaces") << "\"></a>" << divNavTop << '\n'; - out() << "<h2>Namespaces</h2>\n"; - generateAnnotatedList(dn, marker, nm); - } - nm.clear(); - dn->getMemberClasses(nm); - if (!nm.isEmpty()) { - out() << "<a name=\"" << registerRef("classes") << "\"></a>" << divNavTop << '\n'; - out() << "<h2>Classes</h2>\n"; - generateAnnotatedList(dn, marker, nm); - } - nm.clear(); - } - else if (dn->subType() == Node::HeaderFile) { + if (dn->subType() == Node::HeaderFile) { // Generate brief text and status for modules. generateBrief(dn, marker); generateStatus(dn, marker); @@ -1584,29 +1571,100 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker) ++s; } - Text brief = dn->doc().briefText(); - if (dn->subType() == Node::Module && !brief.isEmpty()) { - generateExtractionMark(dn, DetailedDescriptionMark); + generateExtractionMark(dn, DetailedDescriptionMark); + out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504 + + generateBody(dn, marker); + out() << "</div>\n"; // QTBUG-9504 + generateAlsoList(dn, marker); + generateExtractionMark(dn, EndMark); + + sections = marker->sections(dn, CodeMarker::Detailed, CodeMarker::Okay); + s = sections.constBegin(); + while (s != sections.constEnd()) { + //out() << "<hr />\n"; + out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; + + NodeList::ConstIterator m = (*s).members.constBegin(); + while (m != (*s).members.constEnd()) { + generateDetailedMember(*m, dn, marker); + ++m; + } + ++s; + } + generateFooter(dn); +} + +/*! + Generate the HTML page for a group, module, or QML module. + */ +void HtmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marker) +{ + SubTitleSize subTitleSize = LargeSubTitle; + QList<Section> sections; + QList<Section>::const_iterator s; + QString fullTitle = cn->fullTitle(); + QString htmlTitle = fullTitle; + + generateHeader(htmlTitle, cn, marker); + generateTableOfContents(cn,marker,0); + generateTitle(fullTitle, Text() << cn->subTitle(), subTitleSize, cn, marker); + + if (cn->isModule()) { + // Generate brief text and status for modules. + generateBrief(cn, marker); + generateStatus(cn, marker); + generateSince(cn, marker); + + NodeMap nm; + cn->getMemberNamespaces(nm); + if (!nm.isEmpty()) { + out() << "<a name=\"" << registerRef("namespaces") << "\"></a>" << divNavTop << '\n'; + out() << "<h2>Namespaces</h2>\n"; + generateAnnotatedList(cn, marker, nm); + } + nm.clear(); + cn->getMemberClasses(nm); + if (!nm.isEmpty()) { + out() << "<a name=\"" << registerRef("classes") << "\"></a>" << divNavTop << '\n'; + out() << "<h2>Classes</h2>\n"; + generateAnnotatedList(cn, marker, nm); + } + nm.clear(); + } + + sections = marker->sections(cn, CodeMarker::Summary, CodeMarker::Okay); + s = sections.constBegin(); + while (s != sections.constEnd()) { + out() << "<a name=\"" << registerRef((*s).name) << "\"></a>" << divNavTop << '\n'; + out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; + generateSectionList(*s, cn, marker, CodeMarker::Summary); + ++s; + } + + Text brief = cn->doc().briefText(); + if (cn->isModule() && !brief.isEmpty()) { + generateExtractionMark(cn, DetailedDescriptionMark); out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << '\n'; out() << "<div class=\"descr\">\n"; // QTBUG-9504 out() << "<h2>" << "Detailed Description" << "</h2>\n"; } else { - generateExtractionMark(dn, DetailedDescriptionMark); + generateExtractionMark(cn, DetailedDescriptionMark); out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504 } - generateBody(dn, marker); + generateBody(cn, marker); out() << "</div>\n"; // QTBUG-9504 - generateAlsoList(dn, marker); - generateExtractionMark(dn, EndMark); + generateAlsoList(cn, marker); + generateExtractionMark(cn, EndMark); - if ((dn->subType() == Node::Group)) - generateAnnotatedList(dn, marker, dn->members()); - else if (dn->subType() == Node::QmlModule) - generateAnnotatedList(dn, marker, dn->members()); + if (cn->isGroup()) + generateAnnotatedList(cn, marker, cn->members()); + else if (cn->isQmlModule()) + generateAnnotatedList(cn, marker, cn->members()); - sections = marker->sections(dn, CodeMarker::Detailed, CodeMarker::Okay); + sections = marker->sections(cn, CodeMarker::Detailed, CodeMarker::Okay); s = sections.constBegin(); while (s != sections.constEnd()) { //out() << "<hr />\n"; @@ -1614,12 +1672,12 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker) NodeList::ConstIterator m = (*s).members.constBegin(); while (m != (*s).members.constEnd()) { - generateDetailedMember(*m, dn, marker); + generateDetailedMember(*m, cn, marker); ++m; } ++s; } - generateFooter(dn); + generateFooter(cn); } /*! @@ -1895,7 +1953,7 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker) if (inner->type() == Node::Class || inner->type() == Node::Namespace) { //add the QT variable to the map if (!inner->moduleName().isEmpty()) { - DocNode * moduleNode = qdb_->findModule(inner->moduleName()); + ModuleNode* moduleNode = qdb_->findModule(inner->moduleName()); if (moduleNode && !moduleNode->qtVariable().isEmpty()) { text.clear(); text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_TELETYPE) @@ -2007,9 +2065,9 @@ void HtmlGenerator::generateQmlRequisites(QmlClassNode *qcn, CodeMarker *marker) //add the module name and version to the map QString qmlModuleVersion; - DocNode* dn = qdb_->findQmlModule(qcn->qmlModuleName()); - if (dn) - qmlModuleVersion = dn->qmlModuleVersion(); + QmlModuleNode* qmn = qdb_->findQmlModule(qcn->qmlModuleName()); + if (qmn) + qmlModuleVersion = qmn->qmlModuleVersion(); else qmlModuleVersion = qcn->qmlModuleVersion(); text.clear(); @@ -2141,7 +2199,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node, QList<Atom*> toc; if (node->doc().hasTableOfContents()) toc = node->doc().tableOfContents(); - if (toc.isEmpty() && !sections && (node->subType() != Node::Module)) + if (toc.isEmpty() && !sections && !node->isModule()) return; QStringList sectionNumber; @@ -2156,7 +2214,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node, sectionNumber.append("1"); out() << "<ul>\n"; - if (node->subType() == Node::Module) { + if (node->isModule()) { if (node->hasNamespaces()) { out() << "<li class=\"level" << sectionNumber.size() @@ -2183,9 +2241,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node, } } } - else if (sections && ((node->type() == Node::Class) || - (node->type() == Node::Namespace) || - (node->subType() == Node::QmlClass))) { + else if (sections && (node->isClass() || node->isNamespace() || node->isQmlType())) { QList<Section>::ConstIterator s = sections->constBegin(); while (s != sections->constEnd()) { if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) { @@ -2453,7 +2509,7 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, NodeMap& classM NodeMap newTop; foreach (const RelatedClass &d, child->derivedClasses()) { - if (d.node_ && (d.access_ != Node::Private && !d.node_->doc().isEmpty())) + if (d.node_ && !d.isPrivate() && !d.node_->isInternal() && d.node_->hasDoc()) newTop.insert(d.node_->name(), d.node_); } if (!newTop.isEmpty()) { @@ -2474,33 +2530,29 @@ void HtmlGenerator::generateAnnotatedList(const Node* relative, { if (nodeMap.isEmpty()) return; - NodeList nl; - NodeMap::const_iterator i = nodeMap.begin(); - while (i != nodeMap.end()) { - nl.append(i.value()); - ++i; - } - generateAnnotatedList(relative, marker, nl); + generateAnnotatedList(relative, marker, nodeMap.values()); } +/*! + */ void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *marker, - const NodeList& nodes) + const NodeList& unsortedNodes) { + NodeMap nm; bool allInternal = true; - foreach (const Node* node, nodes) { - if (!node->isInternal() && node->status() != Node::Obsolete) { + foreach (Node* node, unsortedNodes) { + if (!node->isInternal() && !node->isObsolete()) { allInternal = false; + nm.insert(node->fullName(relative), node); } } if (allInternal) return; out() << "<table class=\"annotated\">\n"; int row = 0; + NodeList nodes = nm.values(); foreach (const Node* node, nodes) { - if (node->isInternal() || node->status() == Node::Obsolete) - continue; - if (++row % 2 == 1) out() << "<tr class=\"odd topAlign\">"; else @@ -2509,7 +2561,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative, generateFullName(node, relative); out() << "</p></td>"; - if (!(node->type() == Node::Document)) { + if (!node->isDocNode()) { Text brief = node->doc().trimmedBriefText(node->name()); if (!brief.isEmpty()) { out() << "<td class=\"tblDescr\"><p>"; @@ -2794,114 +2846,102 @@ void HtmlGenerator::generateQmlItem(const Node *node, out() << highlightedCode(marked, relative, false); } -void HtmlGenerator::generateOverviewList(const Node *relative) +void HtmlGenerator::generateList(const Node* relative, CodeMarker* marker, const QString& selector) { - QMap<const DocNode *, QMap<QString, DocNode *> > docNodeMap; - QMap<QString, const DocNode *> groupTitlesMap; - QMap<QString, DocNode *> uncategorizedNodeMap; + NodeList nl; + CollectionList cl; QRegExp singleDigit("\\b([0-9])\\b"); - const NodeList children = qdb_->primaryTreeRoot()->childNodes(); - foreach (Node *child, children) { - if (child->type() == Node::Document && child != relative) { - DocNode *docNode = static_cast<DocNode *>(child); - - // Check whether the page is part of a group or is the group - // definition page. - QString group; - bool isGroupPage = false; - if (docNode->doc().metaCommandsUsed().contains("group")) { - group = docNode->doc().metaCommandArgs("group")[0].first; - isGroupPage = true; - } - - // there are too many examples; they would clutter the list - if (docNode->subType() == Node::Example) - continue; - - // not interested either in individual (Qt Designer etc.) manual chapters - if (docNode->links().contains(Node::ContentsLink)) - continue; - - // Discard external nodes. - if (docNode->subType() == Node::ExternalPage) - continue; - - QString sortKey = docNode->fullTitle().toLower(); - if (sortKey.startsWith("the ")) - sortKey.remove(0, 4); - sortKey.replace(singleDigit, "0\\1"); - - if (!group.isEmpty()) { - if (isGroupPage) { - // If we encounter a group definition page, we add all - // the pages in that group to the list for that group. - foreach (Node *member, docNode->members()) { - if (member->isInternal() || member->type() != Node::Document) - continue; - DocNode *page = static_cast<DocNode *>(member); - if (page) { - QString sortKey = page->fullTitle().toLower(); - if (sortKey.startsWith("the ")) - sortKey.remove(0, 4); - sortKey.replace(singleDigit, "0\\1"); - docNodeMap[const_cast<const DocNode *>(docNode)].insert(sortKey, page); - groupTitlesMap[docNode->fullTitle()] = const_cast<const DocNode *>(docNode); - } - } - } - else if (!isGroupPage) { - // If we encounter a page that belongs to a group then - // we add that page to the list for that group. - const DocNode* gn = qdb_->getGroup(group); - if (gn && !docNode->isInternal()) - docNodeMap[gn].insert(sortKey, docNode); - } - } + if (selector == "overviews") { + CNMap groups; + qdb_->mergeCollections(Node::Group, groups, relative); + cl = groups.values(); + foreach (CollectionNode* cn, cl) + nl.append(cn); + generateAnnotatedList(relative, marker, nl); + } + else if (selector == "cpp-modules") { + CNMap modules; + qdb_->mergeCollections(Node::Module, modules, relative); + cl = modules.values(); + foreach (CollectionNode* cn, cl) + nl.append(cn); + generateAnnotatedList(relative, marker, nl); + } + else if (selector == "qml-modules") { + CNMap qmlModules; + qdb_->mergeCollections(Node::QmlModule, qmlModules, relative); + cl = qmlModules.values(); + foreach (CollectionNode* cn, cl) + nl.append(cn); + generateAnnotatedList(relative, marker, nl); + } + else { + /* + \generatelist {selector} is only allowed in a + comment where the topic is \group, \module, or + \qmlmodule. + */ + if (!relative || !relative->isCollectionNode()) { + relative->doc().location().warning(tr("\\generatelist {%1} is only allowed in \\group, \\module, and \\qmlmodule comments.").arg(selector)); + return; + } + if (selector == "related") { + Node* n = const_cast<Node*>(relative); + CollectionNode* cn = static_cast<CollectionNode*>(n); + qdb_->mergeCollections(cn); + generateAnnotatedList(cn, marker, cn->members()); + } + else { + Node* n = const_cast<Node*>(relative); + CollectionNode* cn = static_cast<CollectionNode*>(n); + qdb_->mergeCollections(cn); + generateAnnotatedList(cn, marker, cn->members()); } } - // We now list all the pages found that belong to groups. - // If only certain pages were found for a group, but the definition page - // for that group wasn't listed, the list of pages will be intentionally - // incomplete. However, if the group definition page was listed, all the - // pages in that group are listed for completeness. - - if (!docNodeMap.isEmpty()) { - foreach (const QString &groupTitle, groupTitlesMap.keys()) { - const DocNode *groupNode = groupTitlesMap[groupTitle]; +#if 0 + QStringList keys = groups.uniqueKeys(); + foreach (QString key, keys) { + GroupNode* gn = static_cast<GroupNode*>(groups.value(key)); + if (gn) { out() << QString("<h3><a href=\"%1\">%2</a></h3>\n").arg( - linkForNode(groupNode, relative)).arg( - protectEnc(groupNode->fullTitle())); - - if (docNodeMap[groupNode].count() == 0) + linkForNode(gn, relative)).arg( + protectEnc(gn->fullTitle())); +#if 0 + if (gn->members().isEmpty()) continue; - out() << "<ul>\n"; + NodeMap nm; + foreach (Node* member, gn->members()) { + if (member->isInternal() || member->isExample() || member->isExternalPage() || + member->isObsolete()) + continue; + // not interested either in individual (Qt Designer etc.) manual chapters + if (member->links().contains(Node::ContentsLink)) + continue; + QString sortKey = member->fullTitle().toLower(); + if (sortKey.startsWith("the ")) + sortKey.remove(0, 4); + sortKey.replace(singleDigit, "0\\1"); + nm.insert(sortKey, member); + } - foreach (const DocNode *docNode, docNodeMap[groupNode]) { - QString title = docNode->fullTitle(); + out() << "<ul>\n"; + QStringList titles = nm.keys(); + foreach (QString t, titles) { + Node* member = nm.value(t); + QString title = member->fullTitle(); if (title.startsWith("The ")) title.remove(0, 4); - out() << "<li><a href=\"" << linkForNode(docNode, relative) << "\">" + out() << "<li><a href=\"" << linkForNode(member, relative) << "\">" << protectEnc(title) << "</a></li>\n"; } out() << "</ul>\n"; +#endif } } - - if (!uncategorizedNodeMap.isEmpty()) { - out() << QString("<h3>Miscellaneous</h3>\n"); - out() << "<ul>\n"; - foreach (const DocNode *docNode, uncategorizedNodeMap) { - QString title = docNode->fullTitle(); - if (title.startsWith("The ")) - title.remove(0, 4); - out() << "<li><a href=\"" << linkForNode(docNode, relative) << "\">" - << protectEnc(title) << "</a></li>\n"; - } - out() << "</ul>\n"; - } +#endif } void HtmlGenerator::generateSection(const NodeList& nl, @@ -4229,7 +4269,7 @@ void HtmlGenerator::generateManifestFiles() { generateManifestFile("examples", "example"); generateManifestFile("demos", "demo"); - ExampleNode::exampleNodeMap.clear(); + qdb_->exampleNodeMap().clear(); manifestMetaContent.clear(); } @@ -4240,7 +4280,8 @@ void HtmlGenerator::generateManifestFiles() */ void HtmlGenerator::generateManifestFile(QString manifest, QString element) { - if (ExampleNode::exampleNodeMap.isEmpty()) + ExampleNodeMap& exampleNodeMap = qdb_->exampleNodeMap(); + if (exampleNodeMap.isEmpty()) return; QString fileName = manifest +"-manifest.xml"; QFile file(outputDir() + QLatin1Char('/') + fileName); @@ -4251,8 +4292,8 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element) demos = true; bool proceed = false; - ExampleNodeMap::Iterator i = ExampleNode::exampleNodeMap.begin(); - while (i != ExampleNode::exampleNodeMap.end()) { + ExampleNodeMap::Iterator i = exampleNodeMap.begin(); + while (i != exampleNodeMap.end()) { const ExampleNode* en = i.value(); if (demos) { if (en->name().startsWith("demos")) { @@ -4276,8 +4317,8 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element) writer.writeAttribute("module", project); writer.writeStartElement(manifest); - i = ExampleNode::exampleNodeMap.begin(); - while (i != ExampleNode::exampleNodeMap.end()) { + i = exampleNodeMap.begin(); + while (i != exampleNodeMap.end()) { const ExampleNode* en = i.value(); if (demos) { if (!en->name().startsWith("demos")) { @@ -4501,6 +4542,12 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent) break; case Node::Class: break; + case Node::Group: + break; + case Node::Module: + break; + case Node::QmlModule: + break; case Node::Document: switch (child->subType()) { case Node::Example: @@ -4511,10 +4558,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent) break; case Node::Image: break; - case Node::Group: - break; - case Node::Module: - break; case Node::Page: break; case Node::ExternalPage: @@ -4523,8 +4566,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent) break; case Node::QmlBasicType: break; - case Node::QmlModule: - break; case Node::Collision: break; default: |