qdoc: Structure the DITA map with a root node.
authorMartin Smith <martin.smith@nokia.com>
Thu, 15 Mar 2012 12:55:37 +0000 (13:55 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 15 Mar 2012 17:05:05 +0000 (18:05 +0100)
The root topicref is now always index.dita, unless
there is no index.dita. But there is always a root
topicref that has the project name as its navtitle,
even if there is no index.dita file to map it to.

Task-number:  Mzilla bug - 7229
Change-Id: I0c9fdf1a2e3ba847fe8975a0745667189a77a755
Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>
src/tools/qdoc/ditaxmlgenerator.cpp
src/tools/qdoc/ditaxmlgenerator.h
src/tools/qdoc/node.h
src/tools/qdoc/pagegenerator.cpp

index b716863..6b0c2dc 100644 (file)
@@ -5722,6 +5722,9 @@ bool DitaXmlGenerator::isDuplicate(NodeMultiMap* nmm, const QString& key, Node*
 /*!
   Collect all the nodes in the tree according to their type or subtype.
 
+  If a node is found that is named index.html, return that node as the
+  root page node.
+
   type: Class
   type: Namespace
 
@@ -5735,159 +5738,117 @@ bool DitaXmlGenerator::isDuplicate(NodeMultiMap* nmm, const QString& key, Node*
   subtype: QML class
   subtype: QML module
  */
-void DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
+Node* DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
 {
-    //qDebug() << "START";
+    Node* rootPageNode = 0;
     const NodeList& children = parent->childNodes();
     if (children.size() == 0)
-        return;
+        return rootPageNode;
 
-    bool related;
     QString message;
     for (int i=0; i<children.size(); ++i) {
         Node* child = children[i];
-        if (!child || child->isInternal() || child->doc().isEmpty())
+        if ((child->type() == Node::Fake) && (child->subType() == Node::Collision)) {
+            const FakeNode* fake = static_cast<const FakeNode*>(child);
+            Node* n = collectNodesByTypeAndSubtype(fake);
+            if (n)
+                rootPageNode = n;
             continue;
-        if (child->relates()) {
-            related = true;
-            message = child->relates()->name();
         }
-        else {
-            related = false;
-            message = "has documentation but no \\relates command";
+        if (!child || child->isInternal() || child->doc().isEmpty())
+            continue;
+
+        if (child->name() == "index.html") {
+            rootPageNode = child;
         }
+
         switch (child->type()) {
         case Node::Namespace:
-            //qDebug() << "NODE: Namespace" << "TITLE:" << child->name()
-            //         << "FILE:" << fileName(child);
             if (!isDuplicate(nodeTypeMaps[Node::Namespace],child->name(),child))
                 nodeTypeMaps[Node::Namespace]->insert(child->name(),child);
             break;
         case Node::Class:
-            //qDebug() << "NODE: Class" << "TITLE:" << child->name()
-            //         << "FILE:" << fileName(child);
             if (!isDuplicate(nodeTypeMaps[Node::Class],child->name(),child))
                 nodeTypeMaps[Node::Class]->insert(child->name(),child);
             break;
         case Node::Fake:
-            //qDebug() << "NODE: Fake";
             switch (child->subType()) {
             case Node::Example:
-                //qDebug() << "FAKE NODE: Example" << "TITLE:" << child->title()
-                //         << "FILE:" << fileName(child);
                 if (!isDuplicate(nodeSubtypeMaps[Node::Example],child->title(),child))
                     nodeSubtypeMaps[Node::Example]->insert(child->title(),child);
                 break;
             case Node::HeaderFile:
-                //qDebug() << "FAKE NODE: Header file" << "TITLE:" << child->title()
-                //         << "FILE:" << fileName(child);
                 if (!isDuplicate(nodeSubtypeMaps[Node::HeaderFile],child->title(),child))
                     nodeSubtypeMaps[Node::HeaderFile]->insert(child->title(),child);
                 break;
             case Node::File:
-                //qDebug() << "FAKE NODE: File";
                 break;
             case Node::Image:
-                //qDebug() << "FAKE NODE: Image";
                 break;
             case Node::Group:
-                //qDebug() << "FAKE NODE: Group" << "TITLE:" << child->title()
-                //         << "FILE:" << fileName(child);
                 if (!isDuplicate(nodeSubtypeMaps[Node::Group],child->title(),child))
                     nodeSubtypeMaps[Node::Group]->insert(child->title(),child);
                 break;
             case Node::Module:
-                //qDebug() << "FAKE NODE: Module" << "TITLE:" << child->title()
-                //         << "FILE:" << fileName(child);
                 if (!isDuplicate(nodeSubtypeMaps[Node::Module],child->title(),child))
                     nodeSubtypeMaps[Node::Module]->insert(child->title(),child);
                 break;
             case Node::Page:
-                //qDebug() << "FAKE NODE: Page" << "PAGE TYPE:" << child->pageTypeString()
-                //         << "TITLE:" << child->title()
-                //         << "FILE:" << fileName(child);
                 if (!isDuplicate(pageTypeMaps[child->pageType()],child->title(),child))
                     pageTypeMaps[child->pageType()]->insert(child->title(),child);
                 break;
             case Node::ExternalPage:
-                //qDebug() << "FAKE NODE: External page" << "TITLE:" << child->title()
-                //         << "FILE:" << fileName(child);
                 if (!isDuplicate(nodeSubtypeMaps[Node::ExternalPage],child->title(),child))
                     nodeSubtypeMaps[Node::ExternalPage]->insert(child->title(),child);
                 break;
             case Node::QmlClass:
-                //qDebug() << "FAKE NODE: QML class" << "TITLE:" << child->title() << "FILE:"
-                //         << fileName(child);
                 if (!isDuplicate(nodeSubtypeMaps[Node::QmlClass],child->title(),child))
                     nodeSubtypeMaps[Node::QmlClass]->insert(child->title(),child);
                 break;
             case Node::QmlPropertyGroup:
-                //qDebug() << "FAKE NODE: QML property group";
                 break;
             case Node::QmlBasicType:
-                //qDebug() << "FAKE NODE: QML basic type" << "TITLE:" << child->title()
-                //         << "FILE:" << fileName(child);
                 if (!isDuplicate(nodeSubtypeMaps[Node::QmlBasicType],child->title(),child))
                     nodeSubtypeMaps[Node::QmlBasicType]->insert(child->title(),child);
                 break;
             case Node::QmlModule:
-                //qDebug() << "FAKE NODE: QML module" << "TITLE:" << child->title()
-                //         << "FILE:" << fileName(child);
                 if (!isDuplicate(nodeSubtypeMaps[Node::QmlModule],child->title(),child))
                     nodeSubtypeMaps[Node::QmlModule]->insert(child->title(),child);
                 break;
             case Node::Collision:
-                //qDebug() << "FAKE NODE: Collision";
+                qDebug() << "FAKE NODE: Collision";
+                if (!isDuplicate(nodeSubtypeMaps[Node::Collision],child->title(),child))
+                    nodeSubtypeMaps[Node::Collision]->insert(child->title(),child);
                 break;
             default:
                 break;
             }
             break;
         case Node::Enum:
-            if (!related)
-                child->location().warning(tr("Global enum, %1, %2").arg(child->name()).arg(message));
             break;
         case Node::Typedef:
-            if (!related)
-                child->location().warning(tr("Global typedef, %1, %2").arg(child->name()).arg(message));
             break;
         case Node::Function:
-            if (!related) {
-                const FunctionNode* fn = static_cast<const FunctionNode*>(child);
-                if (fn->isMacro())
-                    child->location().warning(tr("Global macro, %1, %2").arg(child->name()).arg(message));
-                else
-                    child->location().warning(tr("Global function, %1(), %2").arg(child->name()).arg(message));
-            }
             break;
         case Node::Property:
             break;
         case Node::Variable:
-            if (!related)
-                child->location().warning(tr("Global variable, %1, %2").arg(child->name()).arg(message));
             break;
         case Node::Target:
             break;
         case Node::QmlProperty:
-            if (!related)
-                child->location().warning(tr("Global QML property, %1, %2").arg(child->name()).arg(message));
             break;
         case Node::QmlSignal:
-            if (!related)
-                child->location().warning(tr("Global QML, signal, %1 %2").arg(child->name()).arg(message));
             break;
         case Node::QmlSignalHandler:
-            if (!related)
-                child->location().warning(tr("Global QML signal handler, %1, %2").arg(child->name()).arg(message));
             break;
         case Node::QmlMethod:
-            if (!related)
-                child->location().warning(tr("Global QML method, %1, %2").arg(child->name()).arg(message));
             break;
         default:
             break;
         }
     }
+    return rootPageNode;
 }
 
 /*!
@@ -5896,16 +5857,13 @@ void DitaXmlGenerator::collectNodesByTypeAndSubtype(const InnerNode* parent)
  */
 void DitaXmlGenerator::writeDitaMap(const Tree *tree)
 {
-    beginSubPage(tree->root(),"qt.ditamap");
-
     QString doctype;
-    doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
-    //    doctype = "<!DOCTYPE cxxAPIMap PUBLIC \"-//NOKIA//DTD DITA C++ API Map Reference Type v0.6.0//EN\" \"dtd/cxxAPIMap.dtd\">";
 
+#if 0
+    beginSubPage(tree->root(),"qt.ditamap");
+    doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
     xmlWriter().writeDTD(doctype);
     writeStartTag(DT_map);
-    //xmlWriter().writeAttribute("id","Qt-DITA-Map");
-    //xmlWriter().writeAttribute("title","Qt DITA Map");
     writeStartTag(DT_topicmeta);
     writeStartTag(DT_shortdesc);
     xmlWriter().writeCharacters("The top level map for the Qt documentation");
@@ -5920,6 +5878,7 @@ void DitaXmlGenerator::writeDitaMap(const Tree *tree)
         ++i;
     }
     endSubPage();
+#endif
 
     for (unsigned i=0; i<Node::LastType; ++i)
         nodeTypeMaps[i] = new NodeMultiMap;
@@ -5927,22 +5886,9 @@ void DitaXmlGenerator::writeDitaMap(const Tree *tree)
         nodeSubtypeMaps[i] = new NodeMultiMap;
     for (unsigned i=0; i<Node::OnBeyondZebra; ++i)
         pageTypeMaps[i] = new NodeMultiMap;
-    collectNodesByTypeAndSubtype(tree->root());
-#if 0
-    for (unsigned i=0; i<Node::LastType; ++i) {
-        if (nodeTypeMaps[i] && nodeTypeMaps[i]->size() > 0)
-            qDebug() << "NODE TYPE:" << Node::nodeTypeString(i) << nodeTypeMaps[i]->size();
-    }
-    for (unsigned i=1; i<Node::LastSubtype; ++i) {
-        if (nodeSubtypeMaps[i] && nodeSubtypeMaps[i]->size() > 0)
-            qDebug() << "NODE SUBTYPE:" << Node::nodeSubtypeString(i) << nodeSubtypeMaps[i]->size();
-    }
-    for (unsigned i=1; i<Node::OnBeyondZebra; ++i) {
-        if (pageTypeMaps[i] && pageTypeMaps[i]->size() > 0)
-            qDebug() << "PAGE TYPE:" << Node::pageTypeString(i) << pageTypeMaps[i]->size();
-    }
-#endif
-    beginSubPage(tree->root(),"test.ditamap");
+    Node* rootPageNode = collectNodesByTypeAndSubtype(tree->root());
+
+    beginSubPage(tree->root(),"qt.ditamap");
 
     doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
     xmlWriter().writeDTD(doctype);
@@ -5953,6 +5899,11 @@ void DitaXmlGenerator::writeDitaMap(const Tree *tree)
     writeEndTag(); // </shortdesc>
     writeEndTag(); // </topicmeta>
 
+    writeStartTag(DT_topicref);
+    xmlWriter().writeAttribute("navtitle",project);
+    if (rootPageNode)
+        xmlWriter().writeAttribute("href",fileName(rootPageNode));
+
     writeTopicrefs(pageTypeMaps[Node::OverviewPage], "overviews");
     writeTopicrefs(pageTypeMaps[Node::HowToPage], "howtos");
     writeTopicrefs(pageTypeMaps[Node::TutorialPage], "tutorials");
@@ -5968,6 +5919,7 @@ void DitaXmlGenerator::writeDitaMap(const Tree *tree)
     writeTopicrefs(nodeSubtypeMaps[Node::QmlModule], "QML modules");
     writeTopicrefs(nodeSubtypeMaps[Node::QmlBasicType], "QML basic types");
 
+    writeEndTag(); // </topicref>
     endSubPage();
 
     for (unsigned i=0; i<Node::LastType; ++i)
@@ -5988,8 +5940,6 @@ void DitaXmlGenerator::writeDitaMap(const DitaMapNode* node)
 
     QString doctype;
     doctype = "<!DOCTYPE map PUBLIC \"-//OASIS//DTD DITA Map//EN\" \"map.dtd\">";
-    //    doctype = "<!DOCTYPE cxxAPIMap PUBLIC \"-//NOKIA//DTD DITA C++ API Map Reference Type v0.6.0//EN\" \"dtd/cxxAPIMap.dtd\">";
-
     xmlWriter().writeDTD(doctype);
     writeStartTag(DT_map);
     writeStartTag(DT_topicmeta);
index bc3ed93..b3da02b 100644 (file)
@@ -455,7 +455,7 @@ private:
     int currentSectionNestingLevel() const { return sectionNestingLevel; }
     QString metadataDefault(DitaTag t) const;
     QString stripMarkup(const QString& src) const;
-    void collectNodesByTypeAndSubtype(const InnerNode* parent);
+    Node* collectNodesByTypeAndSubtype(const InnerNode* parent);
     void writeDitaRefs(const DitaRefList& ditarefs);
     void writeTopicrefs(NodeMultiMap* nmm, const QString& navtitle);
     bool isDuplicate(NodeMultiMap* nmm, const QString& key, Node* node);
index 23ee38c..8c6eb67 100644 (file)
@@ -174,6 +174,7 @@ public:
     void setPageType(const QString& t);
     void setParent(InnerNode* n) { parent_ = n; }
     void setIndexNodeFlag() { indexNodeFlag_ = true; }
+    virtual void setOutputFileName(const QString& ) { }
 
     virtual bool isInnerNode() const = 0;
     virtual bool isReimp() const { return false; }
@@ -194,6 +195,7 @@ public:
     QString moduleName() const;
     QString url() const;
     virtual QString nameForLists() const { return name_; }
+    virtual QString outputFileName() const { return QString(); }
 
     Access access() const { return access_; }
     QString accessString() const;
@@ -324,6 +326,8 @@ public:
     virtual void addPageKeywords(const QString& t) { pageKeywds << t; }
     virtual void setCurrentChild() { }
     virtual void setCurrentChild(InnerNode* ) { }
+    virtual void setOutputFileName(const QString& f) { outputFileName_ = f; }
+    virtual QString outputFileName() const { return outputFileName_; }
 
 protected:
     InnerNode(Type type, InnerNode* parent, const QString& name);
@@ -337,6 +341,7 @@ private:
     void removeRelated(Node* pseudoChild);
     void removeChild(Node* child);
 
+    QString outputFileName_;
     QStringList pageKeywds;
     QStringList inc;
     NodeList children;
index d8c3bab..6a52b77 100644 (file)
@@ -298,6 +298,7 @@ void PageGenerator::beginSubPage(const InnerNode* node, const QString& fileName)
     if (outputCodec)
         out->setCodec(outputCodec);
     outStreamStack.push(out);
+    const_cast<InnerNode*>(node)->setOutputFileName(fileName);
 }
 
 /*!