qdoc: Teach qdoc to use multiple trees (part 3)

With this update, qdoc is now ready for testing
with multiple trees. In making this change to using
multiple trees, it has become clear that qdoc does
not really need trees the way it currently uses them.
Each C++ class or namespace, or QML type is naturally
a tree tree structure, but above that level, what we
currently call a tree in qdoc should really be called
a collection of maps. This change has moved qdoc in
that direction. It remains to replace the Tree class
with a class that encapsulates a set of maps, one for
each major node type. That can be implemented later.

Task-number: QTBUG-35377
Change-Id: I39068a0cb26c01f14ec0e4621742d727efb913bf
Reviewed-by: Martin Smith <martin.smith@digia.com>
This commit is contained in:
Martin Smith 2014-02-24 13:12:08 +01:00 committed by The Qt Project
parent 5fecc6512f
commit a9d75c8eb8
18 changed files with 1703 additions and 1039 deletions

View File

@ -76,7 +76,6 @@ QT_BEGIN_NAMESPACE
QString CodeParser::currentSubDir_; QString CodeParser::currentSubDir_;
QList<CodeParser *> CodeParser::parsers; QList<CodeParser *> CodeParser::parsers;
bool CodeParser::showInternal = false; bool CodeParser::showInternal = false;
QMap<QString,QString> CodeParser::nameToTitle;
/*! /*!
The constructor adds this code parser to the static The constructor adds this code parser to the static
@ -300,49 +299,29 @@ void CodeParser::processCommonMetaCommand(const Location& location,
else if (command == COMMAND_PAGEKEYWORDS) { else if (command == COMMAND_PAGEKEYWORDS) {
node->addPageKeywords(arg.first); node->addPageKeywords(arg.first);
} }
else if (command == COMMAND_SUBTITLE) {
if (node->type() == Node::Document) {
DocNode *dn = static_cast<DocNode *>(node);
dn->setSubTitle(arg.first);
}
else
location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
}
else if (command == COMMAND_THREADSAFE) { else if (command == COMMAND_THREADSAFE) {
node->setThreadSafeness(Node::ThreadSafe); node->setThreadSafeness(Node::ThreadSafe);
} }
else if (command == COMMAND_TITLE) { else if (command == COMMAND_TITLE) {
if (node->type() == Node::Document) { node->setTitle(arg.first);
DocNode *dn = static_cast<DocNode *>(node); if (!node->isDocNode() && !node->isCollectionNode())
dn->setTitle(arg.first); location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
if (dn->subType() == Node::Example) { else if (node->isExample())
ExampleNode::exampleNodeMap.insert(dn->title(),static_cast<ExampleNode*>(dn)); qdb_->addExampleNode(static_cast<ExampleNode*>(node));
} }
nameToTitle.insert(dn->name(),arg.first); else if (command == COMMAND_SUBTITLE) {
} node->setSubTitle(arg.first);
else if (!node->isDocNode() && !node->isCollectionNode())
location.warning(tr("Ignored '\\%1'").arg(COMMAND_TITLE)); location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE));
} }
else if (command == COMMAND_QTVARIABLE) { else if (command == COMMAND_QTVARIABLE) {
if (node->subType() == Node::Module) { node->setQtVariable(arg.first);
DocNode *dn = static_cast<DocNode *>(node); if (!node->isModule() && !node->isQmlModule())
dn->setQtVariable(arg.first); location.warning(tr("Command '\\%1' is only meanigfule in '\\module' and '\\qmlmodule'.")
}
else
location.warning(tr("Command '\\%1' found outside of '\\module'. It can only be used within a module page.")
.arg(COMMAND_QTVARIABLE)); .arg(COMMAND_QTVARIABLE));
} }
} }
/*!
Find the page title given the page \a name and return it.
*/
const QString CodeParser::titleFromName(const QString& name)
{
const QString t = nameToTitle.value(name);
return t;
}
/*! /*!
\internal \internal
*/ */

View File

@ -81,7 +81,6 @@ public:
static CodeParser *parserForLanguage(const QString& language); static CodeParser *parserForLanguage(const QString& language);
static CodeParser *parserForHeaderFile(const QString &filePath); static CodeParser *parserForHeaderFile(const QString &filePath);
static CodeParser *parserForSourceFile(const QString &filePath); static CodeParser *parserForSourceFile(const QString &filePath);
static const QString titleFromName(const QString& name);
static void setLink(Node* node, Node::LinkType linkType, const QString& arg); static void setLink(Node* node, Node::LinkType linkType, const QString& arg);
static const QString& currentOutputSubdirectory() { return currentSubDir_; } static const QString& currentOutputSubdirectory() { return currentSubDir_; }
@ -101,7 +100,6 @@ private:
static QString currentSubDir_; static QString currentSubDir_;
static QList<CodeParser *> parsers; static QList<CodeParser *> parsers;
static bool showInternal; static bool showInternal;
static QMap<QString,QString> nameToTitle;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -458,25 +458,28 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc,
dn->setLocation(doc.startLocation()); dn->setLocation(doc.startLocation());
return dn; return dn;
} }
else if (command == COMMAND_GROUP) {
DocNode* dn = qdb_->addGroup(arg.first);
dn->setLocation(doc.startLocation());
return dn;
}
else if (command == COMMAND_HEADERFILE) { else if (command == COMMAND_HEADERFILE) {
DocNode* dn = new DocNode(qdb_->primaryTreeRoot(), arg.first, Node::HeaderFile, Node::ApiPage); DocNode* dn = new DocNode(qdb_->primaryTreeRoot(), arg.first, Node::HeaderFile, Node::ApiPage);
dn->setLocation(doc.startLocation()); dn->setLocation(doc.startLocation());
return dn; return dn;
} }
else if (command == COMMAND_GROUP) {
GroupNode* gn = qdb_->addGroup(arg.first);
gn->setLocation(doc.startLocation());
gn->markSeen();
return gn;
}
else if (command == COMMAND_MODULE) { else if (command == COMMAND_MODULE) {
DocNode* dn = qdb_->addModule(arg.first); ModuleNode* mn = qdb_->addModule(arg.first);
dn->setLocation(doc.startLocation()); mn->setLocation(doc.startLocation());
return dn; mn->markSeen();
return mn;
} }
else if (command == COMMAND_QMLMODULE) { else if (command == COMMAND_QMLMODULE) {
DocNode* dn = qdb_->addQmlModule(arg.first); QmlModuleNode* qmn = qdb_->addQmlModule(arg.first);
dn->setLocation(doc.startLocation()); qmn->setLocation(doc.startLocation());
return dn; qmn->markSeen();
return qmn;
} }
else if (command == COMMAND_PAGE) { else if (command == COMMAND_PAGE) {
Node::PageType ptype = Node::ArticlePage; Node::PageType ptype = Node::ArticlePage;

View File

@ -671,7 +671,6 @@ GuidMap* DitaXmlGenerator::lookupGuidMap(const QString& fileName)
*/ */
void DitaXmlGenerator::generateDocs() void DitaXmlGenerator::generateDocs()
{ {
qdb_->buildCollections();
if (!runPrepareOnly()) { if (!runPrepareOnly()) {
Generator::generateDocs(); Generator::generateDocs();
generateCollisionPages(); generateCollisionPages();
@ -1013,9 +1012,9 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
break; break;
case Atom::AnnotatedList: case Atom::AnnotatedList:
{ {
DocNode* dn = qdb_->getGroup(atom->string()); GroupNode* gn = qdb_->getGroup(atom->string());
if (dn) if (gn)
generateAnnotatedList(relative, marker, dn->members()); generateAnnotatedList(relative, marker, gn->members());
} }
break; break;
case Atom::GeneratedList: case Atom::GeneratedList:
@ -1032,10 +1031,10 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
QString arg = atom->string().trimmed(); QString arg = atom->string().trimmed();
QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed(); QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed();
QDocDatabase* qdb = QDocDatabase::qdocDB(); QDocDatabase* qdb = QDocDatabase::qdocDB();
DocNode* dn = qdb->findModule(moduleName); ModuleNode* mn = qdb->findModule(moduleName);
if (dn) { if (mn) {
NodeMap m; NodeMap m;
dn->getMemberClasses(m); mn->getMemberClasses(m);
if (!m.isEmpty()) { if (!m.isEmpty()) {
generateAnnotatedList(relative, marker, m); generateAnnotatedList(relative, marker, m);
} }
@ -1084,9 +1083,11 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
generateAnnotatedList(relative, marker, qdb_->getNamespaces()); generateAnnotatedList(relative, marker, qdb_->getNamespaces());
} }
else if (atom->string() == "related") { else if (atom->string() == "related") {
const DocNode *dn = static_cast<const DocNode *>(relative); if (relative && relative->isCollectionNode()) {
if (dn) const CollectionNode* cn = static_cast<const CollectionNode *>(relative);
generateAnnotatedList(dn, marker, dn->members()); if (cn)
generateAnnotatedList(cn, marker, cn->members());
}
} }
break; break;
case Atom::SinceList: case Atom::SinceList:
@ -2263,24 +2264,6 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
writeStartTag(DT_body); writeStartTag(DT_body);
enterSection(QString(), QString()); enterSection(QString(), QString());
if (dn->subType() == Node::Module) {
generateStatus(dn, marker);
NodeMap nm;
dn->getMemberNamespaces(nm);
if (!nm.isEmpty()) {
enterSection("h2","Namespaces");
generateAnnotatedList(dn, marker, nm);
leaveSection();
}
nm.clear();
dn->getMemberClasses(nm);
if (!nm.isEmpty()) {
enterSection("h2","Classes");
generateAnnotatedList(dn, marker, nm);
leaveSection();
}
nm.clear();
}
if (dn->doc().isEmpty()) { if (dn->doc().isEmpty()) {
if (dn->subType() == Node::File) { if (dn->subType() == Node::File) {
@ -2299,16 +2282,8 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
} }
} }
else { else {
if (dn->subType() == Node::Module) {
enterSection(QString(), QString());
generateBody(dn, marker); generateBody(dn, marker);
leaveSection();
}
else {
generateBody(dn, marker);
}
generateAlsoList(dn, marker); generateAlsoList(dn, marker);
generateAnnotatedList(dn, marker, dn->members());
} }
leaveSection(); // </section> leaveSection(); // </section>
if (!writeEndTag()) { // </body> if (!writeEndTag()) { // </body>
@ -2319,6 +2294,61 @@ void DitaXmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
writeEndTag(); // </topic> writeEndTag(); // </topic>
} }
/*!
Generate the DITA XML file for a group, module, or QML module.
*/
void DitaXmlGenerator::generateCollectionNode(CollectionNode* cn, CodeMarker* marker)
{
QList<Section> sections;
QList<Section>::const_iterator s;
QString fullTitle = cn->fullTitle();
generateHeader(cn, fullTitle);
generateBrief(cn, marker); // <shortdesc>
writeProlog(cn);
writeStartTag(DT_body);
enterSection(QString(), QString());
if (cn->isModule()) {
generateStatus(cn, marker);
NodeMap nm;
cn->getMemberNamespaces(nm);
if (!nm.isEmpty()) {
enterSection("h2","Namespaces");
generateAnnotatedList(cn, marker, nm);
leaveSection();
}
nm.clear();
cn->getMemberClasses(nm);
if (!nm.isEmpty()) {
enterSection("h2","Classes");
generateAnnotatedList(cn, marker, nm);
leaveSection();
}
nm.clear();
}
if (!cn->doc().isEmpty()) {
if (cn->isModule()) {
enterSection(QString(), QString());
generateBody(cn, marker);
leaveSection();
}
else {
generateBody(cn, marker);
}
generateAlsoList(cn, marker);
generateAnnotatedList(cn, marker, cn->members());
}
leaveSection(); // </section>
if (!writeEndTag()) { // </body>
cn->doc().location().warning(tr("Pop of empty XML tag stack; generating DITA for '%1'").arg(cn->name()));
return;
}
writeRelatedLinks(cn);
writeEndTag(); // </topic>
}
/*! /*!
This function writes a \e{<link>} element inside a This function writes a \e{<link>} element inside a
\e{<related-links>} element. \e{<related-links>} element.
@ -2350,7 +2380,7 @@ void DitaXmlGenerator::writeLink(const Node* node,
value of the \e role attribute is \c{parent} for the value of the \e role attribute is \c{parent} for the
\c{start} link. \c{start} link.
*/ */
void DitaXmlGenerator::writeRelatedLinks(const DocNode* node) void DitaXmlGenerator::writeRelatedLinks(const Node* node)
{ {
const Node* linkNode = 0; const Node* linkNode = 0;
QPair<QString,QString> linkPair; QPair<QString,QString> linkPair;
@ -2405,12 +2435,9 @@ QString DitaXmlGenerator::fileExtension() const
Writes an XML file header to the current XML stream. This Writes an XML file header to the current XML stream. This
depends on which kind of DITA XML file is being generated, depends on which kind of DITA XML file is being generated,
which is determined by the \a node type and subtype and the which is determined by the \a node type and subtype and the
\a subpage flag. If the \subpage flag is true, a \c{<topic>} \a subpage flag.
header is written, regardless of the type of \a node.
*/ */
void DitaXmlGenerator::generateHeader(const Node* node, void DitaXmlGenerator::generateHeader(const Node* node, const QString& name)
const QString& name,
bool subpage)
{ {
if (!node) if (!node)
return; return;
@ -2423,7 +2450,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
QString version; QString version;
QString outputclass; QString outputclass;
if (node->type() == Node::Class) { if (node->isClass()) {
mainTag = DT_cxxClass; mainTag = DT_cxxClass;
nameTag = DT_apiName; nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd"; dtd = "dtd/cxxClass.dtd";
@ -2432,7 +2459,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
" PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" + " PUBLIC \"-//NOKIA//DTD DITA C++ API Class Reference Type v" +
version + "//EN\" \"" + dtd + "\">"; version + "//EN\" \"" + dtd + "\">";
} }
else if (node->type() == Node::Namespace) { else if (node->isNamespace()) {
mainTag = DT_cxxClass; mainTag = DT_cxxClass;
nameTag = DT_apiName; nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd"; dtd = "dtd/cxxClass.dtd";
@ -2442,8 +2469,28 @@ void DitaXmlGenerator::generateHeader(const Node* node,
version + "//EN\" \"" + dtd + "\">"; version + "//EN\" \"" + dtd + "\">";
outputclass = "namespace"; outputclass = "namespace";
} }
else if (node->type() == Node::Document || subpage) { else if (node->isCollectionNode()) {
if (node->subType() == Node::HeaderFile) { mainTag = DT_topic;
nameTag = DT_title;
dtd = "dtd/topic.dtd";
doctype = "<!DOCTYPE " + ditaTags[mainTag] +
" PUBLIC \"-//OASIS//DTD DITA Topic//EN\" \"" + dtd + "\">";
switch (node->type()) {
case Node::Group:
outputclass = "group";
break;
case Node::Module:
outputclass = "module";
break;
case Node::QmlModule:
outputclass = "qmlmodule";
break;
default:
outputclass = "page";
}
}
else if (node->isDocNode()) {
if (node->isHeaderFile()) {
mainTag = DT_cxxClass; mainTag = DT_cxxClass;
nameTag = DT_apiName; nameTag = DT_apiName;
dtd = "dtd/cxxClass.dtd"; dtd = "dtd/cxxClass.dtd";
@ -2453,7 +2500,7 @@ void DitaXmlGenerator::generateHeader(const Node* node,
version + "//EN\" \"" + dtd + "\">"; version + "//EN\" \"" + dtd + "\">";
outputclass = "headerfile"; outputclass = "headerfile";
} }
else if (node->subType() == Node::QmlClass) { else if (node->isQmlType()) {
mainTag = DT_qmlType; mainTag = DT_qmlType;
nameTag = DT_apiName; nameTag = DT_apiName;
dtd = "dtd/qmlType.dtd"; dtd = "dtd/qmlType.dtd";
@ -2473,9 +2520,6 @@ void DitaXmlGenerator::generateHeader(const Node* node,
case Node::Page: case Node::Page:
outputclass = node->pageTypeString(); outputclass = node->pageTypeString();
break; break;
case Node::Group:
outputclass = "group";
break;
case Node::Example: case Node::Example:
outputclass = "example"; outputclass = "example";
break; break;
@ -2485,9 +2529,6 @@ void DitaXmlGenerator::generateHeader(const Node* node,
case Node::Image: // not used case Node::Image: // not used
outputclass = "image"; outputclass = "image";
break; break;
case Node::Module:
outputclass = "module";
break;
case Node::ExternalPage: // not used case Node::ExternalPage: // not used
outputclass = "externalpage"; outputclass = "externalpage";
break; break;
@ -3106,100 +3147,57 @@ void DitaXmlGenerator::generateQmlItem(const Node* node,
*/ */
void DitaXmlGenerator::generateOverviewList(const Node* relative) void DitaXmlGenerator::generateOverviewList(const Node* relative)
{ {
QMap<const DocNode*, QMap<QString, DocNode*> > docNodeMap; CNMap groups;
QMap<QString, const DocNode*> groupTitlesMap; CNMap modules;
QMap<QString, DocNode*> uncategorizedNodeMap; CNMap qmlModules;
QRegExp singleDigit("\\b([0-9])\\b"); QRegExp singleDigit("\\b([0-9])\\b");
const NodeList children = qdb_->primaryTreeRoot()->childNodes(); qdb_->mergeCollections(Node::Group, groups, relative);
foreach (Node* child, children) { qdb_->mergeCollections(Node::Module, modules, relative);
if (child->type() == Node::Document && child != relative) { qdb_->mergeCollections(Node::QmlModule, qmlModules, relative);
DocNode* docNode = static_cast<DocNode*>(child);
// Check whether the page is part of a group or is the group QStringList keys = groups.uniqueKeys();
// definition page. foreach (QString key, keys) {
QString group; GroupNode* gn = static_cast<GroupNode*>(groups.value(key));
bool isGroupPage = false; if (gn) {
if (docNode->doc().metaCommandsUsed().contains("group")) { writeStartTag(DT_p);
group = docNode->doc().metaCommandArgs("group")[0].first; xmlWriter().writeAttribute("outputclass","h3");
isGroupPage = true; writeStartTag(DT_xref);
} // formathtml
xmlWriter().writeAttribute("href",linkForNode(gn, relative));
writeCharacters(protectEnc(gn->fullTitle()));
writeEndTag(); // </xref>
writeEndTag(); // </p>
// there are too many examples; they would clutter the list if (gn->members().isEmpty())
if (docNode->subType() == Node::Example)
continue; continue;
NodeMap nm;
foreach (Node* member, gn->members()) {
if (member->isInternal() || member->isExample() || member->isExternalPage() ||
member->isObsolete())
continue;
// not interested either in individual (Qt Designer etc.) manual chapters // not interested either in individual (Qt Designer etc.) manual chapters
if (docNode->links().contains(Node::ContentsLink)) if (member->links().contains(Node::ContentsLink))
continue; continue;
QString sortKey = member->fullTitle().toLower();
// Discard external nodes.
if (docNode->subType() == Node::ExternalPage)
continue;
QString sortKey = docNode->fullTitle().toLower();
if (sortKey.startsWith("the ")) if (sortKey.startsWith("the "))
sortKey.remove(0, 4); sortKey.remove(0, 4);
sortKey.replace(singleDigit, "0\\1"); sortKey.replace(singleDigit, "0\\1");
nm.insert(sortKey, member);
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);
}
}
}
}
// 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];
writeStartTag(DT_p);
xmlWriter().writeAttribute("outputclass","h3");
writeStartTag(DT_xref);
// formathtml
xmlWriter().writeAttribute("href",linkForNode(groupNode, relative));
writeCharacters(protectEnc(groupNode->fullTitle()));
writeEndTag(); // </xref>
writeEndTag(); // </p>
if (docNodeMap[groupNode].count() == 0)
continue;
writeStartTag(DT_ul); writeStartTag(DT_ul);
foreach (const DocNode* docNode, docNodeMap[groupNode]) { QStringList titles = nm.keys();
QString title = docNode->fullTitle(); foreach (QString t, titles) {
Node* member = nm.value(t);
QString title = member->fullTitle();
if (title.startsWith("The ")) if (title.startsWith("The "))
title.remove(0, 4); title.remove(0, 4);
writeStartTag(DT_li); writeStartTag(DT_li);
writeStartTag(DT_xref); writeStartTag(DT_xref);
// formathtml // formathtml
xmlWriter().writeAttribute("href",linkForNode(docNode, relative)); xmlWriter().writeAttribute("href",linkForNode(member, relative));
writeCharacters(protectEnc(title)); writeCharacters(protectEnc(title));
writeEndTag(); // </xref> writeEndTag(); // </xref>
writeEndTag(); // </li> writeEndTag(); // </li>
@ -3207,27 +3205,6 @@ void DitaXmlGenerator::generateOverviewList(const Node* relative)
writeEndTag(); // </ul> writeEndTag(); // </ul>
} }
} }
if (!uncategorizedNodeMap.isEmpty()) {
writeStartTag(DT_p);
xmlWriter().writeAttribute("outputclass","h3");
xmlWriter().writeCharacters("Miscellaneous");
writeEndTag(); // </p>
writeStartTag(DT_ul);
foreach (const DocNode *docNode, uncategorizedNodeMap) {
QString title = docNode->fullTitle();
if (title.startsWith("The "))
title.remove(0, 4);
writeStartTag(DT_li);
writeStartTag(DT_xref);
// formathtml
xmlWriter().writeAttribute("href",linkForNode(docNode, relative));
writeCharacters(protectEnc(title));
writeEndTag(); // </xref>
writeEndTag(); // </li>
}
writeEndTag(); // </ul>
}
} }
/*! /*!
@ -3703,13 +3680,12 @@ QString DitaXmlGenerator::guidForNode(const Node* node)
/*! /*!
Constructs a file name appropriate for the \a node and returns Constructs a file name appropriate for the \a node and returns
it. If the \a node is not a fake node, or if it is a fake node but it. If the \a node is not a not an external page, an image, or
it is neither an external page node nor an image node or a ditamap, a ditamap, call fileName() in the base class, Generator.
call the Generator::fileName() function.
*/ */
QString DitaXmlGenerator::fileName(const Node* node) QString DitaXmlGenerator::fileName(const Node* node)
{ {
if (node->type() == Node::Document) { if (node->isDocNode()) {
if (static_cast<const DocNode*>(node)->pageType() == Node::DitaMapPage) if (static_cast<const DocNode*>(node)->pageType() == Node::DitaMapPage)
return node->name(); return node->name();
if (static_cast<const DocNode*>(node)->subType() == Node::ExternalPage) if (static_cast<const DocNode*>(node)->subType() == Node::ExternalPage)
@ -5422,6 +5398,18 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
if (!isDuplicate(nodeTypeMaps[Node::Class],child->name(),child)) if (!isDuplicate(nodeTypeMaps[Node::Class],child->name(),child))
nodeTypeMaps[Node::Class]->insert(child->name(),child); nodeTypeMaps[Node::Class]->insert(child->name(),child);
break; break;
case Node::Group:
if (!isDuplicate(nodeTypeMaps[Node::Group],child->title(),child))
nodeTypeMaps[Node::Group]->insert(child->title(),child);
break;
case Node::Module:
if (!isDuplicate(nodeTypeMaps[Node::Module],child->title(),child))
nodeTypeMaps[Node::Module]->insert(child->title(),child);
break;
case Node::QmlModule:
if (!isDuplicate(nodeTypeMaps[Node::QmlModule],child->title(),child))
nodeTypeMaps[Node::QmlModule]->insert(child->title(),child);
break;
case Node::Document: case Node::Document:
switch (child->subType()) { switch (child->subType()) {
case Node::Example: case Node::Example:
@ -5436,14 +5424,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
break; break;
case Node::Image: case Node::Image:
break; break;
case Node::Group:
if (!isDuplicate(nodeSubtypeMaps[Node::Group],child->title(),child))
nodeSubtypeMaps[Node::Group]->insert(child->title(),child);
break;
case Node::Module:
if (!isDuplicate(nodeSubtypeMaps[Node::Module],child->title(),child))
nodeSubtypeMaps[Node::Module]->insert(child->title(),child);
break;
case Node::Page: case Node::Page:
if (!isDuplicate(pageTypeMaps[child->pageType()],child->title(),child)) if (!isDuplicate(pageTypeMaps[child->pageType()],child->title(),child))
pageTypeMaps[child->pageType()]->insert(child->title(),child); pageTypeMaps[child->pageType()]->insert(child->title(),child);
@ -5460,10 +5440,6 @@ Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
if (!isDuplicate(nodeSubtypeMaps[Node::QmlBasicType],child->title(),child)) if (!isDuplicate(nodeSubtypeMaps[Node::QmlBasicType],child->title(),child))
nodeSubtypeMaps[Node::QmlBasicType]->insert(child->title(),child); nodeSubtypeMaps[Node::QmlBasicType]->insert(child->title(),child);
break; break;
case Node::QmlModule:
if (!isDuplicate(nodeSubtypeMaps[Node::QmlModule],child->title(),child))
nodeSubtypeMaps[Node::QmlModule]->insert(child->title(),child);
break;
case Node::Collision: case Node::Collision:
if (!isDuplicate(nodeSubtypeMaps[Node::Collision],child->title(),child)) if (!isDuplicate(nodeSubtypeMaps[Node::Collision],child->title(),child))
nodeSubtypeMaps[Node::Collision]->insert(child->title(),child); nodeSubtypeMaps[Node::Collision]->insert(child->title(),child);
@ -5567,22 +5543,26 @@ void DitaXmlGenerator::writeDitaMap()
writeTopicrefs(pageTypeMaps[Node::FAQPage], "FAQs"); writeTopicrefs(pageTypeMaps[Node::FAQPage], "FAQs");
writeTopicrefs(pageTypeMaps[Node::ArticlePage], "Articles"); writeTopicrefs(pageTypeMaps[Node::ArticlePage], "Articles");
writeTopicrefs(nodeSubtypeMaps[Node::Example], "Examples"); writeTopicrefs(nodeSubtypeMaps[Node::Example], "Examples");
if (nodeSubtypeMaps[Node::QmlModule]->size() > 1)
writeTopicrefs(nodeSubtypeMaps[Node::QmlModule], "QML modules"); if (nodeTypeMaps[Node::QmlModule]->size() > 1)
if (nodeSubtypeMaps[Node::QmlModule]->size() == 1) writeTopicrefs(nodeTypeMaps[Node::QmlModule], "QML modules");
writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types", nodeSubtypeMaps[Node::QmlModule]->values()[0]);
if (nodeTypeMaps[Node::QmlModule]->size() == 1)
writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types", nodeTypeMaps[Node::QmlModule]->values()[0]);
else else
writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types"); writeTopicrefs(nodeSubtypeMaps[Node::QmlClass], "QML types");
writeTopicrefs(nodeSubtypeMaps[Node::QmlBasicType], "QML basic types"); writeTopicrefs(nodeSubtypeMaps[Node::QmlBasicType], "QML basic types");
if (nodeSubtypeMaps[Node::Module]->size() > 1)
writeTopicrefs(nodeSubtypeMaps[Node::Module], "Modules"); if (nodeTypeMaps[Node::Module]->size() > 1)
if (nodeSubtypeMaps[Node::Module]->size() == 1) writeTopicrefs(nodeTypeMaps[Node::Module], "Modules");
writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes", nodeSubtypeMaps[Node::Module]->values()[0]);
if (nodeTypeMaps[Node::Module]->size() == 1)
writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes", nodeTypeMaps[Node::Module]->values()[0]);
else else
writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes"); writeTopicrefs(nodeTypeMaps[Node::Class], "C++ classes");
writeTopicrefs(nodeTypeMaps[Node::Namespace], "C++ namespaces"); writeTopicrefs(nodeTypeMaps[Node::Namespace], "C++ namespaces");
writeTopicrefs(nodeSubtypeMaps[Node::HeaderFile], "Header files"); writeTopicrefs(nodeSubtypeMaps[Node::HeaderFile], "Header files");
writeTopicrefs(nodeSubtypeMaps[Node::Group], "Groups"); writeTopicrefs(nodeTypeMaps[Node::Group], "Groups");
writeEndTag(); // </topicref> writeEndTag(); // </topicref>
endSubPage(); endSubPage();
@ -5931,6 +5911,12 @@ DitaXmlGenerator::writeProlog(const InnerNode* inner)
category = "Class reference"; category = "Class reference";
else if (inner->type() == Node::Namespace) else if (inner->type() == Node::Namespace)
category = "Namespace"; category = "Namespace";
else if (inner->type() == Node::Module)
category = "Module";
else if (inner->type() == Node::QmlModule)
category = "QML Module";
else if (inner->type() == Node::Group)
category = "Group";
else if (inner->type() == Node::Document) { else if (inner->type() == Node::Document) {
if (inner->subType() == Node::QmlClass) if (inner->subType() == Node::QmlClass)
category = "QML Reference"; category = "QML Reference";
@ -5938,16 +5924,12 @@ DitaXmlGenerator::writeProlog(const InnerNode* inner)
category = "QML Basic Type"; category = "QML Basic Type";
else if (inner->subType() == Node::HeaderFile) else if (inner->subType() == Node::HeaderFile)
category = "Header File"; category = "Header File";
else if (inner->subType() == Node::Module)
category = "Module";
else if (inner->subType() == Node::File) else if (inner->subType() == Node::File)
category = "Example Source File"; category = "Example Source File";
else if (inner->subType() == Node::Example) else if (inner->subType() == Node::Example)
category = "Example"; category = "Example";
else if (inner->subType() == Node::Image) else if (inner->subType() == Node::Image)
category = "Image"; category = "Image";
else if (inner->subType() == Node::Group)
category = "Group";
else if (inner->subType() == Node::Page) else if (inner->subType() == Node::Page)
category = "Page"; category = "Page";
else if (inner->subType() == Node::ExternalPage) else if (inner->subType() == Node::ExternalPage)

View File

@ -316,6 +316,7 @@ protected:
CodeMarker* marker); CodeMarker* marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker); virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateDocNode(DocNode* dn, CodeMarker* marker); virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
virtual QString fileExtension() const; virtual QString fileExtension() const;
virtual QString guidForNode(const Node* node); virtual QString guidForNode(const Node* node);
virtual QString linkForNode(const Node* node, const Node* relative); virtual QString linkForNode(const Node* node, const Node* relative);
@ -349,7 +350,7 @@ protected:
CodeMarker* marker, CodeMarker* marker,
const QString& attribute = QString()); const QString& attribute = QString());
void writePropertyParameter(const QString& tag, const NodeList& nlist); void writePropertyParameter(const QString& tag, const NodeList& nlist);
void writeRelatedLinks(const DocNode* dn); void writeRelatedLinks(const Node* dn);
void writeLink(const Node* node, const QString& tex, const QString& role); void writeLink(const Node* node, const QString& tex, const QString& role);
void writeProlog(const InnerNode* inner); void writeProlog(const InnerNode* inner);
bool writeMetadataElement(const InnerNode* inner, bool writeMetadataElement(const InnerNode* inner,
@ -364,9 +365,7 @@ private:
enum SubTitleSize { SmallSubTitle, LargeSubTitle }; enum SubTitleSize { SmallSubTitle, LargeSubTitle };
const QPair<QString,QString> anchorForNode(const Node* node); const QPair<QString,QString> anchorForNode(const Node* node);
void generateHeader(const Node* node, void generateHeader(const Node* node, const QString& name);
const QString& name,
bool subpage = false);
void generateBrief(const Node* node, CodeMarker* marker); void generateBrief(const Node* node, CodeMarker* marker);
void generateTableOfContents(const Node* node, void generateTableOfContents(const Node* node,
CodeMarker* marker, CodeMarker* marker,

View File

@ -322,7 +322,7 @@ QString Generator::fileBase(const Node *node) const
return node->baseName(); return node->baseName();
QString base; QString base;
if (node->type() == Node::Document) { if (node->isDocNode()) {
base = node->name(); base = node->name();
if (node->subType() == Node::Collision) { if (node->subType() == Node::Collision) {
const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node); const NameCollisionNode* ncn = static_cast<const NameCollisionNode*>(node);
@ -347,12 +347,6 @@ QString Generator::fileBase(const Node *node) const
base.prepend(outputPrefix(QLatin1String("QML"))); base.prepend(outputPrefix(QLatin1String("QML")));
} }
} }
else if (node->subType() == Node::QmlModule) {
base.append("-qmlmodule");
}
else if (node->subType() == Node::Module) {
base.append("-module");
}
if (node->isExample() || node->isExampleFile()) { if (node->isExample() || node->isExampleFile()) {
QString modPrefix(node->moduleName()); QString modPrefix(node->moduleName());
if (modPrefix.isEmpty()) { if (modPrefix.isEmpty()) {
@ -364,6 +358,19 @@ QString Generator::fileBase(const Node *node) const
base.append(QLatin1String("-example")); base.append(QLatin1String("-example"));
} }
} }
else if (node->isCollectionNode()) {
base = node->name();
if (base.endsWith(".html"))
base.truncate(base.length() - 5);
if (node->isQmlModule()) {
base.append("-qmlmodule");
}
else if (node->isModule()) {
base.append("-module");
}
// Why not add "-group" for gropup pages?
}
else { else {
const Node *p = node; const Node *p = node;
forever { forever {
@ -845,6 +852,10 @@ void Generator::generateDocNode(DocNode* /* dn */, CodeMarker* /* marker */)
{ {
} }
void Generator::generateCollectionNode(CollectionNode* , CodeMarker* )
{
}
/*! /*!
This function is called when the documentation for an This function is called when the documentation for an
example is being formatted. It outputs the list of source example is being formatted. It outputs the list of source
@ -1002,20 +1013,50 @@ void Generator::generateInnerNode(InnerNode* node)
later in generateCollisionPages(). Each one is later in generateCollisionPages(). Each one is
appended to a list for later. appended to a list for later.
*/ */
if ((node->type() == Node::Document) && (node->subType() == Node::Collision)) { if (node->isCollisionNode()) {
NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node); NameCollisionNode* ncn = static_cast<NameCollisionNode*>(node);
collisionNodes.append(const_cast<NameCollisionNode*>(ncn)); collisionNodes.append(const_cast<NameCollisionNode*>(ncn));
} }
else { else {
if (node->isNamespace() || node->isClass()) {
beginSubPage(node, fileName(node)); beginSubPage(node, fileName(node));
if (node->type() == Node::Namespace || node->type() == Node::Class) {
generateClassLikeNode(node, marker); generateClassLikeNode(node, marker);
}
else if (node->type() == Node::Document) {
generateDocNode(static_cast<DocNode*>(node), marker);
}
endSubPage(); endSubPage();
} }
else if (node->isDocNode()) {
beginSubPage(node, fileName(node));
generateDocNode(static_cast<DocNode*>(node), marker);
endSubPage();
}
else if (node->isCollectionNode()) {
CollectionNode* cn = static_cast<CollectionNode*>(node);
/*
A collection node is one of: group, module,
or QML module.
Don't output an HTML page for the collection
node unless the \group, \module, or \qmlmodule
command was actually seen by qdoc in the qdoc
comment for the node.
A key prerequisite in this case is the call to
mergeCollections(cn). We don't know if this
collection (group, module, or QML module) has
members in other modules. We know at this point
that cn's members list contains only members in
the current module. Therefore, before outputting
the page for cn, we must search for members of
cn in the other modules and add them to the
members list.
*/
if (cn->wasSeen()) {
qdb_->mergeCollections(cn);
beginSubPage(node, fileName(node));
generateCollectionNode(cn, marker);
endSubPage();
}
}
}
} }
int i = 0; int i = 0;
@ -1923,7 +1964,6 @@ void Generator::terminate()
imageDirs.clear(); imageDirs.clear();
outDir_.clear(); outDir_.clear();
QmlClassNode::terminate(); QmlClassNode::terminate();
ExampleNode::terminate();
} }
void Generator::terminateGenerator() void Generator::terminateGenerator()

View File

@ -110,16 +110,13 @@ protected:
virtual QString fileBase(const Node* node) const; virtual QString fileBase(const Node* node) const;
virtual QString fileExtension() const = 0; virtual QString fileExtension() const = 0;
virtual void generateAlsoList(const Node *node, CodeMarker *marker); virtual void generateAlsoList(const Node *node, CodeMarker *marker);
virtual int generateAtom(const Atom *atom, virtual int generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker);
const Node *relative,
CodeMarker *marker);
virtual void generateBody(const Node *node, CodeMarker *marker); virtual void generateBody(const Node *node, CodeMarker *marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker); virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateDocNode(DocNode* dn, CodeMarker* marker); virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
virtual void generateInheritedBy(const ClassNode *classe, virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
CodeMarker *marker); virtual void generateInheritedBy(const ClassNode *classe, CodeMarker *marker);
virtual void generateInherits(const ClassNode *classe, virtual void generateInherits(const ClassNode *classe, CodeMarker *marker);
CodeMarker *marker);
virtual void generateInnerNode(InnerNode* node); virtual void generateInnerNode(InnerNode* node);
virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker); virtual void generateMaintainerList(const InnerNode* node, CodeMarker* marker);
virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker); virtual void generateQmlInheritedBy(const QmlClassNode* qcn, CodeMarker* marker);
@ -128,9 +125,7 @@ protected:
const Node *relative, const Node *relative,
CodeMarker *marker, CodeMarker *marker,
const QString& qmlName); const QString& qmlName);
virtual bool generateText(const Text& text, virtual bool generateText(const Text& text, const Node *relative, CodeMarker *marker);
const Node *relative,
CodeMarker *marker);
virtual QString imageFileName(const Node *relative, const QString& fileBase); virtual QString imageFileName(const Node *relative, const QString& fileBase);
virtual int skipAtoms(const Atom *atom, Atom::Type type) const; virtual int skipAtoms(const Atom *atom, Atom::Type type) const;
virtual QString typeString(const Node *node); virtual QString typeString(const Node *node);

View File

@ -131,6 +131,9 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
typeHash["function"] = Node::Function; typeHash["function"] = Node::Function;
typeHash["property"] = Node::Property; typeHash["property"] = Node::Property;
typeHash["variable"] = Node::Variable; typeHash["variable"] = Node::Variable;
typeHash["group"] = Node::Group;
typeHash["module"] = Node::Module;
typeHash["qmlmodule"] = Node::QmlModule;
typeHash["qmlproperty"] = Node::QmlProperty; typeHash["qmlproperty"] = Node::QmlProperty;
typeHash["qmlsignal"] = Node::QmlSignal; typeHash["qmlsignal"] = Node::QmlSignal;
typeHash["qmlsignalhandler"] = Node::QmlSignalHandler; typeHash["qmlsignalhandler"] = Node::QmlSignalHandler;
@ -141,8 +144,6 @@ void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList
subTypeHash["example"] = Node::Example; subTypeHash["example"] = Node::Example;
subTypeHash["headerfile"] = Node::HeaderFile; subTypeHash["headerfile"] = Node::HeaderFile;
subTypeHash["file"] = Node::File; subTypeHash["file"] = Node::File;
subTypeHash["group"] = Node::Group;
subTypeHash["module"] = Node::Module;
subTypeHash["page"] = Node::Page; subTypeHash["page"] = Node::Page;
subTypeHash["externalpage"] = Node::ExternalPage; subTypeHash["externalpage"] = Node::ExternalPage;
subTypeHash["qmlclass"] = Node::QmlClass; subTypeHash["qmlclass"] = Node::QmlClass;
@ -316,6 +317,34 @@ bool HelpProjectWriter::generateSection(HelpProject &project,
} }
break; break;
case Node::Group:
case Node::Module:
case Node::QmlModule:
{
const CollectionNode* cn = static_cast<const CollectionNode*>(node);
if (!cn->fullTitle().isEmpty()) {
if (cn->doc().hasKeywords()) {
foreach (const Atom* keyword, cn->doc().keywords()) {
if (!keyword->string().isEmpty()) {
QStringList details;
details << keyword->string()
<< keyword->string()
<< gen_->fullDocumentLocation(node, Generator::useOutputSubdirs()) +
QLatin1Char('#') + Doc::canonicalTitle(keyword->string());
project.keywords.append(details);
}
else
cn->doc().location().warning(
tr("Bad keyword in %1").arg(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()))
);
}
}
project.keywords.append(keywordDetails(node));
project.files.insert(gen_->fullDocumentLocation(node,Generator::useOutputSubdirs()));
}
}
break;
case Node::Property: case Node::Property:
case Node::QmlProperty: case Node::QmlProperty:
case Node::QmlSignal: case Node::QmlSignal:
@ -601,6 +630,17 @@ void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer
writer.writeEndElement(); // section writer.writeEndElement(); // section
} }
break; break;
case Node::Group:
case Node::Module:
case Node::QmlModule:
{
const CollectionNode* cn = static_cast<const CollectionNode*>(node);
writer.writeStartElement("section");
writer.writeAttribute("ref", href);
writer.writeAttribute("title", cn->fullTitle());
writer.writeEndElement(); // section
}
break;
default: default:
; ;
} }

View File

@ -268,7 +268,6 @@ QString HtmlGenerator::format()
*/ */
void HtmlGenerator::generateDocs() void HtmlGenerator::generateDocs()
{ {
qdb_->buildCollections();
Node* qflags = qdb_->findNodeByNameAndType(QStringList("QFlags"), Node::Class, Node::NoSubType); Node* qflags = qdb_->findNodeByNameAndType(QStringList("QFlags"), Node::Class, Node::NoSubType);
if (qflags) if (qflags)
qflagsHref_ = linkForNode(qflags,0); qflagsHref_ = linkForNode(qflags,0);
@ -488,9 +487,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
break; break;
case Atom::AnnotatedList: case Atom::AnnotatedList:
{ {
DocNode* dn = qdb_->getGroup(atom->string()); GroupNode* gn = qdb_->getGroup(atom->string());
if (dn) if (gn)
generateAnnotatedList(relative, marker, dn->members()); generateList(gn, marker, atom->string());
} }
break; break;
case Atom::GeneratedList: case Atom::GeneratedList:
@ -507,10 +506,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
QString arg = atom->string().trimmed(); QString arg = atom->string().trimmed();
QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed(); QString moduleName = atom->string().mid(atom->string().indexOf("classesbymodule") + 15).trimmed();
QDocDatabase* qdb = QDocDatabase::qdocDB(); QDocDatabase* qdb = QDocDatabase::qdocDB();
DocNode* dn = qdb->findModule(moduleName); ModuleNode* mn = qdb->findModule(moduleName);
if (dn) { if (mn) {
NodeMap m; NodeMap m;
dn->getMemberClasses(m); mn->getMemberClasses(m);
if (!m.isEmpty()) { if (!m.isEmpty()) {
generateAnnotatedList(relative, marker, m); 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")); generateCompactList(Generic, relative, qdb_->getServiceClasses(), false, QStringLiteral("Q"));
} }
else if (atom->string() == "overviews") { 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") { else if (atom->string() == "namespaces") {
generateAnnotatedList(relative, marker, qdb_->getNamespaces()); generateAnnotatedList(relative, marker, qdb_->getNamespaces());
} }
else if (atom->string() == "related") { else if (atom->string() == "related") {
const DocNode *dn = static_cast<const DocNode *>(relative); generateList(relative, marker, "related");
if (dn)
generateAnnotatedList(dn, marker, dn->members());
} }
#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") { else if (atom->string() == "relatedinline") {
const DocNode *dn = static_cast<const DocNode *>(relative); const DocNode *dn = static_cast<const DocNode *>(relative);
if (dn && !dn->members().isEmpty()) { if (dn && !dn->members().isEmpty()) {
@ -576,6 +584,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
generateBody(node, marker); generateBody(node, marker);
} }
} }
#endif
break; break;
case Atom::SinceList: case Atom::SinceList:
{ {
@ -1473,29 +1482,7 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
dn, dn,
marker); marker);
if (dn->subType() == Node::Module) { if (dn->subType() == Node::HeaderFile) {
// 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) {
// Generate brief text and status for modules. // Generate brief text and status for modules.
generateBrief(dn, marker); generateBrief(dn, marker);
generateStatus(dn, marker); generateStatus(dn, marker);
@ -1584,28 +1571,14 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
++s; ++s;
} }
Text brief = dn->doc().briefText();
if (dn->subType() == Node::Module && !brief.isEmpty()) {
generateExtractionMark(dn, 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(dn, DetailedDescriptionMark);
out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504 out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
}
generateBody(dn, marker); generateBody(dn, marker);
out() << "</div>\n"; // QTBUG-9504 out() << "</div>\n"; // QTBUG-9504
generateAlsoList(dn, marker); generateAlsoList(dn, marker);
generateExtractionMark(dn, EndMark); generateExtractionMark(dn, EndMark);
if ((dn->subType() == Node::Group))
generateAnnotatedList(dn, marker, dn->members());
else if (dn->subType() == Node::QmlModule)
generateAnnotatedList(dn, marker, dn->members());
sections = marker->sections(dn, CodeMarker::Detailed, CodeMarker::Okay); sections = marker->sections(dn, CodeMarker::Detailed, CodeMarker::Okay);
s = sections.constBegin(); s = sections.constBegin();
while (s != sections.constEnd()) { while (s != sections.constEnd()) {
@ -1622,6 +1595,91 @@ void HtmlGenerator::generateDocNode(DocNode* dn, CodeMarker* marker)
generateFooter(dn); 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(cn, DetailedDescriptionMark);
out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
}
generateBody(cn, marker);
out() << "</div>\n"; // QTBUG-9504
generateAlsoList(cn, marker);
generateExtractionMark(cn, EndMark);
if (cn->isGroup())
generateAnnotatedList(cn, marker, cn->members());
else if (cn->isQmlModule())
generateAnnotatedList(cn, marker, cn->members());
sections = marker->sections(cn, 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, cn, marker);
++m;
}
++s;
}
generateFooter(cn);
}
/*! /*!
Returns "html" for this subclass of Generator. Returns "html" for this subclass of Generator.
*/ */
@ -1895,7 +1953,7 @@ void HtmlGenerator::generateRequisites(InnerNode *inner, CodeMarker *marker)
if (inner->type() == Node::Class || inner->type() == Node::Namespace) { if (inner->type() == Node::Class || inner->type() == Node::Namespace) {
//add the QT variable to the map //add the QT variable to the map
if (!inner->moduleName().isEmpty()) { if (!inner->moduleName().isEmpty()) {
DocNode * moduleNode = qdb_->findModule(inner->moduleName()); ModuleNode* moduleNode = qdb_->findModule(inner->moduleName());
if (moduleNode && !moduleNode->qtVariable().isEmpty()) { if (moduleNode && !moduleNode->qtVariable().isEmpty()) {
text.clear(); text.clear();
text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_TELETYPE) 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 //add the module name and version to the map
QString qmlModuleVersion; QString qmlModuleVersion;
DocNode* dn = qdb_->findQmlModule(qcn->qmlModuleName()); QmlModuleNode* qmn = qdb_->findQmlModule(qcn->qmlModuleName());
if (dn) if (qmn)
qmlModuleVersion = dn->qmlModuleVersion(); qmlModuleVersion = qmn->qmlModuleVersion();
else else
qmlModuleVersion = qcn->qmlModuleVersion(); qmlModuleVersion = qcn->qmlModuleVersion();
text.clear(); text.clear();
@ -2141,7 +2199,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
QList<Atom*> toc; QList<Atom*> toc;
if (node->doc().hasTableOfContents()) if (node->doc().hasTableOfContents())
toc = node->doc().tableOfContents(); toc = node->doc().tableOfContents();
if (toc.isEmpty() && !sections && (node->subType() != Node::Module)) if (toc.isEmpty() && !sections && !node->isModule())
return; return;
QStringList sectionNumber; QStringList sectionNumber;
@ -2156,7 +2214,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
sectionNumber.append("1"); sectionNumber.append("1");
out() << "<ul>\n"; out() << "<ul>\n";
if (node->subType() == Node::Module) { if (node->isModule()) {
if (node->hasNamespaces()) { if (node->hasNamespaces()) {
out() << "<li class=\"level" out() << "<li class=\"level"
<< sectionNumber.size() << sectionNumber.size()
@ -2183,9 +2241,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
} }
} }
} }
else if (sections && ((node->type() == Node::Class) || else if (sections && (node->isClass() || node->isNamespace() || node->isQmlType())) {
(node->type() == Node::Namespace) ||
(node->subType() == Node::QmlClass))) {
QList<Section>::ConstIterator s = sections->constBegin(); QList<Section>::ConstIterator s = sections->constBegin();
while (s != sections->constEnd()) { while (s != sections->constEnd()) {
if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) { if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) {
@ -2453,7 +2509,7 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, NodeMap& classM
NodeMap newTop; NodeMap newTop;
foreach (const RelatedClass &d, child->derivedClasses()) { 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_); newTop.insert(d.node_->name(), d.node_);
} }
if (!newTop.isEmpty()) { if (!newTop.isEmpty()) {
@ -2474,33 +2530,29 @@ void HtmlGenerator::generateAnnotatedList(const Node* relative,
{ {
if (nodeMap.isEmpty()) if (nodeMap.isEmpty())
return; return;
NodeList nl; generateAnnotatedList(relative, marker, nodeMap.values());
NodeMap::const_iterator i = nodeMap.begin();
while (i != nodeMap.end()) {
nl.append(i.value());
++i;
}
generateAnnotatedList(relative, marker, nl);
} }
/*!
*/
void HtmlGenerator::generateAnnotatedList(const Node *relative, void HtmlGenerator::generateAnnotatedList(const Node *relative,
CodeMarker *marker, CodeMarker *marker,
const NodeList& nodes) const NodeList& unsortedNodes)
{ {
NodeMap nm;
bool allInternal = true; bool allInternal = true;
foreach (const Node* node, nodes) { foreach (Node* node, unsortedNodes) {
if (!node->isInternal() && node->status() != Node::Obsolete) { if (!node->isInternal() && !node->isObsolete()) {
allInternal = false; allInternal = false;
nm.insert(node->fullName(relative), node);
} }
} }
if (allInternal) if (allInternal)
return; return;
out() << "<table class=\"annotated\">\n"; out() << "<table class=\"annotated\">\n";
int row = 0; int row = 0;
NodeList nodes = nm.values();
foreach (const Node* node, nodes) { foreach (const Node* node, nodes) {
if (node->isInternal() || node->status() == Node::Obsolete)
continue;
if (++row % 2 == 1) if (++row % 2 == 1)
out() << "<tr class=\"odd topAlign\">"; out() << "<tr class=\"odd topAlign\">";
else else
@ -2509,7 +2561,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative,
generateFullName(node, relative); generateFullName(node, relative);
out() << "</p></td>"; out() << "</p></td>";
if (!(node->type() == Node::Document)) { if (!node->isDocNode()) {
Text brief = node->doc().trimmedBriefText(node->name()); Text brief = node->doc().trimmedBriefText(node->name());
if (!brief.isEmpty()) { if (!brief.isEmpty()) {
out() << "<td class=\"tblDescr\"><p>"; out() << "<td class=\"tblDescr\"><p>";
@ -2794,114 +2846,102 @@ void HtmlGenerator::generateQmlItem(const Node *node,
out() << highlightedCode(marked, relative, false); 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; NodeList nl;
QMap<QString, const DocNode *> groupTitlesMap; CollectionList cl;
QMap<QString, DocNode *> uncategorizedNodeMap;
QRegExp singleDigit("\\b([0-9])\\b"); QRegExp singleDigit("\\b([0-9])\\b");
const NodeList children = qdb_->primaryTreeRoot()->childNodes(); if (selector == "overviews") {
foreach (Node *child, children) { CNMap groups;
if (child->type() == Node::Document && child != relative) { qdb_->mergeCollections(Node::Group, groups, relative);
DocNode *docNode = static_cast<DocNode *>(child); cl = groups.values();
foreach (CollectionNode* cn, cl)
// Check whether the page is part of a group or is the group nl.append(cn);
// definition page. generateAnnotatedList(relative, marker, nl);
QString group;
bool isGroupPage = false;
if (docNode->doc().metaCommandsUsed().contains("group")) {
group = docNode->doc().metaCommandArgs("group")[0].first;
isGroupPage = true;
} }
else if (selector == "cpp-modules") {
// there are too many examples; they would clutter the list CNMap modules;
if (docNode->subType() == Node::Example) qdb_->mergeCollections(Node::Module, modules, relative);
continue; cl = modules.values();
foreach (CollectionNode* cn, cl)
// not interested either in individual (Qt Designer etc.) manual chapters nl.append(cn);
if (docNode->links().contains(Node::ContentsLink)) generateAnnotatedList(relative, marker, nl);
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 (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;
} }
else if (!isGroupPage) { if (selector == "related") {
// If we encounter a page that belongs to a group then Node* n = const_cast<Node*>(relative);
// we add that page to the list for that group. CollectionNode* cn = static_cast<CollectionNode*>(n);
const DocNode* gn = qdb_->getGroup(group); qdb_->mergeCollections(cn);
if (gn && !docNode->isInternal()) generateAnnotatedList(cn, marker, cn->members());
docNodeMap[gn].insert(sortKey, docNode);
}
} }
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 0
// If only certain pages were found for a group, but the definition page QStringList keys = groups.uniqueKeys();
// for that group wasn't listed, the list of pages will be intentionally foreach (QString key, keys) {
// incomplete. However, if the group definition page was listed, all the GroupNode* gn = static_cast<GroupNode*>(groups.value(key));
// pages in that group are listed for completeness. if (gn) {
if (!docNodeMap.isEmpty()) {
foreach (const QString &groupTitle, groupTitlesMap.keys()) {
const DocNode *groupNode = groupTitlesMap[groupTitle];
out() << QString("<h3><a href=\"%1\">%2</a></h3>\n").arg( out() << QString("<h3><a href=\"%1\">%2</a></h3>\n").arg(
linkForNode(groupNode, relative)).arg( linkForNode(gn, relative)).arg(
protectEnc(groupNode->fullTitle())); protectEnc(gn->fullTitle()));
#if 0
if (docNodeMap[groupNode].count() == 0) if (gn->members().isEmpty())
continue; 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]) { out() << "<ul>\n";
QString title = docNode->fullTitle(); QStringList titles = nm.keys();
foreach (QString t, titles) {
Node* member = nm.value(t);
QString title = member->fullTitle();
if (title.startsWith("The ")) if (title.startsWith("The "))
title.remove(0, 4); title.remove(0, 4);
out() << "<li><a href=\"" << linkForNode(docNode, relative) << "\">" out() << "<li><a href=\"" << linkForNode(member, relative) << "\">"
<< protectEnc(title) << "</a></li>\n"; << protectEnc(title) << "</a></li>\n";
} }
out() << "</ul>\n"; out() << "</ul>\n";
#endif
} }
} }
#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";
}
} }
void HtmlGenerator::generateSection(const NodeList& nl, void HtmlGenerator::generateSection(const NodeList& nl,
@ -4229,7 +4269,7 @@ void HtmlGenerator::generateManifestFiles()
{ {
generateManifestFile("examples", "example"); generateManifestFile("examples", "example");
generateManifestFile("demos", "demo"); generateManifestFile("demos", "demo");
ExampleNode::exampleNodeMap.clear(); qdb_->exampleNodeMap().clear();
manifestMetaContent.clear(); manifestMetaContent.clear();
} }
@ -4240,7 +4280,8 @@ void HtmlGenerator::generateManifestFiles()
*/ */
void HtmlGenerator::generateManifestFile(QString manifest, QString element) void HtmlGenerator::generateManifestFile(QString manifest, QString element)
{ {
if (ExampleNode::exampleNodeMap.isEmpty()) ExampleNodeMap& exampleNodeMap = qdb_->exampleNodeMap();
if (exampleNodeMap.isEmpty())
return; return;
QString fileName = manifest +"-manifest.xml"; QString fileName = manifest +"-manifest.xml";
QFile file(outputDir() + QLatin1Char('/') + fileName); QFile file(outputDir() + QLatin1Char('/') + fileName);
@ -4251,8 +4292,8 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
demos = true; demos = true;
bool proceed = false; bool proceed = false;
ExampleNodeMap::Iterator i = ExampleNode::exampleNodeMap.begin(); ExampleNodeMap::Iterator i = exampleNodeMap.begin();
while (i != ExampleNode::exampleNodeMap.end()) { while (i != exampleNodeMap.end()) {
const ExampleNode* en = i.value(); const ExampleNode* en = i.value();
if (demos) { if (demos) {
if (en->name().startsWith("demos")) { if (en->name().startsWith("demos")) {
@ -4276,8 +4317,8 @@ void HtmlGenerator::generateManifestFile(QString manifest, QString element)
writer.writeAttribute("module", project); writer.writeAttribute("module", project);
writer.writeStartElement(manifest); writer.writeStartElement(manifest);
i = ExampleNode::exampleNodeMap.begin(); i = exampleNodeMap.begin();
while (i != ExampleNode::exampleNodeMap.end()) { while (i != exampleNodeMap.end()) {
const ExampleNode* en = i.value(); const ExampleNode* en = i.value();
if (demos) { if (demos) {
if (!en->name().startsWith("demos")) { if (!en->name().startsWith("demos")) {
@ -4501,6 +4542,12 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break; break;
case Node::Class: case Node::Class:
break; break;
case Node::Group:
break;
case Node::Module:
break;
case Node::QmlModule:
break;
case Node::Document: case Node::Document:
switch (child->subType()) { switch (child->subType()) {
case Node::Example: case Node::Example:
@ -4511,10 +4558,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break; break;
case Node::Image: case Node::Image:
break; break;
case Node::Group:
break;
case Node::Module:
break;
case Node::Page: case Node::Page:
break; break;
case Node::ExternalPage: case Node::ExternalPage:
@ -4523,8 +4566,6 @@ void HtmlGenerator::reportOrphans(const InnerNode* parent)
break; break;
case Node::QmlBasicType: case Node::QmlBasicType:
break; break;
case Node::QmlModule:
break;
case Node::Collision: case Node::Collision:
break; break;
default: default:

View File

@ -103,6 +103,7 @@ protected:
CodeMarker *marker); CodeMarker *marker);
virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker); virtual void generateClassLikeNode(InnerNode* inner, CodeMarker* marker);
virtual void generateDocNode(DocNode* dn, CodeMarker* marker); virtual void generateDocNode(DocNode* dn, CodeMarker* marker);
virtual void generateCollectionNode(CollectionNode* cn, CodeMarker* marker);
virtual QString fileExtension() const; virtual QString fileExtension() const;
virtual QString refForNode(const Node *node); virtual QString refForNode(const Node *node);
virtual QString linkForNode(const Node *node, const Node *relative); virtual QString linkForNode(const Node *node, const Node *relative);
@ -167,7 +168,7 @@ private:
QString commonPrefix); QString commonPrefix);
void generateFunctionIndex(const Node *relative); void generateFunctionIndex(const Node *relative);
void generateLegaleseList(const Node *relative, CodeMarker *marker); void generateLegaleseList(const Node *relative, CodeMarker *marker);
void generateOverviewList(const Node *relative); void generateList(const Node* relative, CodeMarker* marker, const QString& selector);
void generateSectionList(const Section& section, void generateSectionList(const Section& section,
const Node *relative, const Node *relative,
CodeMarker *marker, CodeMarker *marker,

View File

@ -50,7 +50,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
int Node::propertyGroupCount_ = 0; int Node::propertyGroupCount_ = 0;
ExampleNodeMap ExampleNode::exampleNodeMap;
QStringMap Node::operators_; QStringMap Node::operators_;
/*! /*!
@ -127,14 +126,14 @@ QString Node::plainFullName(const Node* relative) const
*/ */
QString Node::fullName(const Node* relative) const QString Node::fullName(const Node* relative) const
{ {
if (type() == Node::Document) { if (isDocNode() || isCollectionNode()) {
const DocNode* dn = static_cast<const DocNode*>(this); const DocNode* dn = static_cast<const DocNode*>(this);
// Only print modulename::type on collision pages. // Only print modulename::type on collision pages.
if (!dn->qmlModuleName().isEmpty() && relative != 0 && relative->isCollisionNode()) if (!dn->qmlModuleName().isEmpty() && relative != 0 && relative->isCollisionNode())
return dn->qmlModuleName() + "::" + dn->title(); return dn->qmlModuleName() + "::" + dn->title();
return dn->title(); return dn->title();
} }
else if (type() == Node::Class) { else if (isClass()) {
const ClassNode* cn = static_cast<const ClassNode*>(this); const ClassNode* cn = static_cast<const ClassNode*>(this);
if (!cn->serviceName().isEmpty()) if (!cn->serviceName().isEmpty())
return cn->serviceName(); return cn->serviceName();
@ -195,7 +194,6 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
pageType_(NoPageType), pageType_(NoPageType),
status_(Commendable), status_(Commendable),
indexNodeFlag_(false), indexNodeFlag_(false),
seen_(true),
parent_(parent), parent_(parent),
relatesTo_(0), relatesTo_(0),
name_(name) name_(name)
@ -249,21 +247,13 @@ Node::Node(Type type, InnerNode *parent, const QString& name)
} }
} }
/*! /*! \fn QString Node::url() const
Returns the node's URL. Returns the node's URL.
*/ */
QString Node::url() const
{
return url_;
}
/*! /*! \fn void Node::setUrl(const QString &url)
Sets the node's URL to \a url Sets the node's URL to \a url
*/ */
void Node::setUrl(const QString &url)
{
url_ = url;
}
/*! /*!
Returns this node's page type as a string, for use as an Returns this node's page type as a string, for use as an
@ -334,6 +324,12 @@ QString Node::nodeTypeString(unsigned t)
return "property"; return "property";
case Variable: case Variable:
return "variable"; return "variable";
case Group:
return "group";
case Module:
return "module";
case QmlModule:
return "QML module";
case QmlProperty: case QmlProperty:
return "QML property"; return "QML property";
case QmlPropertyGroup: case QmlPropertyGroup:
@ -376,10 +372,6 @@ QString Node::nodeSubtypeString(unsigned t)
return "file"; return "file";
case Image: case Image:
return "image"; return "image";
case Group:
return "group";
case Module:
return "module";
case Page: case Page:
return "page"; return "page";
case ExternalPage: case ExternalPage:
@ -388,8 +380,6 @@ QString Node::nodeSubtypeString(unsigned t)
return "QML type"; return "QML type";
case QmlBasicType: case QmlBasicType:
return "QML basic type"; return "QML basic type";
case QmlModule:
return "QML module";
case DitaMap: case DitaMap:
return "ditamap"; return "ditamap";
case Collision: case Collision:
@ -678,86 +668,6 @@ InnerNode::~InnerNode()
removeFromRelated(); removeFromRelated();
} }
/*!
Returns \c true if this node's members coolection is not empty.
*/
bool InnerNode::hasMembers() const
{
return !members_.isEmpty();
}
/*!
Appends \a node to the members list, if and only if it
isn't already in the members list.
*/
void InnerNode::addMember(Node* node)
{
if (!members_.contains(node))
members_.append(node);
}
/*!
Returns \c true if this node's members collection contains at
least one namespace node.
*/
bool InnerNode::hasNamespaces() const
{
if (!members_.isEmpty()) {
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isNamespace())
return true;
++i;
}
}
return false;
}
/*!
Returns \c true if this node's members collection contains at
least one class node.
*/
bool InnerNode::hasClasses() const
{
if (!members_.isEmpty()) {
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isClass())
return true;
++i;
}
}
return false;
}
/*!
Loads \a out with all this node's member nodes that are namespace nodes.
*/
void InnerNode::getMemberNamespaces(NodeMap& out)
{
out.clear();
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isNamespace())
out.insert((*i)->name(),(*i));
++i;
}
}
/*!
Loads \a out with all this node's member nodes that are class nodes.
*/
void InnerNode::getMemberClasses(NodeMap& out)
{
out.clear();
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isClass())
out.insert((*i)->name(),(*i));
++i;
}
}
/*! /*!
Find the node in this node's children that has the Find the node in this node's children that has the
given \a name. If this node is a QML class node, be given \a name. If this node is a QML class node, be
@ -1492,6 +1402,15 @@ void ClassNode::addResolvedBaseClass(Access access, ClassNode* node)
node->derived_.append(RelatedClass(access, this)); node->derived_.append(RelatedClass(access, this));
} }
/*!
Adds the derived class \a node to this class's list of derived
classes. The derived class inherits this class with \a access.
*/
void ClassNode::addDerivedClass(Access access, ClassNode* node)
{
derived_.append(RelatedClass(access, node));
}
/*! /*!
Add an unresolved base class to this class node's list of Add an unresolved base class to this class node's list of
base classes. The unresolved base class will be resolved base classes. The unresolved base class will be resolved
@ -1656,13 +1575,6 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node::
case DitaMap: case DitaMap:
setPageType(ptype); setPageType(ptype);
break; break;
case Module:
case Group:
setPageType(OverviewPage);
break;
case QmlModule:
setPageType(OverviewPage);
break;
case QmlClass: case QmlClass:
case QmlBasicType: case QmlBasicType:
setPageType(ApiPage); setPageType(ApiPage);
@ -1678,13 +1590,9 @@ DocNode::DocNode(InnerNode* parent, const QString& name, SubType subtype, Node::
} }
} }
/*! /*! \fn QString DocNode::title() const
Returns the document node's title. This is used for the page title. Returns the document node's title. This is used for the page title.
*/ */
QString DocNode::title() const
{
return title_;
}
/*! /*!
Sets the document node's \a title. This is used for the page title. Sets the document node's \a title. This is used for the page title.
@ -1743,16 +1651,6 @@ QString DocNode::subTitle() const
return QString(); return QString();
} }
/*!
The constructor calls the DocNode constructor with
\a parent, \a name, and Node::Example.
*/
ExampleNode::ExampleNode(InnerNode* parent, const QString& name)
: DocNode(parent, name, Node::Example, Node::ExamplePage)
{
// nothing
}
/*! /*!
\class EnumNode \class EnumNode
*/ */
@ -2857,8 +2755,6 @@ QString Node::idForNode() const
str = "qml-class-" + name(); str = "qml-class-" + name();
break; break;
case Node::Page: case Node::Page:
case Node::Group:
case Node::Module:
case Node::HeaderFile: case Node::HeaderFile:
str = title(); str = title();
if (str.isEmpty()) { if (str.isEmpty()) {
@ -2879,9 +2775,6 @@ QString Node::idForNode() const
case Node::QmlBasicType: case Node::QmlBasicType:
str = "qml-basic-type-" + name(); str = "qml-basic-type-" + name();
break; break;
case Node::QmlModule:
str = "qml-module-" + name();
break;
case Node::Collision: case Node::Collision:
str = title(); str = title();
str.replace(": ","-"); str.replace(": ","-");
@ -2893,6 +2786,19 @@ QString Node::idForNode() const
} }
} }
break; break;
case Node::Group:
case Node::Module:
str = title();
if (str.isEmpty()) {
str = name();
if (str.endsWith(".html"))
str.remove(str.size()-5,5);
}
str.replace(QLatin1Char('/'), QLatin1Char('-'));
break;
case Node::QmlModule:
str = "qml-module-" + name();
break;
case Node::QmlProperty: case Node::QmlProperty:
str = "qml-property-" + name(); str = "qml-property-" + name();
break; break;
@ -2953,10 +2859,93 @@ void InnerNode::printChildren(const QString& title)
} }
/*! /*!
Prints the inner node's list of members. Returns \c true if the collection node's member list is
not empty.
*/
bool CollectionNode::hasMembers() const
{
return !members_.isEmpty();
}
/*!
Appends \a node to the collection node's member list, if
and only if it isn't already in the member list.
*/
void CollectionNode::addMember(Node* node)
{
if (!members_.contains(node))
members_.append(node);
}
/*!
Returns \c true if this collection node contains at least
one namespace node.
*/
bool CollectionNode::hasNamespaces() const
{
if (!members_.isEmpty()) {
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isNamespace())
return true;
++i;
}
}
return false;
}
/*!
Returns \c true if this collection node contains at least
one class node.
*/
bool CollectionNode::hasClasses() const
{
if (!members_.isEmpty()) {
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isClass())
return true;
++i;
}
}
return false;
}
/*!
Loads \a out with all this collection node's members that
are namespace nodes.
*/
void CollectionNode::getMemberNamespaces(NodeMap& out)
{
out.clear();
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isNamespace())
out.insert((*i)->name(),(*i));
++i;
}
}
/*!
Loads \a out with all this collection node's members that
are class nodes.
*/
void CollectionNode::getMemberClasses(NodeMap& out)
{
out.clear();
NodeList::const_iterator i = members_.begin();
while (i != members_.end()) {
if ((*i)->isClass())
out.insert((*i)->name(),(*i));
++i;
}
}
/*!
Prints the collection node's list of members.
For debugging only. For debugging only.
*/ */
void InnerNode::printMembers(const QString& title) void CollectionNode::printMembers(const QString& title)
{ {
qDebug() << title << name() << members_.size(); qDebug() << title << name() << members_.size();
if (members_.size() > 0) { if (members_.size() > 0) {
@ -2967,4 +2956,13 @@ void InnerNode::printMembers(const QString& title)
} }
} }
/*!
Sets the document node's \a title. This is used for the page title.
*/
void CollectionNode::setTitle(const QString& title)
{
title_ = title;
parent()->addChild(this, title);
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -55,21 +55,27 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class Node; class Node;
class EnumNode;
class ClassNode; class ClassNode;
class InnerNode; class InnerNode;
class ExampleNode; class ExampleNode;
class TypedefNode;
class QmlClassNode; class QmlClassNode;
class QDocDatabase; class QDocDatabase;
class FunctionNode;
class PropertyNode;
class QmlModuleNode; class QmlModuleNode;
class CollectionNode;
class QmlPropertyNode; class QmlPropertyNode;
class NameCollisionNode;
typedef QList<Node*> NodeList; typedef QList<Node*> NodeList;
typedef QMap<QString, Node*> NodeMap; typedef QMap<QString, Node*> NodeMap;
typedef QMultiMap<QString, Node*> NodeMultiMap; typedef QMultiMap<QString, Node*> NodeMultiMap;
typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
typedef QPair<int, int> NodeTypePair; typedef QPair<int, int> NodeTypePair;
typedef QList<NodeTypePair> NodeTypeList; typedef QList<NodeTypePair> NodeTypeList;
typedef QMap<QString, CollectionNode*> CNMap;
typedef QMultiMap<QString, CollectionNode*> CNMultiMap;
class Node class Node
{ {
@ -85,6 +91,9 @@ public:
Function, Function,
Property, Property,
Variable, Variable,
Group,
Module,
QmlModule,
QmlPropertyGroup, QmlPropertyGroup,
QmlProperty, QmlProperty,
QmlSignal, QmlSignal,
@ -99,13 +108,10 @@ public:
HeaderFile, HeaderFile,
File, File,
Image, Image,
Group,
Module,
Page, Page,
ExternalPage, ExternalPage,
QmlClass, QmlClass,
QmlBasicType, QmlBasicType,
QmlModule,
DitaMap, DitaMap,
Collision, Collision,
LastSubtype LastSubtype
@ -184,8 +190,7 @@ public:
void setSince(const QString &since); void setSince(const QString &since);
void setRelates(InnerNode* pseudoParent); void setRelates(InnerNode* pseudoParent);
void setModuleName(const QString &name) { moduleName_ = name; } void setModuleName(const QString &name) { moduleName_ = name; }
void setLink(LinkType linkType, const QString &link, const QString &desc); void setUrl(const QString& url) { url_ = url; }
void setUrl(const QString &url);
void setTemplateStuff(const QString &templateStuff) { templateStuff_ = templateStuff; } void setTemplateStuff(const QString &templateStuff) { templateStuff_ = templateStuff; }
void setReconstitutedBrief(const QString &t) { reconstitutedBrief_ = t; } void setReconstitutedBrief(const QString &t) { reconstitutedBrief_ = t; }
void setPageType(PageType t) { pageType_ = t; } void setPageType(PageType t) { pageType_ = t; }
@ -193,14 +198,17 @@ public:
void setParent(InnerNode* n) { parent_ = n; } void setParent(InnerNode* n) { parent_ = n; }
void setIndexNodeFlag() { indexNodeFlag_ = true; } void setIndexNodeFlag() { indexNodeFlag_ = true; }
virtual void setOutputFileName(const QString& ) { } virtual void setOutputFileName(const QString& ) { }
void markSeen() { seen_ = true; }
void markNotSeen() { seen_ = false; }
virtual bool isInnerNode() const = 0; virtual bool isInnerNode() const = 0;
virtual bool isDocNode() const { return false; }
virtual bool isCollectionNode() const { return false; }
virtual bool isGroup() const { return false; }
virtual bool isModule() const { return false; }
virtual bool isQmlModule() const { return false; } virtual bool isQmlModule() const { return false; }
virtual bool isQmlType() const { return false; } virtual bool isQmlType() const { return false; }
virtual bool isExample() const { return false; } virtual bool isExample() const { return false; }
virtual bool isExampleFile() const { return false; } virtual bool isExampleFile() const { return false; }
virtual bool isHeaderFile() const { return false; }
virtual bool isLeaf() const { return false; } virtual bool isLeaf() const { return false; }
virtual bool isReimp() const { return false; } virtual bool isReimp() const { return false; }
virtual bool isFunction() const { return false; } virtual bool isFunction() const { return false; }
@ -213,7 +221,6 @@ public:
virtual bool isCollisionNode() const { return false; } virtual bool isCollisionNode() const { return false; }
virtual bool isAttached() const { return false; } virtual bool isAttached() const { return false; }
virtual bool isAlias() const { return false; } virtual bool isAlias() const { return false; }
virtual bool isGroup() const { return false; }
virtual bool isWrapper() const; virtual bool isWrapper() const;
virtual bool isReadOnly() const { return false; } virtual bool isReadOnly() const { return false; }
virtual bool isDefault() const { return false; } virtual bool isDefault() const { return false; }
@ -224,7 +231,11 @@ public:
virtual bool hasClasses() const { return false; } virtual bool hasClasses() const { return false; }
virtual void setAbstract(bool ) { } virtual void setAbstract(bool ) { }
virtual void setWrapper() { } virtual void setWrapper() { }
virtual QString title() const { return QString(); } virtual QString title() const { return name(); }
virtual QString fullTitle() const { return name(); }
virtual QString subTitle() const { return QString(); }
virtual void setTitle(const QString& ) { }
virtual void setSubTitle(const QString& ) { }
virtual QmlPropertyNode* hasQmlProperty(const QString& ) const { return 0; } virtual QmlPropertyNode* hasQmlProperty(const QString& ) const { return 0; }
virtual void getMemberNamespaces(NodeMap& ) { } virtual void getMemberNamespaces(NodeMap& ) { }
virtual void getMemberClasses(NodeMap& ) { } virtual void getMemberClasses(NodeMap& ) { }
@ -232,28 +243,35 @@ public:
virtual void setDataType(const QString& ) { } virtual void setDataType(const QString& ) { }
virtual void setReadOnly(bool ) { } virtual void setReadOnly(bool ) { }
virtual Node* disambiguate(Type , SubType ) { return this; } virtual Node* disambiguate(Type , SubType ) { return this; }
virtual bool wasSeen() const { return false; }
virtual void appendGroupName(const QString& ) { }
bool isIndexNode() const { return indexNodeFlag_; } bool isIndexNode() const { return indexNodeFlag_; }
bool wasSeen() const { return seen_; }
Type type() const { return nodeType_; } Type type() const { return nodeType_; }
virtual SubType subType() const { return NoSubType; } virtual SubType subType() const { return NoSubType; }
bool match(const NodeTypeList& types) const; bool match(const NodeTypeList& types) const;
InnerNode* parent() const { return parent_; } InnerNode* parent() const { return parent_; }
InnerNode* relates() const { return relatesTo_; } InnerNode* relates() const { return relatesTo_; }
const QString& name() const { return name_; } const QString& name() const { return name_; }
const QMap<LinkType, QPair<QString,QString> >& links() const { return linkMap_; }
QString moduleName() const; QString moduleName() const;
QString url() const; QString url() const { return url_; }
virtual QString nameForLists() const { return name_; } virtual QString nameForLists() const { return name_; }
virtual QString outputFileName() const { return QString(); } virtual QString outputFileName() const { return QString(); }
virtual QString obsoleteLink() const { return QString(); } virtual QString obsoleteLink() const { return QString(); }
virtual void setObsoleteLink(const QString& ) { }; virtual void setObsoleteLink(const QString& ) { };
virtual void setQtVariable(const QString& ) { }
virtual QString qtVariable() const { return QString(); }
const QMap<LinkType, QPair<QString,QString> >& links() const { return linkMap_; }
void setLink(LinkType linkType, const QString &link, const QString &desc);
Access access() const { return access_; } Access access() const { return access_; }
QString accessString() const; QString accessString() const;
const Location& location() const { return loc_; } const Location& location() const { return loc_; }
const Doc& doc() const { return doc_; } const Doc& doc() const { return doc_; }
bool hasDoc() const { return !doc_.isEmpty(); }
Status status() const { return status_; } Status status() const { return status_; }
Status inheritedStatus() const; Status inheritedStatus() const;
bool isObsolete() const { return (status_ == Obsolete); }
ThreadSafeness threadSafeness() const; ThreadSafeness threadSafeness() const;
ThreadSafeness inheritedThreadSafeness() const; ThreadSafeness inheritedThreadSafeness() const;
QString since() const { return since_; } QString since() const { return since_; }
@ -310,7 +328,6 @@ private:
PageType pageType_; PageType pageType_;
Status status_; Status status_;
bool indexNodeFlag_; bool indexNodeFlag_;
bool seen_;
InnerNode* parent_; InnerNode* parent_;
InnerNode* relatesTo_; InnerNode* relatesTo_;
@ -330,10 +347,6 @@ private:
static int propertyGroupCount_; static int propertyGroupCount_;
}; };
class FunctionNode;
class EnumNode;
class NameCollisionNode;
class InnerNode : public Node class InnerNode : public Node
{ {
public: public:
@ -360,14 +373,6 @@ public:
const NodeList & childNodes() const { return children_; } const NodeList & childNodes() const { return children_; }
const NodeList & relatedNodes() const { return related_; } const NodeList & relatedNodes() const { return related_; }
virtual void addMember(Node* node);
const NodeList& members() const { return members_; }
virtual bool hasMembers() const;
virtual bool hasNamespaces() const;
virtual bool hasClasses() const;
virtual void getMemberNamespaces(NodeMap& out);
virtual void getMemberClasses(NodeMap& out);
int count() const { return children_.size(); } int count() const { return children_.size(); }
int overloadNumber(const FunctionNode* func) const; int overloadNumber(const FunctionNode* func) const;
NodeList overloads(const QString &funcName) const; NodeList overloads(const QString &funcName) const;
@ -383,9 +388,9 @@ public:
virtual QString outputFileName() const { return outputFileName_; } virtual QString outputFileName() const { return outputFileName_; }
virtual QmlPropertyNode* hasQmlProperty(const QString& ) const; virtual QmlPropertyNode* hasQmlProperty(const QString& ) const;
void addChild(Node* child, const QString& title); void addChild(Node* child, const QString& title);
const QStringList& groupNames() const { return groupNames_; }
virtual void appendGroupName(const QString& t) { groupNames_.append(t); }
void printChildren(const QString& title); void printChildren(const QString& title);
void printMembers(const QString& title);
protected: protected:
InnerNode(Type type, InnerNode* parent, const QString& name); InnerNode(Type type, InnerNode* parent, const QString& name);
@ -402,8 +407,8 @@ private:
QString outputFileName_; QString outputFileName_;
QStringList pageKeywds; QStringList pageKeywds;
QStringList includes_; QStringList includes_;
QStringList groupNames_;
NodeList children_; NodeList children_;
NodeList members_;
NodeList enumChildren_; NodeList enumChildren_;
NodeList related_; NodeList related_;
QMap<QString, Node*> childMap; QMap<QString, Node*> childMap;
@ -433,8 +438,6 @@ public:
virtual bool isNamespace() const { return true; } virtual bool isNamespace() const { return true; }
}; };
class ClassNode;
struct RelatedClass struct RelatedClass
{ {
RelatedClass() { } RelatedClass() { }
@ -445,6 +448,7 @@ struct RelatedClass
RelatedClass(Node::Access access, const QStringList& path, const QString& signature) RelatedClass(Node::Access access, const QStringList& path, const QString& signature)
: access_(access), node_(0), path_(path), signature_(signature) { } : access_(access), node_(0), path_(path), signature_(signature) { }
QString accessString() const; QString accessString() const;
bool isPrivate() const { return (access_ == Node::Private); }
Node::Access access_; Node::Access access_;
ClassNode* node_; ClassNode* node_;
@ -452,8 +456,6 @@ struct RelatedClass
QString signature_; QString signature_;
}; };
class PropertyNode;
class ClassNode : public InnerNode class ClassNode : public InnerNode
{ {
public: public:
@ -466,6 +468,7 @@ public:
virtual void setWrapper() { wrapper_ = true; } virtual void setWrapper() { wrapper_ = true; }
void addResolvedBaseClass(Access access, ClassNode* node); void addResolvedBaseClass(Access access, ClassNode* node);
void addDerivedClass(Access access, ClassNode* node);
void addUnresolvedBaseClass(Access access, const QStringList& path, const QString& signature); void addUnresolvedBaseClass(Access access, const QStringList& path, const QString& signature);
void fixBaseClasses(); void fixBaseClasses();
void fixPropertyUsingBaseClasses(PropertyNode* pn); void fixPropertyUsingBaseClasses(PropertyNode* pn);
@ -508,49 +511,26 @@ public:
PageType ptype); PageType ptype);
virtual ~DocNode() { } virtual ~DocNode() { }
void setQtVariable(const QString &variable) { qtVariable_ = variable; } virtual void setTitle(const QString &title);
void setTitle(const QString &title); virtual void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
QString qtVariable() const { return qtVariable_; }
SubType subType() const { return nodeSubtype_; } SubType subType() const { return nodeSubtype_; }
virtual QString title() const; virtual QString title() const { return title_; }
virtual QString fullTitle() const; virtual QString fullTitle() const;
virtual QString subTitle() const; virtual QString subTitle() const;
virtual QString imageFileName() const { return QString(); } virtual QString imageFileName() const { return QString(); }
virtual QString nameForLists() const { return title(); } virtual QString nameForLists() const { return title(); }
virtual void setImageFileName(const QString& ) { } virtual void setImageFileName(const QString& ) { }
virtual bool isGroup() const { return (subType() == Node::Group); } virtual bool isHeaderFile() const { return (subType() == Node::HeaderFile); }
virtual bool isExample() const { return (subType() == Node::Example); } virtual bool isExample() const { return (subType() == Node::Example); }
virtual bool isExampleFile() const { return (parent() && parent()->isExample()); } virtual bool isExampleFile() const { return (parent() && parent()->isExample()); }
virtual bool isExternalPage() const { return nodeSubtype_ == ExternalPage; } virtual bool isExternalPage() const { return nodeSubtype_ == ExternalPage; }
virtual bool isDocNode() const { return true; }
protected: protected:
SubType nodeSubtype_; SubType nodeSubtype_;
QString title_; QString title_;
QString subtitle_; QString subtitle_;
private:
QString qtVariable_;
};
class QmlModuleNode : public DocNode
{
public:
QmlModuleNode(InnerNode* parent, const QString& name)
: DocNode(parent, name, Node::QmlModule, Node::OverviewPage) { }
virtual ~QmlModuleNode() { }
virtual bool isQmlModule() const { return true; }
virtual QString qmlModuleName() const { return qmlModuleName_; }
virtual QString qmlModuleVersion() const { return qmlModuleVersionMajor_ + "." + qmlModuleVersionMinor_; }
virtual QString qmlModuleIdentifier() const { return qmlModuleName_ + qmlModuleVersionMajor_; }
virtual void setQmlModuleInfo(const QString& );
private:
QString qmlModuleName_;
QString qmlModuleVersionMajor_;
QString qmlModuleVersionMinor_;
}; };
class NameCollisionNode : public DocNode class NameCollisionNode : public DocNode
@ -578,16 +558,12 @@ private:
class ExampleNode : public DocNode class ExampleNode : public DocNode
{ {
public: public:
ExampleNode(InnerNode* parent, const QString& name); ExampleNode(InnerNode* parent, const QString& name)
: DocNode(parent, name, Node::Example, Node::ExamplePage) { }
virtual ~ExampleNode() { } virtual ~ExampleNode() { }
virtual QString imageFileName() const { return imageFileName_; } virtual QString imageFileName() const { return imageFileName_; }
virtual void setImageFileName(const QString& ifn) { imageFileName_ = ifn; } virtual void setImageFileName(const QString& ifn) { imageFileName_ = ifn; }
static void terminate() { exampleNodeMap.clear(); }
public:
static ExampleNodeMap exampleNodeMap;
private: private:
QString imageFileName_; QString imageFileName_;
}; };
@ -694,8 +670,6 @@ public:
int idNumber_; int idNumber_;
}; };
class QmlPropertyNode;
class QmlPropertyNode : public LeafNode class QmlPropertyNode : public LeafNode
{ {
Q_DECLARE_TR_FUNCTIONS(QDoc::QmlPropertyNode) Q_DECLARE_TR_FUNCTIONS(QDoc::QmlPropertyNode)
@ -764,8 +738,6 @@ private:
Text txt; Text txt;
}; };
class TypedefNode;
class EnumNode : public LeafNode class EnumNode : public LeafNode
{ {
public: public:
@ -1055,6 +1027,94 @@ public:
const DitaRefList& map() const { return doc().ditamap(); } const DitaRefList& map() const { return doc().ditamap(); }
}; };
class CollectionNode : public InnerNode
{
public:
CollectionNode(Type type, InnerNode* parent, const QString& name)
: InnerNode(type, parent, name), seen_(false) {
setPageType(Node::OverviewPage);
}
virtual ~CollectionNode() { }
virtual bool isCollectionNode() const { return true; }
virtual void addMember(Node* node);
virtual bool hasMembers() const;
virtual bool hasNamespaces() const;
virtual bool hasClasses() const;
virtual void getMemberNamespaces(NodeMap& out);
virtual void getMemberClasses(NodeMap& out);
virtual bool wasSeen() const { return seen_; }
virtual QString title() const { return title_; }
virtual QString subTitle() const { return subtitle_; }
virtual QString fullTitle() const { return title_; }
virtual QString nameForLists() const { return title_; }
virtual void setTitle(const QString &title);
virtual void setSubTitle(const QString &subTitle) { subtitle_ = subTitle; }
const NodeList& members() const { return members_; }
void printMembers(const QString& title);
void markSeen() { seen_ = true; }
void markNotSeen() { seen_ = false; }
private:
bool seen_;
QString title_;
QString subtitle_;
NodeList members_;
};
class GroupNode : public CollectionNode
{
public:
GroupNode(InnerNode* parent, const QString& name)
: CollectionNode(Node::Group, parent, name) { }
virtual ~GroupNode() { }
virtual bool isGroup() const { return true; }
};
class ModuleNode : public CollectionNode
{
public:
ModuleNode(InnerNode* parent, const QString& name)
: CollectionNode(Node::Module, parent, name) { }
virtual ~ModuleNode() { }
virtual bool isModule() const { return true; }
virtual void setQtVariable(const QString& v) { qtVariable_ = v; }
virtual QString qtVariable() const { return qtVariable_; }
private:
QString qtVariable_;
};
class QmlModuleNode : public CollectionNode
{
public:
QmlModuleNode(InnerNode* parent, const QString& name)
: CollectionNode(Node::QmlModule, parent, name) { }
virtual ~QmlModuleNode() { }
virtual bool isQmlModule() const { return true; }
virtual QString qmlModuleName() const { return qmlModuleName_; }
virtual QString qmlModuleVersion() const {
return qmlModuleVersionMajor_ + "." + qmlModuleVersionMinor_;
}
virtual QString qmlModuleIdentifier() const {
return qmlModuleName_ + qmlModuleVersionMajor_;
}
virtual void setQmlModuleInfo(const QString& );
virtual void setQtVariable(const QString& v) { qtVariable_ = v; }
virtual QString qtVariable() const { return qtVariable_; }
private:
QString qmlModuleName_;
QString qmlModuleVersionMajor_;
QString qmlModuleVersionMinor_;
QString qtVariable_;
};
QT_END_NAMESPACE QT_END_NAMESPACE
#endif #endif

View File

@ -79,6 +79,7 @@ QDocForest::~QDocForest()
delete searchOrder_.at(i); delete searchOrder_.at(i);
forest_.clear(); forest_.clear();
searchOrder_.clear(); searchOrder_.clear();
indexSearchOrder_.clear();
moduleNames_.clear(); moduleNames_.clear();
primaryTree_ = 0; primaryTree_ = 0;
} }
@ -91,7 +92,7 @@ QDocForest::~QDocForest()
NamespaceNode* QDocForest::firstRoot() NamespaceNode* QDocForest::firstRoot()
{ {
currentIndex_ = 0; currentIndex_ = 0;
return (!searchOrder_.isEmpty() ? searchOrder_[0]->root() : 0); return (!searchOrder().isEmpty() ? searchOrder()[0]->root() : 0);
} }
/*! /*!
@ -102,7 +103,7 @@ NamespaceNode* QDocForest::firstRoot()
NamespaceNode* QDocForest::nextRoot() NamespaceNode* QDocForest::nextRoot()
{ {
++currentIndex_; ++currentIndex_;
return (currentIndex_ < searchOrder_.size() ? searchOrder_[currentIndex_]->root() : 0); return (currentIndex_ < searchOrder().size() ? searchOrder()[currentIndex_]->root() : 0);
} }
/*! /*!
@ -113,7 +114,7 @@ NamespaceNode* QDocForest::nextRoot()
Tree* QDocForest::firstTree() Tree* QDocForest::firstTree()
{ {
currentIndex_ = 0; currentIndex_ = 0;
return (!searchOrder_.isEmpty() ? searchOrder_[0] : 0); return (!searchOrder().isEmpty() ? searchOrder()[0] : 0);
} }
/*! /*!
@ -124,7 +125,7 @@ Tree* QDocForest::firstTree()
Tree* QDocForest::nextTree() Tree* QDocForest::nextTree()
{ {
++currentIndex_; ++currentIndex_;
return (currentIndex_ < searchOrder_.size() ? searchOrder_[currentIndex_] : 0); return (currentIndex_ < searchOrder().size() ? searchOrder()[currentIndex_] : 0);
} }
/*! /*!
@ -305,15 +306,46 @@ void QDocForest::setSearchOrder()
will probably be changed. will probably be changed.
If the search order array is empty, this function calls If the search order array is empty, this function calls
setSearchOrder() to create the search order. indexSearchOrder(). The search order array is empty while
the index files are being loaded, but some searches must
be performed during this time, notably searches for base
class nodes. These searches require a temporary search
order. The temporary order changes throughout the loading
of the index files, but it is always the tree for the
current index file first, followed by the trees for the
index files that have already been loaded. The only
ordering required in this temporary search order is that
the current tree must be searched first.
*/ */
const QVector<Tree*>& QDocForest::searchOrder() const QVector<Tree*>& QDocForest::searchOrder()
{ {
if (searchOrder_.isEmpty()) if (searchOrder_.isEmpty())
setSearchOrder(); return indexSearchOrder();
return searchOrder_; return searchOrder_;
} }
/*!
There are two search orders used by qdoc when searching for
things. The normal search order is returned by searchOrder(),
but this normal search order is not known until all the index
files have been read. At that point, setSearchOrder() is
called.
During the reading of the index files, the vector holding
the normal search order remains empty. Whenever the search
order is requested, if that vector is empty, this function
is called to return a temporary search order, which includes
all the index files that have been read so far, plus the
one being read now. That one is prepended to the front of
the vector.
*/
const QVector<Tree*>& QDocForest::indexSearchOrder()
{
if (forest_.size() > indexSearchOrder_.size())
indexSearchOrder_.prepend(primaryTree_);
return indexSearchOrder_;
}
/*! /*!
Create a new Tree for the index file for the specified Create a new Tree for the index file for the specified
\a module and add it to the forest. Return the pointer \a module and add it to the forest. Return the pointer
@ -384,6 +416,31 @@ const Node* QDocForest::resolveTypeHelper(const QStringList& path, const Node* r
return t->findNode(path, relative, flags); return t->findNode(path, relative, flags);
} }
/*!
This function merges all the collection maps for collection
nodes of node type \a t into the collection multimap \a cnmm,
which is cleared before starting.
This is mainly useful for groups, which often cross module
boundaries. It might be true that neither modules nor QML
modules cross module boundaries, but this function works for
those cases as well.
*/
void QDocForest::mergeCollectionMaps(Node::Type nt, CNMultiMap& cnmm)
{
foreach (Tree* t, searchOrder()) {
const CNMap& cnm = t->getCollections(nt);
if (!cnm.isEmpty()) {
CNMap::const_iterator i = cnm.begin();
while (i != cnm.end()) {
if (!i.value()->isInternal())
cnmm.insert(i.key(), i.value());
++i;
}
}
}
}
/*! \class QDocDatabase /*! \class QDocDatabase
This class provides exclusive access to the qdoc database, This class provides exclusive access to the qdoc database,
which consists of a forrest of trees and a lot of maps and which consists of a forrest of trees and a lot of maps and
@ -411,7 +468,7 @@ QDocDatabase::QDocDatabase() : showInternal_(false), forest_(this)
*/ */
QDocDatabase::~QDocDatabase() QDocDatabase::~QDocDatabase()
{ {
masterMap_.clear(); // nothing.
} }
/*! /*!
@ -599,36 +656,29 @@ void QDocDatabase::initializeDB()
*/ */
/*! /*!
\fn const DocNodeMap& QDocDatabase::groups() const \fn const GroupMap& QDocDatabase::groups()
Returns a const reference to the collection of all Returns a const reference to the collection of all
group nodes. group nodes in the primary tree.
*/ */
/*! /*!
\fn const DocNodeMap& QDocDatabase::modules() const \fn const ModuleMap& QDocDatabase::modules()
Returns a const reference to the collection of all Returns a const reference to the collection of all
module nodes. module nodes in the primary tree.
*/ */
/*! /*!
\fn const DocNodeMap& QDocDatabase::qmlModules() const \fn const QmlModuleMap& QDocDatabase::qmlModules()
Returns a const reference to the collection of all Returns a const reference to the collection of all
QML module nodes. QML module nodes in the primary tree.
*/ */
/*! /*! \fn GroupNode* QDocDatabase::getGroup(const QString& name)
Find the group node named \a name and return a pointer Find the group node named \a name and return a pointer
to it. If a matching node is not found, return 0. to it. If a matching node is not found, return 0.
*/ */
DocNode* QDocDatabase::getGroup(const QString& name)
{
DocNodeMap::const_iterator i = groups_.find(name);
if (i != groups_.end())
return i.value();
return 0;
}
/*! /*! \fn GroupNode* QDocDatabase::findGroup(const QString& name)
Find the group node named \a name and return a pointer Find the group node named \a name and return a pointer
to it. If a matching node is not found, add a new group to it. If a matching node is not found, add a new group
node named \a name and return a pointer to that one. node named \a name and return a pointer to that one.
@ -636,20 +686,8 @@ DocNode* QDocDatabase::getGroup(const QString& name)
If a new group node is added, its parent is the tree root, If a new group node is added, its parent is the tree root,
and the new group node is marked \e{not seen}. and the new group node is marked \e{not seen}.
*/ */
DocNode* QDocDatabase::findGroup(const QString& name)
{
DocNodeMap::const_iterator i = groups_.find(name);
if (i != groups_.end())
return i.value();
DocNode* dn = new DocNode(primaryTreeRoot(), name, Node::Group, Node::OverviewPage);
dn->markNotSeen();
groups_.insert(name,dn);
if (!masterMap_.contains(name,dn))
masterMap_.insert(name,dn);
return dn;
}
/*! /*! \fn ModuleNode* QDocDatabase::findModule(const QString& name)
Find the module node named \a name and return a pointer Find the module node named \a name and return a pointer
to it. If a matching node is not found, add a new module to it. If a matching node is not found, add a new module
node named \a name and return a pointer to that one. node named \a name and return a pointer to that one.
@ -657,20 +695,8 @@ DocNode* QDocDatabase::findGroup(const QString& name)
If a new module node is added, its parent is the tree root, If a new module node is added, its parent is the tree root,
and the new module node is marked \e{not seen}. and the new module node is marked \e{not seen}.
*/ */
DocNode* QDocDatabase::findModule(const QString& name)
{
DocNodeMap::const_iterator i = modules_.find(name);
if (i != modules_.end())
return i.value();
DocNode* dn = new DocNode(primaryTreeRoot(), name, Node::Module, Node::OverviewPage);
dn->markNotSeen();
modules_.insert(name,dn);
if (!masterMap_.contains(name,dn))
masterMap_.insert(name,dn);
return dn;
}
/*! /*! \fn QmlModuleNode* QDocDatabase::findQmlModule(const QString& name)
Find the QML module node named \a name and return a pointer Find the QML module node named \a name and return a pointer
to it. If a matching node is not found, add a new QML module to it. If a matching node is not found, add a new QML module
node named \a name and return a pointer to that one. node named \a name and return a pointer to that one.
@ -678,68 +704,32 @@ DocNode* QDocDatabase::findModule(const QString& name)
If a new QML module node is added, its parent is the tree root, If a new QML module node is added, its parent is the tree root,
and the new QML module node is marked \e{not seen}. and the new QML module node is marked \e{not seen}.
*/ */
QmlModuleNode* QDocDatabase::findQmlModule(const QString& name)
{
if (qmlModules_.contains(name))
return static_cast<QmlModuleNode*>(qmlModules_.value(name));
QmlModuleNode* qmn = new QmlModuleNode(primaryTreeRoot(), name); /*! \fn GroupNode* QDocDatabase::addGroup(const QString& name)
qmn->markNotSeen(); Looks up the group named \a name in the primary tree. If
qmn->setQmlModuleInfo(name); a match is found, a pointer to the node is returned.
qmlModules_.insert(name, qmn); Otherwise, a new group node named \a name is created and
masterMap_.insert(name, qmn); inserted into the collection, and the pointer to that node
return qmn; is returned.
}
/*!
Looks up the group node named \a name in the collection
of all group nodes. If a match is found, a pointer to the
node is returned. Otherwise, a new group node named \a name
is created and inserted into the collection, and the pointer
to that node is returned. The group node is marked \e{seen}
in either case.
*/ */
DocNode* QDocDatabase::addGroup(const QString& name)
{
DocNode* group = findGroup(name);
group->markSeen();
return group;
}
/*! /*! \fn ModuleNode* QDocDatabase::addModule(const QString& name)
Looks up the module node named \a name in the collection Looks up the module named \a name in the primary tree. If
of all module nodes. If a match is found, a pointer to the a match is found, a pointer to the node is returned.
node is returned. Otherwise, a new module node named \a name Otherwise, a new module node named \a name is created and
is created and inserted into the collection, and the pointer inserted into the collection, and the pointer to that node
to that node is returned. The module node is marked \e{seen} is returned.
in either case.
*/ */
DocNode* QDocDatabase::addModule(const QString& name)
{
DocNode* module = findModule(name);
module->markSeen();
return module;
}
/*! /*! \fn QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
Looks up the QML module node named \a name in the collection Looks up the QML module named \a name in the primary tree.
of all QML module nodes. If a match is found, a pointer to the If a match is found, a pointer to the node is returned.
node is returned. Otherwise, a new QML module node named \a name Otherwise, a new QML module node named \a name is created
is created and inserted into the collection, and the pointer and inserted into the collection, and the pointer to that
to that node is returned. The QML module node is marked \e{seen} node is returned.
in either case.
*/ */
QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
{
QStringList blankSplit = name.split(QLatin1Char(' '));
QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
qmn->setQmlModuleInfo(name);
qmn->markSeen();
//masterMap_.insert(qmn->qmlModuleIdentifier(),qmn);
return qmn;
}
/*! /*! \fn GroupNode* QDocDatabase::addToGroup(const QString& name, Node* node)
Looks up the group node named \a name in the collection Looks up the group node named \a name in the collection
of all group nodes. If a match is not found, a new group of all group nodes. If a match is not found, a new group
node named \a name is created and inserted into the collection. node named \a name is created and inserted into the collection.
@ -748,63 +738,20 @@ QmlModuleNode* QDocDatabase::addQmlModule(const QString& name)
\a node is not changed by this function. Returns a pointer to \a node is not changed by this function. Returns a pointer to
the group node. the group node.
*/ */
DocNode* QDocDatabase::addToGroup(const QString& name, Node* node)
{
DocNode* dn = findGroup(name);
dn->addMember(node);
node->addMember(dn);
return dn;
}
/*! /*! \fn ModuleNode* QDocDatabase::addToModule(const QString& name, Node* node)
Looks up the module node named \a name in the collection Looks up the module node named \a name in the collection
of all module nodes. If a match is not found, a new module of all module nodes. If a match is not found, a new module
node named \a name is created and inserted into the collection. node named \a name is created and inserted into the collection.
Then append \a node to the module's members list. The parent of Then append \a node to the module's members list. The parent of
\a node is not changed by this function. Returns the module node. \a node is not changed by this function. Returns the module node.
*/ */
DocNode* QDocDatabase::addToModule(const QString& name, Node* node)
{
DocNode* dn = findModule(name);
dn->addMember(node);
node->setModuleName(name);
return dn;
}
/*! /*! \fn QmlModuleNode* QDocDatabase::addToQmlModule(const QString& name, Node* node)
Looks up the QML module named \a name. If it isn't there, Looks up the QML module named \a name. If it isn't there,
create it. Then append \a node to the QML module's member create it. Then append \a node to the QML module's member
list. The parent of \a node is not changed by this function. list. The parent of \a node is not changed by this function.
*/ */
void QDocDatabase::addToQmlModule(const QString& name, Node* node)
{
QStringList qmid;
QStringList dotSplit;
QStringList blankSplit = name.split(QLatin1Char(' '));
qmid.append(blankSplit[0]);
if (blankSplit.size() > 1) {
qmid.append(blankSplit[0] + blankSplit[1]);
dotSplit = blankSplit[1].split(QLatin1Char('.'));
qmid.append(blankSplit[0] + dotSplit[0]);
}
QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
qmn->addMember(node);
node->setQmlModule(qmn);
if (node->subType() == Node::QmlClass) {
QmlClassNode* n = static_cast<QmlClassNode*>(node);
for (int i=0; i<qmid.size(); ++i) {
QString key = qmid[i] + "::" + node->name();
if (!qmlTypeMap_.contains(key))
qmlTypeMap_.insert(key,n);
if (!masterMap_.contains(key))
masterMap_.insert(key,node);
}
if (!masterMap_.contains(node->name(),node))
masterMap_.insert(node->name(),node);
}
}
/*! /*!
Looks up the QML type node identified by the Qml module id Looks up the QML type node identified by the Qml module id
@ -816,8 +763,12 @@ void QDocDatabase::addToQmlModule(const QString& name, Node* node)
*/ */
QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name) QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name)
{ {
if (!qmid.isEmpty()) if (!qmid.isEmpty()) {
return qmlTypeMap_.value(qmid + "::" + name); QString t = qmid + "::" + name;
QmlClassNode* qcn = forest_.lookupQmlType(t);
if (qcn)
return qcn;
}
QStringList path(name); QStringList path(name);
Node* n = forest_.findNodeByNameAndType(path, Node::Document, Node::QmlClass, true); Node* n = forest_.findNodeByNameAndType(path, Node::Document, Node::QmlClass, true);
@ -839,7 +790,7 @@ QmlClassNode* QDocDatabase::findQmlType(const QString& qmid, const QString& name
QML type \a name and returns a pointer to the QML type node. QML type \a name and returns a pointer to the QML type node.
If a QML type node is not found, 0 is returned. If a QML type node is not found, 0 is returned.
*/ */
QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString& name) const QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString& name)
{ {
if (!import.isEmpty()) { if (!import.isEmpty()) {
QStringList dotSplit; QStringList dotSplit;
@ -851,7 +802,7 @@ QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString&
qmName = import.importUri_; qmName = import.importUri_;
for (int i=0; i<dotSplit.size(); ++i) { for (int i=0; i<dotSplit.size(); ++i) {
QString qualifiedName = qmName + "::" + dotSplit[i]; QString qualifiedName = qmName + "::" + dotSplit[i];
QmlClassNode* qcn = qmlTypeMap_.value(qualifiedName); QmlClassNode* qcn = forest_.lookupQmlType(qualifiedName);
if (qcn) if (qcn)
return qcn; return qcn;
} }
@ -859,30 +810,6 @@ QmlClassNode* QDocDatabase::findQmlType(const ImportRec& import, const QString&
return 0; return 0;
} }
/*!
For debugging only.
*/
void QDocDatabase::printModules() const
{
DocNodeMap::const_iterator i = modules_.begin();
while (i != modules_.end()) {
qDebug() << " " << i.key();
++i;
}
}
/*!
For debugging only.
*/
void QDocDatabase::printQmlModules() const
{
DocNodeMap::const_iterator i = qmlModules_.begin();
while (i != qmlModules_.end()) {
qDebug() << " " << i.key();
++i;
}
}
/*! /*!
This function calls \a func for each tree in the forest. This function calls \a func for each tree in the forest.
*/ */
@ -896,36 +823,138 @@ void QDocDatabase::processForest(void (QDocDatabase::*func) (InnerNode*))
} }
/*! /*!
Traverses the database to construct useful data structures Constructs the collection of legalese texts, if it has not
for use when outputting certain significant collections of already been constructed and returns a reference to it.
things, C++ classes, QML types, "since" lists, and other
stuff.
*/ */
void QDocDatabase::buildCollections() TextToNodeMap& QDocDatabase::getLegaleseTexts()
{ {
nonCompatClasses_.clear(); if (legaleseTexts_.isEmpty())
mainClasses_.clear();
compatClasses_.clear();
obsoleteClasses_.clear();
funcIndex_.clear();
legaleseTexts_.clear();
serviceClasses_.clear();
qmlClasses_.clear();
/*
findAllClasses(treeRoot());
findAllFunctions(treeRoot());
findAllLegaleseTexts(treeRoot());
findAllNamespaces(treeRoot());
findAllSince(treeRoot());
findAllObsoleteThings(treeRoot());
*/
processForest(&QDocDatabase::findAllClasses);
processForest(&QDocDatabase::findAllFunctions);
processForest(&QDocDatabase::findAllLegaleseTexts); processForest(&QDocDatabase::findAllLegaleseTexts);
processForest(&QDocDatabase::findAllNamespaces); return legaleseTexts_;
processForest(&QDocDatabase::findAllSince); }
/*!
Construct the data structures for obsolete things, if they
have not already been constructed. Returns a reference to
the map of C++ classes with obsolete members.
*/
NodeMap& QDocDatabase::getClassesWithObsoleteMembers()
{
if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
processForest(&QDocDatabase::findAllObsoleteThings); processForest(&QDocDatabase::findAllObsoleteThings);
return classesWithObsoleteMembers_;
}
/*!
Construct the data structures for obsolete things, if they
have not already been constructed. Returns a reference to
the map of obsolete QML types.
*/
NodeMap& QDocDatabase::getObsoleteQmlTypes()
{
if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
processForest(&QDocDatabase::findAllObsoleteThings);
return obsoleteQmlTypes_;
}
/*!
Construct the data structures for obsolete things, if they
have not already been constructed. Returns a reference to
the map of QML types with obsolete members.
*/
NodeMap& QDocDatabase::getQmlTypesWithObsoleteMembers()
{
if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
processForest(&QDocDatabase::findAllObsoleteThings);
return qmlTypesWithObsoleteMembers_;
}
/*!
Constructs the C++ namespace data structure, if it has not
already been constructed. Returns a reference to it.
*/
NodeMap& QDocDatabase::getNamespaces()
{
if (namespaceIndex_.isEmpty())
processForest(&QDocDatabase::findAllNamespaces);
return namespaceIndex_;
}
/*!
Construct the C++ class data structures, if they have not
already been constructed. Returns a reference to the map
of C++ service clases.
\note This is currently not used.
*/
NodeMap& QDocDatabase::getServiceClasses()
{
if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
processForest(&QDocDatabase::findAllClasses);
return serviceClasses_;
}
/*!
Construct the data structures for obsolete things, if they
have not already been constructed. Returns a reference to
the map of obsolete QML types.
*/
NodeMap& QDocDatabase::getQmlTypes()
{
if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
processForest(&QDocDatabase::findAllClasses);
return qmlClasses_;
}
/*!
Construct the data structures for obsolete things, if they
have not already been constructed. Returns a reference to
the map of obsolete C++ clases.
*/
NodeMap& QDocDatabase::getObsoleteClasses()
{
if (obsoleteClasses_.isEmpty() && obsoleteQmlTypes_.isEmpty())
processForest(&QDocDatabase::findAllObsoleteThings);
return obsoleteClasses_;
}
/*!
Construct the C++ class data structures, if they have not
already been constructed. Returns a reference to the map
of compatibility C++ clases.
*/
NodeMap& QDocDatabase::getCompatibilityClasses()
{
if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
processForest(&QDocDatabase::findAllClasses);
return compatClasses_;
}
/*!
Construct the C++ class data structures, if they have not
already been constructed. Returns a reference to the map
of main C++ clases.
\note The main C++ classes data structure is currently not
used.
*/
NodeMap& QDocDatabase::getMainClasses()
{
if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
processForest(&QDocDatabase::findAllClasses);
return mainClasses_;
}
/*!
Construct the C++ class data structures, if they have not
already been constructed. Returns a reference to the map
of all C++ classes.
*/
NodeMap& QDocDatabase::getCppClasses()
{
if (nonCompatClasses_.isEmpty() && qmlClasses_.isEmpty())
processForest(&QDocDatabase::findAllClasses);
return nonCompatClasses_;
} }
/*! /*!
@ -975,6 +1004,17 @@ void QDocDatabase::findAllClasses(InnerNode* node)
} }
} }
/*!
Construct the function index data structure and return it.
This data structure is used to output the function index page.
*/
NodeMapMap& QDocDatabase::getFunctionIndex()
{
funcIndex_.clear();
processForest(&QDocDatabase::findAllFunctions);
return funcIndex_;
}
/*! /*!
Finds all the function nodes Finds all the function nodes
*/ */
@ -1215,8 +1255,10 @@ void QDocDatabase::findAllSince(InnerNode* node)
reference to the value, which is a NodeMap. If \a key is not reference to the value, which is a NodeMap. If \a key is not
found, return a reference to an empty NodeMap. found, return a reference to an empty NodeMap.
*/ */
const NodeMap& QDocDatabase::getClassMap(const QString& key) const const NodeMap& QDocDatabase::getClassMap(const QString& key)
{ {
if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
processForest(&QDocDatabase::findAllSince);
NodeMapMap::const_iterator i = newClassMaps_.constFind(key); NodeMapMap::const_iterator i = newClassMaps_.constFind(key);
if (i != newClassMaps_.constEnd()) if (i != newClassMaps_.constEnd())
return i.value(); return i.value();
@ -1228,8 +1270,10 @@ const NodeMap& QDocDatabase::getClassMap(const QString& key) const
reference to the value, which is a NodeMap. If the \a key is not reference to the value, which is a NodeMap. If the \a key is not
found, return a reference to an empty NodeMap. found, return a reference to an empty NodeMap.
*/ */
const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key) const const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key)
{ {
if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
processForest(&QDocDatabase::findAllSince);
NodeMapMap::const_iterator i = newQmlTypeMaps_.constFind(key); NodeMapMap::const_iterator i = newQmlTypeMaps_.constFind(key);
if (i != newQmlTypeMaps_.constEnd()) if (i != newQmlTypeMaps_.constEnd())
return i.value(); return i.value();
@ -1241,8 +1285,10 @@ const NodeMap& QDocDatabase::getQmlTypeMap(const QString& key) const
a reference to the value, which is a NodeMultiMap. If \a key a reference to the value, which is a NodeMultiMap. If \a key
is not found, return a reference to an empty NodeMultiMap. is not found, return a reference to an empty NodeMultiMap.
*/ */
const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key) const const NodeMultiMap& QDocDatabase::getSinceMap(const QString& key)
{ {
if (newSinceMaps_.isEmpty() && newClassMaps_.isEmpty() && newQmlTypeMaps_.isEmpty())
processForest(&QDocDatabase::findAllSince);
NodeMultiMapMap::const_iterator i = newSinceMaps_.constFind(key); NodeMultiMapMap::const_iterator i = newSinceMaps_.constFind(key);
if (i != newSinceMaps_.constEnd()) if (i != newSinceMaps_.constEnd())
return i.value(); return i.value();
@ -1319,7 +1365,7 @@ void QDocDatabase::resolveQmlInheritance(InnerNode* root)
if ((qcn->qmlBaseNode() == 0) && !qcn->qmlBaseName().isEmpty()) { if ((qcn->qmlBaseNode() == 0) && !qcn->qmlBaseName().isEmpty()) {
QmlClassNode* bqcn = 0; QmlClassNode* bqcn = 0;
if (qcn->qmlBaseName().contains("::")) { if (qcn->qmlBaseName().contains("::")) {
bqcn = qmlTypeMap_.value(qcn->qmlBaseName()); bqcn = forest_.lookupQmlType(qcn->qmlBaseName());
} }
else { else {
const ImportList& imports = qcn->importList(); const ImportList& imports = qcn->importList();
@ -1442,4 +1488,129 @@ Node* QDocDatabase::findNodeInOpenNamespace(QStringList& path,
return n; return n;
} }
/*!
Finds all the collection nodes of type \a nt into the
collection node map \a cnn. Nodes that match \a relative
are not included.
*/
void QDocDatabase::mergeCollections(Node::Type nt, CNMap& cnm, const Node* relative)
{
QRegExp singleDigit("\\b([0-9])\\b");
CNMultiMap cnmm;
forest_.mergeCollectionMaps(nt, cnmm);
cnm.clear();
if (cnmm.isEmpty())
return;
QStringList keys = cnmm.uniqueKeys();
foreach (QString key, keys) {
QList<CollectionNode*> values = cnmm.values(key);
CollectionNode* n = 0;
foreach (CollectionNode* v, values) {
if (v && v->wasSeen() && (v != relative)) {
n = v;
break;
}
}
if (n) {
if (values.size() > 1) {
foreach (CollectionNode* v, values) {
if (v != n) {
foreach (Node* t, v->members())
n->addMember(t);
}
}
}
if (!n->members().isEmpty()) {
QString sortKey = n->fullTitle().toLower();
if (sortKey.startsWith("the "))
sortKey.remove(0, 4);
sortKey.replace(singleDigit, "0\\1");
cnm.insert(sortKey, n);
}
}
}
}
/*!
Finds all the collection nodes with the same name
and type as \a cn and merges their members into the
members list of \a cn.
*/
void QDocDatabase::mergeCollections(CollectionNode* cn)
{
CollectionList cl;
forest_.getCorrespondingCollections(cn, cl);
if (!cl.empty()) {
foreach (CollectionNode* v, cl) {
if (v != cn) {
foreach (Node* t, v->members())
cn->addMember(t);
}
}
}
}
QT_END_NAMESPACE QT_END_NAMESPACE
#if 0
void getAllGroups(CNMM& t);
void getAllModules(CNMM& t);
void getAllQmlModules(CNMM& t);
/*!
For each tree in the forest, get the group map from the tree.
Insert each pair from the group map into the collection node
multimap \a t.
*/
void QDocForest::getAllGroups(CNMM& t)
{
foreach (Tree* t, searchOrder()) {
const GroupMap& gm = t->groups();
if (!gm.isEmpty()) {
GroupMap::const_iterator i = gm.begin();
while (i != gm.end()) {
t.insert(i.key(), i.value());
++i;
}
}
}
}
/*!
For each tree in the forest, get the module map from the tree.
Insert each pair from the module map into the collection node
multimap \a t.
*/
void QDocForest::getAllModules(CNMM& t)
{
foreach (Tree* t, searchOrder()) {
const ModuleMap& mm = t->modules();
if (!mm.isEmpty()) {
ModuleMap::const_iterator i = mm.begin();
while (i != mm.end()) {
t.insert(i.key(), i.value());
++i;
}
}
}
}
/*!
For each tree in the forest, get the QML module map from the
tree. Insert each pair from the QML module map into the
collection node multimap \a t.
*/
void QDocForest::getAllQmlModules(CNMM& t)
{
foreach (Tree* t, searchOrder()) {
const QmlModuleMap& qmm = t->groups();
if (!qmm.isEmpty()) {
QmlModuleMap::const_iterator i = qmm.begin();
while (i != qmm.end()) {
t.insert(i.key(), i.value());
++i;
}
}
}
}
#endif

View File

@ -50,12 +50,11 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
typedef QMap<QString, DocNode*> DocNodeMap;
typedef QMap<QString, QmlClassNode*> QmlTypeMap;
typedef QMap<QString, NodeMap> NodeMapMap; typedef QMap<QString, NodeMap> NodeMapMap;
typedef QMap<QString, NodeMultiMap> NodeMultiMapMap; typedef QMap<QString, NodeMultiMap> NodeMultiMapMap;
typedef QMultiMap<QString, Node*> QDocMultiMap; typedef QMultiMap<QString, Node*> QDocMultiMap;
typedef QMap<Text, const Node*> TextToNodeMap; typedef QMap<Text, const Node*> TextToNodeMap;
typedef QList<CollectionNode*> CollectionList;
class Atom; class Atom;
class Generator; class Generator;
@ -81,17 +80,16 @@ class QDocForest
Tree* nextTree(); Tree* nextTree();
Tree* primaryTree() { return primaryTree_; } Tree* primaryTree() { return primaryTree_; }
NamespaceNode* primaryTreeRoot() { return (primaryTree_ ? primaryTree_->root() : 0); } NamespaceNode* primaryTreeRoot() { return (primaryTree_ ? primaryTree_->root() : 0); }
bool isEmpty() const { return searchOrder_.isEmpty(); } bool isEmpty() { return searchOrder().isEmpty(); }
bool done() const { return (currentIndex_ >= searchOrder_.size()); } bool done() { return (currentIndex_ >= searchOrder().size()); }
const QVector<Tree*>& searchOrder(); const QVector<Tree*>& searchOrder();
const QVector<Tree*>& indexSearchOrder();
void setSearchOrder(); void setSearchOrder();
const Node* findNode(const QStringList& path, const Node* relative, int findFlags) { const Node* findNode(const QStringList& path, const Node* relative, int findFlags) {
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
const Node* n = t->findNode(path, relative, findFlags); const Node* n = t->findNode(path, relative, findFlags);
if (n) { if (n) return n;
return n;
}
relative = 0; relative = 0;
} }
if (Config::debug_) if (Config::debug_)
@ -103,11 +101,9 @@ class QDocForest
Node::Type type, Node::Type type,
Node::SubType subtype, Node::SubType subtype,
bool acceptCollision = false) { bool acceptCollision = false) {
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
Node* n = t->findNodeByNameAndType(path, type, subtype, acceptCollision); Node* n = t->findNodeByNameAndType(path, type, subtype, acceptCollision);
if (n) { if (n) return n;
return n;
}
} }
if (Config::debug_) if (Config::debug_)
qDebug() << "FAILED SEARCH 2" << path << type << subtype; qDebug() << "FAILED SEARCH 2" << path << type << subtype;
@ -115,11 +111,9 @@ class QDocForest
} }
ClassNode* findClassNode(const QStringList& path) { ClassNode* findClassNode(const QStringList& path) {
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
ClassNode* n = t->findClassNode(path); ClassNode* n = t->findClassNode(path);
if (n) { if (n) return n;
return n;
}
} }
if (Config::debug_) if (Config::debug_)
qDebug() << "FAILED SEARCH 3" << path; qDebug() << "FAILED SEARCH 3" << path;
@ -127,11 +121,9 @@ class QDocForest
} }
InnerNode* findRelatesNode(const QStringList& path) { InnerNode* findRelatesNode(const QStringList& path) {
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
InnerNode* n = t->findRelatesNode(path); InnerNode* n = t->findRelatesNode(path);
if (n) { if (n) return n;
return n;
}
} }
if (Config::debug_) if (Config::debug_)
qDebug() << "FAILED SEARCH 4" << path; qDebug() << "FAILED SEARCH 4" << path;
@ -140,11 +132,9 @@ class QDocForest
const Node* resolveTarget(const QString& target, const Node* relative) { const Node* resolveTarget(const QString& target, const Node* relative) {
const Node* r = relative; const Node* r = relative;
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
const Node* n = resolveTargetHelper(target, relative, t); const Node* n = resolveTargetHelper(target, relative, t);
if (n) { if (n) return n;
return n;
}
relative = 0; relative = 0;
} }
if (Config::debug_) { if (Config::debug_) {
@ -155,11 +145,9 @@ class QDocForest
const Node* resolveType(const QStringList& path, const Node* relative) const Node* resolveType(const QStringList& path, const Node* relative)
{ {
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
const Node* n = resolveTypeHelper(path, relative, t); const Node* n = resolveTypeHelper(path, relative, t);
if (n) { if (n) return n;
return n;
}
relative = 0; relative = 0;
} }
if (Config::debug_) if (Config::debug_)
@ -167,13 +155,11 @@ class QDocForest
return 0; return 0;
} }
QString findTarget(const QString& target, const Node* node) const QString findTarget(const QString& target, const Node* node)
{ {
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
QString ref = t->findTarget(target, node); QString ref = t->findTarget(target, node);
if (!ref.isEmpty()) { if (!ref.isEmpty()) return ref;
return ref;
}
} }
if (Config::debug_) if (Config::debug_)
qDebug() << "FAILED SEARCH 7" << target; qDebug() << "FAILED SEARCH 7" << target;
@ -182,30 +168,44 @@ class QDocForest
const Node* findUnambiguousTarget(const QString& target, QString& ref, const Node* relative) const Node* findUnambiguousTarget(const QString& target, QString& ref, const Node* relative)
{ {
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
const Node* n = t->findUnambiguousTarget(target, ref, relative); const Node* n = t->findUnambiguousTarget(target, ref, relative);
if (n) { if (n) return n;
return n;
}
} }
if (Config::debug_) if (Config::debug_)
qDebug() << "FAILED SEARCH 8" << target; qDebug() << "FAILED SEARCH 8" << target;
return 0; return 0;
} }
const DocNode* findDocNodeByTitle(const QString& title, const Node* relative) const const DocNode* findDocNodeByTitle(const QString& title, const Node* relative)
{ {
foreach (Tree* t, searchOrder_) { foreach (Tree* t, searchOrder()) {
const DocNode* n = t->findDocNodeByTitle(title, relative); const DocNode* n = t->findDocNodeByTitle(title, relative);
if (n) { if (n) return n;
return n;
}
} }
if (Config::debug_) if (Config::debug_)
qDebug() << "FAILED SEARCH 9" << title; qDebug() << "FAILED SEARCH 9" << title;
return 0; return 0;
} }
QmlClassNode* lookupQmlType(const QString& name)
{
foreach (Tree* t, searchOrder()) {
QmlClassNode* qcn = t->lookupQmlType(name);
if (qcn) return qcn;
}
return 0;
}
void mergeCollectionMaps(Node::Type nt, CNMultiMap& cnmm);
void getCorrespondingCollections(CollectionNode* cn, CollectionList& cl)
{
foreach (Tree* t, searchOrder()) {
CollectionNode* ccn = t->getCorrespondingCollection(cn);
if (ccn)
cl.append(ccn);
}
}
private: private:
void newPrimaryTree(const QString& module); void newPrimaryTree(const QString& module);
NamespaceNode* newIndexTree(const QString& module); NamespaceNode* newIndexTree(const QString& module);
@ -218,6 +218,7 @@ class QDocForest
int currentIndex_; int currentIndex_;
QMap<QString, Tree*> forest_; QMap<QString, Tree*> forest_;
QVector<Tree*> searchOrder_; QVector<Tree*> searchOrder_;
QVector<Tree*> indexSearchOrder_;
QVector<QString> moduleNames_; QVector<QString> moduleNames_;
}; };
@ -230,50 +231,59 @@ class QDocDatabase
static void destroyQdocDB(); static void destroyQdocDB();
~QDocDatabase(); ~QDocDatabase();
const DocNodeMap& groups() const { return groups_; } const CNMap& groups() { return primaryTree()->groups(); }
//const DocNodeMap& modules() const { return modules_; } // not used const CNMap& modules() { return primaryTree()->modules(); }
//const DocNodeMap& qmlModules() const { return qmlModules_; } // not used const CNMap& qmlModules() { return primaryTree()->qmlModules(); }
DocNode* getGroup(const QString& name); GroupNode* getGroup(const QString& name) { return primaryTree()->getGroup(name); }
DocNode* findGroup(const QString& name); GroupNode* findGroup(const QString& name) { return primaryTree()->findGroup(name); }
DocNode* findModule(const QString& name); ModuleNode* findModule(const QString& name) { return primaryTree()->findModule(name); }
QmlModuleNode* findQmlModule(const QString& name); QmlModuleNode* findQmlModule(const QString& name) { return primaryTree()->findQmlModule(name); }
DocNode* addGroup(const QString& name); GroupNode* addGroup(const QString& name) { return primaryTree()->addGroup(name); }
DocNode* addModule(const QString& name); ModuleNode* addModule(const QString& name) { return primaryTree()->addModule(name); }
QmlModuleNode* addQmlModule(const QString& name); QmlModuleNode* addQmlModule(const QString& name) { return primaryTree()->addQmlModule(name); }
DocNode* addToGroup(const QString& name, Node* node); GroupNode* addToGroup(const QString& name, Node* node) {
DocNode* addToModule(const QString& name, Node* node); return primaryTree()->addToGroup(name, node);
void addToQmlModule(const QString& name, Node* node); }
ModuleNode* addToModule(const QString& name, Node* node) {
return primaryTree()->addToModule(name, node);
}
QmlModuleNode* addToQmlModule(const QString& name, Node* node) {
return primaryTree()->addToQmlModule(name, node);
}
void addExampleNode(ExampleNode* n) { primaryTree()->addExampleNode(n); }
ExampleNodeMap& exampleNodeMap() { return primaryTree()->exampleNodeMap(); }
QmlClassNode* findQmlType(const QString& qmid, const QString& name); QmlClassNode* findQmlType(const QString& qmid, const QString& name);
QmlClassNode* findQmlType(const ImportRec& import, const QString& name) const; QmlClassNode* findQmlType(const ImportRec& import, const QString& name);
private:
void findAllClasses(InnerNode *node); void findAllClasses(InnerNode *node);
void findAllFunctions(InnerNode *node); void findAllFunctions(InnerNode *node);
void findAllLegaleseTexts(InnerNode *node); void findAllLegaleseTexts(InnerNode *node);
void findAllNamespaces(InnerNode *node); void findAllNamespaces(InnerNode *node);
void findAllObsoleteThings(InnerNode* node); void findAllObsoleteThings(InnerNode* node);
void findAllSince(InnerNode *node); void findAllSince(InnerNode *node);
void buildCollections();
public:
// special collection access functions // special collection access functions
NodeMap& getCppClasses() { return nonCompatClasses_; } NodeMap& getCppClasses();
NodeMap& getMainClasses() { return mainClasses_; } NodeMap& getMainClasses();
NodeMap& getCompatibilityClasses() { return compatClasses_; } NodeMap& getCompatibilityClasses();
NodeMap& getObsoleteClasses() { return obsoleteClasses_; } NodeMap& getObsoleteClasses();
NodeMap& getClassesWithObsoleteMembers() { return classesWithObsoleteMembers_; } NodeMap& getClassesWithObsoleteMembers();
NodeMap& getObsoleteQmlTypes() { return obsoleteQmlTypes_; } NodeMap& getObsoleteQmlTypes();
NodeMap& getQmlTypesWithObsoleteMembers() { return qmlTypesWithObsoleteMembers_; } NodeMap& getQmlTypesWithObsoleteMembers();
NodeMap& getNamespaces() { return namespaceIndex_; } NodeMap& getNamespaces();
NodeMap& getServiceClasses() { return serviceClasses_; } NodeMap& getServiceClasses();
NodeMap& getQmlTypes() { return qmlClasses_; } NodeMap& getQmlTypes();
NodeMapMap& getFunctionIndex() { return funcIndex_; } NodeMapMap& getFunctionIndex();
TextToNodeMap& getLegaleseTexts() { return legaleseTexts_; } TextToNodeMap& getLegaleseTexts();
const NodeMap& getClassMap(const QString& key) const; const NodeMap& getClassMap(const QString& key);
const NodeMap& getQmlTypeMap(const QString& key) const; const NodeMap& getQmlTypeMap(const QString& key);
const NodeMultiMap& getSinceMap(const QString& key) const; const NodeMultiMap& getSinceMap(const QString& key);
/* convenience functions /* convenience functions
Many of these will be either eliminated or replaced. Many of these will be either eliminated or replaced.
@ -312,7 +322,7 @@ class QDocDatabase
********************************************************************/ ********************************************************************/
ClassNode* findClassNode(const QStringList& path) { return forest_.findClassNode(path); } ClassNode* findClassNode(const QStringList& path) { return forest_.findClassNode(path); }
InnerNode* findRelatesNode(const QStringList& path) { return forest_.findRelatesNode(path); } InnerNode* findRelatesNode(const QStringList& path) { return forest_.findRelatesNode(path); }
QString findTarget(const QString& target, const Node* node) const { QString findTarget(const QString& target, const Node* node) {
return forest_.findTarget(target, node); return forest_.findTarget(target, node);
} }
const Node* resolveTarget(const QString& target, const Node* relative) { const Node* resolveTarget(const QString& target, const Node* relative) {
@ -320,7 +330,7 @@ class QDocDatabase
} }
const Node* resolveType(const QString& type, const Node* relative); const Node* resolveType(const QString& type, const Node* relative);
const Node* findNodeForTarget(const QString& target, const Node* relative); const Node* findNodeForTarget(const QString& target, const Node* relative);
const DocNode* findDocNodeByTitle(const QString& title, const Node* relative = 0) const { const DocNode* findDocNodeByTitle(const QString& title, const Node* relative = 0) {
return forest_.findDocNodeByTitle(title, relative); return forest_.findDocNodeByTitle(title, relative);
} }
const Node* findUnambiguousTarget(const QString& target, QString& ref, const Node* relative) { const Node* findUnambiguousTarget(const QString& target, QString& ref, const Node* relative) {
@ -359,10 +369,8 @@ class QDocDatabase
NamespaceNode* newIndexTree(const QString& module) { return forest_.newIndexTree(module); } NamespaceNode* newIndexTree(const QString& module) { return forest_.newIndexTree(module); }
const QVector<Tree*>& searchOrder() { return forest_.searchOrder(); } const QVector<Tree*>& searchOrder() { return forest_.searchOrder(); }
void setSearchOrder() { forest_.setSearchOrder(); } void setSearchOrder() { forest_.setSearchOrder(); }
void mergeCollections(Node::Type nt, CNMap& cnm, const Node* relative);
/* debugging functions */ void mergeCollections(CollectionNode* cn);
void printModules() const;
void printQmlModules() const;
private: private:
friend class QDocIndexFiles; friend class QDocIndexFiles;
@ -385,12 +393,7 @@ class QDocDatabase
static NodeMap typeNodeMap_; static NodeMap typeNodeMap_;
bool showInternal_; bool showInternal_;
QString version_; QString version_;
QDocMultiMap masterMap_;
QDocForest forest_; QDocForest forest_;
DocNodeMap groups_;
DocNodeMap modules_;
DocNodeMap qmlModules_;
QmlTypeMap qmlTypeMap_;
NodeMap nonCompatClasses_; NodeMap nonCompatClasses_;
NodeMap mainClasses_; NodeMap mainClasses_;

View File

@ -282,6 +282,31 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
FunctionNode* fn = new FunctionNode(t, parent, name, attached); FunctionNode* fn = new FunctionNode(t, parent, name, attached);
node = fn; node = fn;
} }
else if (element.nodeName() == "group") {
GroupNode* gn = qdb_->addGroup(name);
gn->setTitle(element.attribute("title"));
gn->setSubTitle(element.attribute("subtitle"));
if (element.attribute("seen") == "true")
gn->markSeen();
node = gn;
}
else if (element.nodeName() == "module") {
ModuleNode* mn = qdb_->addModule(name);
mn->setTitle(element.attribute("title"));
mn->setSubTitle(element.attribute("subtitle"));
if (element.attribute("seen") == "true")
mn->markSeen();
node = mn;
}
else if (element.nodeName() == "qmlmodule") {
QString t = element.attribute("qml-module-name") + " " + element.attribute("qml-module-version");
QmlModuleNode* qmn = qdb_->addQmlModule(t);
qmn->setTitle(element.attribute("title"));
qmn->setSubTitle(element.attribute("subtitle"));
if (element.attribute("seen") == "true")
qmn->markSeen();
node = qmn;
}
else if (element.nodeName() == "page") { else if (element.nodeName() == "page") {
Node::SubType subtype; Node::SubType subtype;
Node::PageType ptype = Node::NoPageType; Node::PageType ptype = Node::NoPageType;
@ -298,18 +323,6 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
subtype = Node::File; subtype = Node::File;
ptype = Node::NoPageType; ptype = Node::NoPageType;
} }
else if (attr == "group") {
subtype = Node::Group;
ptype = Node::OverviewPage;
}
else if (attr == "module") {
subtype = Node::Module;
ptype = Node::OverviewPage;
}
else if (attr == "qmlmodule") {
subtype = Node::QmlModule;
ptype = Node::OverviewPage;
}
else if (attr == "page") { else if (attr == "page") {
subtype = Node::Page; subtype = Node::Page;
ptype = Node::ArticlePage; ptype = Node::ArticlePage;
@ -329,14 +342,7 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
else else
return; return;
DocNode* docNode = 0; DocNode* docNode = new DocNode(parent, name, subtype, ptype);
if (subtype == Node::QmlModule) {
QString t = element.attribute("qml-module-name") + " " +
element.attribute("qml-module-version");
docNode = qdb_->addQmlModule(t);
}
else
docNode = new DocNode(parent, name, subtype, ptype);
docNode->setTitle(element.attribute("title")); docNode->setTitle(element.attribute("title"));
if (element.hasAttribute("location")) if (element.hasAttribute("location"))
@ -540,17 +546,8 @@ void QDocIndexFiles::readIndexSection(const QDomElement& element,
QString groupsAttr = element.attribute("groups"); QString groupsAttr = element.attribute("groups");
if (!groupsAttr.isEmpty()) { if (!groupsAttr.isEmpty()) {
QStringList groupNames = groupsAttr.split(","); QStringList groupNames = groupsAttr.split(",");
for (int i=0; i<groupNames.size(); ++i) { foreach (QString name, groupNames) {
DocNode* dn = qdb_->findGroup(groupNames[i]); qdb_->addToGroup(name, node);
if (dn) {
dn->addMember(node);
}
#if 0
else {
qDebug() << "NODE:" << node->name() << "GROUPS:" << groupNames;
qDebug() << "DID NOT FIND GROUP:" << dn->name() << "for:" << node->name();
}
#endif
} }
} }
@ -633,38 +630,6 @@ void QDocIndexFiles::resolveIndex()
} }
} }
/*!
Normally this is used for writing the \e groups attribute,
but it can be used for writing any attribute with a list
value that comes from some subset of the members of \a n.
\note The members of \a n are \e not the children of \a n.
The names we want to include are the names of the members
of \a n that have node type \a t and node subtype \a st.
The attribute name is \a attr. The names are joined with
the space character and written with \a writer.
*/
void QDocIndexFiles::writeMembersAttribute(QXmlStreamWriter& writer,
const InnerNode* n,
Node::Type t,
Node::SubType st,
const QString& attr)
{
const NodeList& members = n->members();
if (!members.isEmpty()) {
QStringList names;
NodeList::ConstIterator i = members.constBegin();
while (i != members.constEnd()) {
if ((*i)->type() == t && (*i)->subType() == st)
names.append((*i)->name());
++i;
}
if (!names.isEmpty())
writer.writeAttribute(attr, names.join(","));
}
}
/*! /*!
Generate the index section with the given \a writer for the \a node Generate the index section with the given \a writer for the \a node
specified, returning true if an element was written; otherwise returns specified, returning true if an element was written; otherwise returns
@ -703,6 +668,15 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
else if (node->subType() == Node::QmlBasicType) else if (node->subType() == Node::QmlBasicType)
nodeName = "qmlbasictype"; nodeName = "qmlbasictype";
break; break;
case Node::Group:
nodeName = "group";
break;
case Node::Module:
nodeName = "module";
break;
case Node::QmlModule:
nodeName = "qmlmodule";
break;
case Node::Enum: case Node::Enum:
nodeName = "enum"; nodeName = "enum";
break; break;
@ -776,7 +750,10 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
QXmlStreamAttributes attributes; QXmlStreamAttributes attributes;
if (node->type() != Node::Document) { if ((node->type() != Node::Document) &&
(node->type() != Node::Group) &&
(node->type() != Node::Module) &&
(node->type() != Node::QmlModule)) {
QString threadSafety; QString threadSafety;
switch (node->threadSafeness()) { switch (node->threadSafeness()) {
case Node::NonReentrant: case Node::NonReentrant:
@ -860,10 +837,15 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (!href.isEmpty()) if (!href.isEmpty())
writer.writeAttribute("href", href); writer.writeAttribute("href", href);
writer.writeAttribute("access", access);
writer.writeAttribute("status", status); writer.writeAttribute("status", status);
if ((node->type() != Node::Document) &&
(node->type() != Node::Group) &&
(node->type() != Node::Module) &&
(node->type() != Node::QmlModule)) {
writer.writeAttribute("access", access);
if (node->isAbstract()) if (node->isAbstract())
writer.writeAttribute("abstract", "true"); writer.writeAttribute("abstract", "true");
}
if (!node->location().fileName().isEmpty()) if (!node->location().fileName().isEmpty())
writer.writeAttribute("location", node->location().fileName()); writer.writeAttribute("location", node->location().fileName());
if (!node->location().filePath().isEmpty()) { if (!node->location().filePath().isEmpty()) {
@ -875,7 +857,7 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("since", node->since()); writer.writeAttribute("since", node->since());
} }
QString brief = node->doc().briefText().toString(); QString brief = node->doc().trimmedBriefText(node->name()).toString();
switch (node->type()) { switch (node->type()) {
case Node::Class: case Node::Class:
{ {
@ -892,7 +874,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(",")); writer.writeAttribute("bases", QStringList(baseStrings.toList()).join(","));
if (!node->moduleName().isEmpty()) if (!node->moduleName().isEmpty())
writer.writeAttribute("module", node->moduleName()); writer.writeAttribute("module", node->moduleName());
writeMembersAttribute(writer, classNode, Node::Document, Node::Group, "groups"); if (!classNode->groupNames().isEmpty())
writer.writeAttribute("groups", classNode->groupNames().join(","));
if (!brief.isEmpty()) if (!brief.isEmpty())
writer.writeAttribute("brief", brief); writer.writeAttribute("brief", brief);
} }
@ -902,7 +885,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
const NamespaceNode* namespaceNode = static_cast<const NamespaceNode*>(node); const NamespaceNode* namespaceNode = static_cast<const NamespaceNode*>(node);
if (!namespaceNode->moduleName().isEmpty()) if (!namespaceNode->moduleName().isEmpty())
writer.writeAttribute("module", namespaceNode->moduleName()); writer.writeAttribute("module", namespaceNode->moduleName());
writeMembersAttribute(writer, namespaceNode, Node::Document, Node::Group, "groups"); if (!namespaceNode->groupNames().isEmpty())
writer.writeAttribute("groups", namespaceNode->groupNames().join(","));
if (!brief.isEmpty()) if (!brief.isEmpty())
writer.writeAttribute("brief", brief); writer.writeAttribute("brief", brief);
} }
@ -910,8 +894,8 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::Document: case Node::Document:
{ {
/* /*
Document nodes (such as manual pages) contain subtypes, Document nodes (such as manual pages) have a subtype,
titles and other attributes. a title, and other attributes.
*/ */
bool writeModuleName = false; bool writeModuleName = false;
const DocNode* docNode = static_cast<const DocNode*>(node); const DocNode* docNode = static_cast<const DocNode*>(node);
@ -927,26 +911,6 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
case Node::File: case Node::File:
writer.writeAttribute("subtype", "file"); writer.writeAttribute("subtype", "file");
break; break;
case Node::Group:
{
writer.writeAttribute("subtype", "group");
writer.writeAttribute("seen", docNode->wasSeen() ? "true" : "false");
// Groups contain information about their group members.
const NodeList& members = docNode->members();
QStringList names;
foreach (const Node* member, members) {
names.append(member->name());
}
writer.writeAttribute("members", names.join(","));
writeModuleName = true;
}
break;
case Node::Module:
writer.writeAttribute("subtype", "module");
break;
case Node::QmlModule:
writer.writeAttribute("subtype", "qmlmodule");
break;
case Node::Page: case Node::Page:
writer.writeAttribute("subtype", "page"); writer.writeAttribute("subtype", "page");
writeModuleName = true; writeModuleName = true;
@ -969,7 +933,82 @@ bool QDocIndexFiles::generateIndexSection(QXmlStreamWriter& writer,
if (!node->moduleName().isEmpty() && writeModuleName) { if (!node->moduleName().isEmpty() && writeModuleName) {
writer.writeAttribute("module", node->moduleName()); writer.writeAttribute("module", node->moduleName());
} }
writeMembersAttribute(writer, docNode, Node::Document, Node::Group, "groups"); if (!docNode->groupNames().isEmpty())
writer.writeAttribute("groups", docNode->groupNames().join(","));
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
break;
case Node::Group:
{
const GroupNode* gn = static_cast<const GroupNode*>(node);
writer.writeAttribute("seen", gn->wasSeen() ? "true" : "false");
writer.writeAttribute("title", gn->title());
if (!gn->subTitle().isEmpty())
writer.writeAttribute("subtitle", gn->subTitle());
if (!gn->moduleName().isEmpty())
writer.writeAttribute("module", gn->moduleName());
if (!gn->groupNames().isEmpty())
writer.writeAttribute("groups", gn->groupNames().join(","));
/*
This is not read back in, so it probably
shouldn't be written out in the first place.
*/
if (!gn->members().isEmpty()) {
QStringList names;
foreach (const Node* member, gn->members())
names.append(member->name());
writer.writeAttribute("members", names.join(","));
}
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
break;
case Node::Module:
{
const ModuleNode* mn = static_cast<const ModuleNode*>(node);
writer.writeAttribute("seen", mn->wasSeen() ? "true" : "false");
writer.writeAttribute("title", mn->title());
if (!mn->subTitle().isEmpty())
writer.writeAttribute("subtitle", mn->subTitle());
if (!mn->moduleName().isEmpty())
writer.writeAttribute("module", mn->moduleName());
if (!mn->groupNames().isEmpty())
writer.writeAttribute("groups", mn->groupNames().join(","));
/*
This is not read back in, so it probably
shouldn't be written out in the first place.
*/
if (!mn->members().isEmpty()) {
QStringList names;
foreach (const Node* member, mn->members())
names.append(member->name());
writer.writeAttribute("members", names.join(","));
}
if (!brief.isEmpty())
writer.writeAttribute("brief", brief);
}
case Node::QmlModule:
{
const QmlModuleNode* qmn = static_cast<const QmlModuleNode*>(node);
writer.writeAttribute("seen", qmn->wasSeen() ? "true" : "false");
writer.writeAttribute("title", qmn->title());
if (!qmn->subTitle().isEmpty())
writer.writeAttribute("subtitle", qmn->subTitle());
if (!qmn->moduleName().isEmpty())
writer.writeAttribute("module", qmn->moduleName());
if (!qmn->groupNames().isEmpty())
writer.writeAttribute("groups", qmn->groupNames().join(","));
/*
This is not read back in, so it probably
shouldn't be written out in the first place.
*/
if (!qmn->members().isEmpty()) {
QStringList names;
foreach (const Node* member, qmn->members())
names.append(member->name());
writer.writeAttribute("members", names.join(","));
}
if (!brief.isEmpty()) if (!brief.isEmpty())
writer.writeAttribute("brief", brief); writer.writeAttribute("brief", brief);
} }
@ -1268,9 +1307,13 @@ void QDocIndexFiles::generateIndexSections(QXmlStreamWriter& writer,
bool generateInternalNodes) bool generateInternalNodes)
{ {
/* /*
Note that the groups are written after all the other nodes. Note that groups, modules, and QML modules are written
after all the other nodes.
*/ */
if (!node->isGroup() && generateIndexSection(writer, node, generateInternalNodes)) { if (node->isGroup() || node->isModule() || node->isQmlModule())
return;
if (generateIndexSection(writer, node, generateInternalNodes)) {
if (node->isInnerNode()) { if (node->isInnerNode()) {
const InnerNode* inner = static_cast<const InnerNode*>(node); const InnerNode* inner = static_cast<const InnerNode*>(node);
@ -1329,14 +1372,16 @@ void QDocIndexFiles::generateIndex(const QString& fileName,
generateIndexSections(writer, qdb_->primaryTreeRoot(), generateInternalNodes); generateIndexSections(writer, qdb_->primaryTreeRoot(), generateInternalNodes);
/* /*
We wait until the end of the index file to output the group elements. We wait until the end of the index file to output the group, module,
By waiting until the end, when we read each group element, its members and QML module elements. By outputting them at the end, when we read
will have already been created. It is then only necessary to create the index file back in, all the group, module, and QML module member
the group page and add each member to its member list. elements will have already been created. It is then only necessary to
create the group, module, or QML module element and add each member to
its member list.
*/ */
const DocNodeMap& groups = qdb_->groups(); const CNMap& groups = qdb_->groups();
if (!groups.isEmpty()) { if (!groups.isEmpty()) {
DocNodeMap::ConstIterator g = groups.constBegin(); CNMap::ConstIterator g = groups.constBegin();
while (g != groups.constEnd()) { while (g != groups.constEnd()) {
if (generateIndexSection(writer, g.value(), generateInternalNodes)) if (generateIndexSection(writer, g.value(), generateInternalNodes))
writer.writeEndElement(); writer.writeEndElement();
@ -1344,6 +1389,26 @@ void QDocIndexFiles::generateIndex(const QString& fileName,
} }
} }
const CNMap& modules = qdb_->modules();
if (!modules.isEmpty()) {
CNMap::ConstIterator g = modules.constBegin();
while (g != modules.constEnd()) {
if (generateIndexSection(writer, g.value(), generateInternalNodes))
writer.writeEndElement();
++g;
}
}
const CNMap& qmlModules = qdb_->qmlModules();
if (!qmlModules.isEmpty()) {
CNMap::ConstIterator g = qmlModules.constBegin();
while (g != qmlModules.constEnd()) {
if (generateIndexSection(writer, g.value(), generateInternalNodes))
writer.writeEndElement();
++g;
}
}
writer.writeEndElement(); // INDEX writer.writeEndElement(); // INDEX
writer.writeEndElement(); // QDOCINDEX writer.writeEndElement(); // QDOCINDEX
writer.writeEndDocument(); writer.writeEndDocument();

View File

@ -76,11 +76,6 @@ class QDocIndexFiles
void resolveIndex(); void resolveIndex();
bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); bool generateIndexSection(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false); void generateIndexSections(QXmlStreamWriter& writer, Node* node, bool generateInternalNodes = false);
void writeMembersAttribute(QXmlStreamWriter& writer,
const InnerNode* n,
Node::Type t,
Node::SubType st,
const QString& attr);
private: private:
static QDocIndexFiles* qdocIndexFiles_; static QDocIndexFiles* qdocIndexFiles_;

View File

@ -376,8 +376,8 @@ void Tree::resolveInheritanceHelper(int pass, ClassNode* cn)
QList<RelatedClass>::iterator b = bases.begin(); QList<RelatedClass>::iterator b = bases.begin();
while (b != bases.end()) { while (b != bases.end()) {
if (!(*b).node_) { if (!(*b).node_) {
InnerNode* parent = cn->parent(); Node* n = qdb_->findClassNode((*b).path_);
Node* n = findClassNode((*b).path_); #if 0
/* /*
If the node for the base class was not found, If the node for the base class was not found,
the reason might be that the subclass is in a the reason might be that the subclass is in a
@ -388,10 +388,16 @@ void Tree::resolveInheritanceHelper(int pass, ClassNode* cn)
at the parent of the subclass node (the namespace at the parent of the subclass node (the namespace
node) using the unqualified base class name. node) using the unqualified base class name.
*/ */
if (!n) if (!n) {
InnerNode* parent = cn->parent();
n = findClassNode((*b).path_, parent); n = findClassNode((*b).path_, parent);
if (n) }
(*b).node_ = static_cast<ClassNode*>(n); #endif
if (n) {
ClassNode* bcn = static_cast<ClassNode*>(n);
(*b).node_ = bcn;
bcn->addDerivedClass((*b).access_, cn);
}
} }
++b; ++b;
} }
@ -1015,4 +1021,252 @@ QString Tree::refForAtom(const Atom* atom)
return QString(); return QString();
} }
/*!
\fn const CNMap& Tree::groups() const
Returns a const reference to the collection of all
group nodes.
*/
/*!
\fn const ModuleMap& Tree::modules() const
Returns a const reference to the collection of all
module nodes.
*/
/*!
\fn const QmlModuleMap& Tree::qmlModules() const
Returns a const reference to the collection of all
QML module nodes.
*/
/*!
Returns the collection node in this tree that has the same
name and type as \a cn. Returns 0 if no match is found.
If the matching node is \a cn, return 0.
*/
CollectionNode* Tree::getCorrespondingCollection(CollectionNode* cn)
{
CollectionNode* ccn = 0;
if (cn->isGroup())
ccn = getGroup(cn->name());
else if (cn->isModule())
ccn = getModule(cn->name());
else if (cn->isQmlModule())
ccn = getQmlModule(cn->name());
if (ccn == cn)
ccn = 0;
return ccn;
}
/*!
Find the group node named \a name and return a pointer
to it. If a matching node is not found, return 0.
*/
GroupNode* Tree::getGroup(const QString& name)
{
CNMap::const_iterator i = groups_.find(name);
if (i != groups_.end())
return static_cast<GroupNode*>(i.value());
return 0;
}
/*!
Find the module node named \a name and return a pointer
to it. If a matching node is not found, return 0.
*/
ModuleNode* Tree::getModule(const QString& name)
{
CNMap::const_iterator i = modules_.find(name);
if (i != modules_.end())
return static_cast<ModuleNode*>(i.value());
return 0;
}
/*!
Find the QML module node named \a name and return a pointer
to it. If a matching node is not found, return 0.
*/
QmlModuleNode* Tree::getQmlModule(const QString& name)
{
CNMap::const_iterator i = qmlModules_.find(name);
if (i != qmlModules_.end())
return static_cast<QmlModuleNode*>(i.value());
return 0;
}
/*!
Find the group node named \a name and return a pointer
to it. If the group node is not found, add a new group
node named \a name and return a pointer to the new one.
If a new group node is added, its parent is the tree root,
and the new group node is marked \e{not seen}.
*/
GroupNode* Tree::findGroup(const QString& name)
{
CNMap::const_iterator i = groups_.find(name);
if (i != groups_.end())
return static_cast<GroupNode*>(i.value());;
GroupNode* gn = new GroupNode(root(), name);
gn->markNotSeen();
groups_.insert(name, gn);
return gn;
}
/*!
Find the module node named \a name and return a pointer
to it. If a matching node is not found, add a new module
node named \a name and return a pointer to that one.
If a new module node is added, its parent is the tree root,
and the new module node is marked \e{not seen}.
*/
ModuleNode* Tree::findModule(const QString& name)
{
CNMap::const_iterator i = modules_.find(name);
if (i != modules_.end())
return static_cast<ModuleNode*>(i.value());
ModuleNode* mn = new ModuleNode(root(), name);
mn->markNotSeen();
modules_.insert(name, mn);
return mn;
}
/*!
Find the QML module node named \a name and return a pointer
to it. If a matching node is not found, add a new QML module
node named \a name and return a pointer to that one.
If a new QML module node is added, its parent is the tree root,
and the new QML module node is marked \e{not seen}.
*/
QmlModuleNode* Tree::findQmlModule(const QString& name)
{
CNMap::const_iterator i = qmlModules_.find(name);
if (i != qmlModules_.end())
return static_cast<QmlModuleNode*>(i.value());
QmlModuleNode* qmn = new QmlModuleNode(root(), name);
qmn->markNotSeen();
qmn->setQmlModuleInfo(name);
qmlModules_.insert(name, qmn);
return qmn;
}
/*!
Looks up the group node named \a name in the collection
of all group nodes. If a match is found, a pointer to the
node is returned. Otherwise, a new group node named \a name
is created and inserted into the collection, and the pointer
to that node is returned.
*/
GroupNode* Tree::addGroup(const QString& name)
{
GroupNode* group = findGroup(name);
return group;
}
/*!
Looks up the module node named \a name in the collection
of all module nodes. If a match is found, a pointer to the
node is returned. Otherwise, a new module node named \a name
is created and inserted into the collection, and the pointer
to that node is returned.
*/
ModuleNode* Tree::addModule(const QString& name)
{
ModuleNode* module = findModule(name);
return module;
}
/*!
Looks up the QML module node named \a name in the collection
of all QML module nodes. If a match is found, a pointer to the
node is returned. Otherwise, a new QML module node named \a name
is created and inserted into the collection, and the pointer
to that node is returned.
*/
QmlModuleNode* Tree::addQmlModule(const QString& name)
{
QStringList blankSplit = name.split(QLatin1Char(' '));
QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
qmn->setQmlModuleInfo(name);
return qmn;
}
/*!
Looks up the group node named \a name in the collection
of all group nodes. If a match is not found, a new group
node named \a name is created and inserted into the collection.
Then append \a node to the group's members list, and append the
group name to the list of group names in \a node. The parent of
\a node is not changed by this function. Returns a pointer to
the group node.
*/
GroupNode* Tree::addToGroup(const QString& name, Node* node)
{
GroupNode* gn = findGroup(name);
if (!node->isInternal()) {
gn->addMember(node);
node->appendGroupName(name);
}
return gn;
}
/*!
Looks up the module node named \a name in the collection
of all module nodes. If a match is not found, a new module
node named \a name is created and inserted into the collection.
Then append \a node to the module's members list. The parent of
\a node is not changed by this function. Returns the module node.
*/
ModuleNode* Tree::addToModule(const QString& name, Node* node)
{
ModuleNode* mn = findModule(name);
mn->addMember(node);
node->setModuleName(name);
return mn;
}
/*!
Looks up the QML module named \a name. If it isn't there,
create it. Then append \a node to the QML module's member
list. The parent of \a node is not changed by this function.
Returns the pointer to the QML module node.
*/
QmlModuleNode* Tree::addToQmlModule(const QString& name, Node* node)
{
QStringList qmid;
QStringList dotSplit;
QStringList blankSplit = name.split(QLatin1Char(' '));
qmid.append(blankSplit[0]);
if (blankSplit.size() > 1) {
qmid.append(blankSplit[0] + blankSplit[1]);
dotSplit = blankSplit[1].split(QLatin1Char('.'));
qmid.append(blankSplit[0] + dotSplit[0]);
}
QmlModuleNode* qmn = findQmlModule(blankSplit[0]);
qmn->addMember(node);
node->setQmlModule(qmn);
if (node->subType() == Node::QmlClass) {
QmlClassNode* n = static_cast<QmlClassNode*>(node);
for (int i=0; i<qmid.size(); ++i) {
QString key = qmid[i] + "::" + node->name();
insertQmlType(key, n);
}
}
return qmn;
}
/*!
If the QML type map does not contain \a key, insert node
\a n with the specified \a key.
*/
void Tree::insertQmlType(const QString& key, QmlClassNode* n)
{
if (!qmlTypeMap_.contains(key))
qmlTypeMap_.insert(key,n);
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -65,8 +65,11 @@ struct TargetRec
int priority_; int priority_;
Type type_; Type type_;
}; };
typedef QMultiMap<QString, TargetRec> TargetMap; typedef QMultiMap<QString, TargetRec> TargetMap;
typedef QMultiMap<QString, DocNode*> DocNodeMultiMap; typedef QMultiMap<QString, DocNode*> DocNodeMultiMap;
typedef QMap<QString, QmlClassNode*> QmlTypeMap;
typedef QMultiMap<QString, const ExampleNode*> ExampleNodeMap;
class Tree class Tree
{ {
@ -141,6 +144,40 @@ class Tree
NodeList allBaseClasses(const ClassNode *classe) const; NodeList allBaseClasses(const ClassNode *classe) const;
QString refForAtom(const Atom* atom); QString refForAtom(const Atom* atom);
const CNMap& groups() const { return groups_; }
const CNMap& modules() const { return modules_; }
const CNMap& qmlModules() const { return qmlModules_; }
const CNMap& getCollections(Node::Type t) const {
if (t == Node::Group)
return groups_;
if (t == Node::Module)
return modules_;
return qmlModules_;
}
CollectionNode* getCorrespondingCollection(CollectionNode* cn);
GroupNode* getGroup(const QString& name);
ModuleNode* getModule(const QString& name);
QmlModuleNode* getQmlModule(const QString& name);
GroupNode* findGroup(const QString& name);
ModuleNode* findModule(const QString& name);
QmlModuleNode* findQmlModule(const QString& name);
GroupNode* addGroup(const QString& name);
ModuleNode* addModule(const QString& name);
QmlModuleNode* addQmlModule(const QString& name);
GroupNode* addToGroup(const QString& name, Node* node);
ModuleNode* addToModule(const QString& name, Node* node);
QmlModuleNode* addToQmlModule(const QString& name, Node* node);
QmlClassNode* lookupQmlType(const QString& name) { return qmlTypeMap_.value(name); }
void insertQmlType(const QString& key, QmlClassNode* n);
void addExampleNode(ExampleNode* n) { exampleNodeMap_.insert(n->title(), n); }
ExampleNodeMap& exampleNodeMap() { return exampleNodeMap_; }
public: public:
const QString& moduleName() const { return module_; } const QString& moduleName() const { return module_; }
@ -151,8 +188,11 @@ private:
PropertyMap unresolvedPropertyMap; PropertyMap unresolvedPropertyMap;
DocNodeMultiMap docNodesByTitle_; DocNodeMultiMap docNodesByTitle_;
TargetMap nodesByTarget_; TargetMap nodesByTarget_;
//NodeMap nodesByName_; CNMap groups_;
//NodeMap nodesByTitle_; CNMap modules_;
CNMap qmlModules_;
QmlTypeMap qmlTypeMap_;
ExampleNodeMap exampleNodeMap_;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE