From e9e93fe79d7451f05a714241f759c557a455de67 Mon Sep 17 00:00:00 2001
From: Martin Smith 
Date: Tue, 15 Jun 2010 14:54:37 +0200
Subject: doc: Added more DITA output to the XML generator
Task-number:  	 QTBUG-11391
---
 tools/qdoc3/ditaxmlgenerator.cpp | 542 ++++++++++-----------------------------
 tools/qdoc3/ditaxmlgenerator.h   |  45 +---
 tools/qdoc3/node.cpp             |  35 +++
 tools/qdoc3/node.h               |   2 +
 4 files changed, 178 insertions(+), 446 deletions(-)
diff --git a/tools/qdoc3/ditaxmlgenerator.cpp b/tools/qdoc3/ditaxmlgenerator.cpp
index 2c578f0..197bc13 100644
--- a/tools/qdoc3/ditaxmlgenerator.cpp
+++ b/tools/qdoc3/ditaxmlgenerator.cpp
@@ -501,6 +501,34 @@ QString DitaXmlGenerator::format()
 }
 
 /*!
+  Create a new GUID, write it to the XML stream
+  as an "id" attribute, and return it.
+ */
+QString DitaXmlGenerator::writeGuidAttribute(QString text)
+{
+    QString guid = QUuid::createUuid().toString();
+    name2guidMap.insert(text,guid);
+    writer.writeAttribute("id",guid);
+    return guid;
+}
+
+/*!
+  Looks up \a text in the GUID map. It it finds \a text,
+  it returns the associated GUID. Otherwise it inserts
+  \a text into the map with a new GUID, and it returns
+  the new GUID.
+ */
+QString DitaXmlGenerator::lookupGuid(QString text)
+{
+    QMap::const_iterator i = name2guidMap.find(text);
+    if (i != name2guidMap.end())
+        return i.value();
+    QString guid = QUuid::createUuid().toString();
+    name2guidMap.insert(text,guid);
+    return guid;
+}
+
+/*!
   This is where the DITA XML files are written.
   \note The file generation is done in the base class,
   PageGenerator::generateTree().
@@ -521,9 +549,6 @@ void DitaXmlGenerator::generateTree(const Tree *tree, CodeMarker *marker)
     findAllFunctions(tree->root());
     findAllLegaleseTexts(tree->root());
     findAllNamespaces(tree->root());
-#ifdef ZZZ_QDOC_QML
-    findAllQmlClasses(tree->root());
-#endif
     findAllSince(tree->root());
 
     PageGenerator::generateTree(tree, marker);
@@ -552,7 +577,8 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
     int skipAhead = 0;
     QString hx;
     static bool in_para = false;
-
+    QString guid;
+    
     switch (atom->type()) {
     case Atom::AbstractLeft:
         break;
@@ -922,10 +948,8 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
                 s = sections.constBegin();
                 while (s != sections.constEnd()) {
                     if (!(*s).members.isEmpty()) {
-                        QString guid = QUuid::createUuid().toString();
-                        guidMap.insert(Doc::canonicalTitle((*s).name),guid);
                         writer.writeStartElement("p");
-                        writer.writeAttribute("id",guid);
+                        writeGuidAttribute(Doc::canonicalTitle((*s).name));
                         writer.writeAttribute("outputclass","h3");
                         writer.writeCharacters(protectEnc((*s).name));
                         writer.writeEndElement(); // 
@@ -1203,10 +1227,11 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
         writer.writeCharacters(atom->string());
         break;
     case Atom::SectionLeft:
-#if zzz        
-        out() << "\n";
-#endif        
+        writer.writeStartElement("p");
+        writeGuidAttribute(Doc::canonicalTitle(Text::sectionHeading(atom).toString()));
+        writer.writeAttribute("outputclass","target");
+        writer.writeCharacters(protectEnc(Text::sectionHeading(atom).toString()));
+        writer.writeEndElement(); // 
         break;
     case Atom::SectionRight:
         // nothing
@@ -1338,20 +1363,23 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
         }
         break;
     case Atom::Target:
-#if zzz        
-        out() << "string()) << "\">";
-#endif
+        writer.writeStartElement("p");
+        writeGuidAttribute(Doc::canonicalTitle(atom->string()));
+        writer.writeAttribute("outputclass","target");
+        writer.writeCharacters(protectEnc(atom->string()));
+        writer.writeEndElement(); // 
         break;
     case Atom::UnhandledFormat:
-#if zzz        
-        out() << "<Missing DITAXML>";
-#endif
+        writer.writeStartElement("b");
+        writer.writeAttribute("outputclass","redFont");
+        writer.writeCharacters("<Missing DITAXML>");
+        writer.writeEndElement(); // 
         break;
     case Atom::UnknownCommand:
-#if zzz        
-        out() << "\\" << protectEnc(atom->string())
-              << "";
-#endif
+        writer.writeStartElement("b");
+        writer.writeAttribute("outputclass","redFont code");
+        writer.writeCharacters(protectEnc(atom->string()));
+        writer.writeEndElement(); // 
         break;
 #ifdef QDOC_QML
     case Atom::QmlText:
@@ -1375,7 +1403,7 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
     QList sections;
     QList::ConstIterator s;
 
-    const ClassNode *classe = 0;
+    const ClassNode* cn = 0;
     const NamespaceNode *namespasse = 0;
 
     QString title;
@@ -1388,43 +1416,51 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
         title = rawTitle + " Namespace";
     }
     else if (inner->type() == Node::Class) {
-        classe = static_cast(inner);
+        cn = static_cast(inner);
         rawTitle = marker->plainName(inner);
         fullTitle = marker->plainFullName(inner);
         title = rawTitle + " Class Reference";
-    }
-
-    Text subtitleText;
-    if (rawTitle != fullTitle)
-        subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")"
-                     << Atom(Atom::LineBreak);
 
-    generateHeader(inner);
+        generateHeader(inner);
 
-    writer.writeStartElement(CXXCLASS);
-    writer.writeStartElement(APINAME);
-    writer.writeCharacters(fullTitle);
-    writer.writeEndElement(); // apiName
+        writer.writeStartElement(CXXCLASS);
+        writeGuidAttribute(fullTitle);
+        writer.writeStartElement(APINAME);
+        writer.writeCharacters(fullTitle);
+        writer.writeEndElement(); // 
 
-    generateBrief(inner, marker);
+        generateBrief(inner, marker);
     
-    writer.writeStartElement(CXXCLASSDETAIL);
-    writer.writeStartElement(APIDESC);
-
-    if (!inner->doc().isEmpty()) {
-        writer.writeStartElement("p");
-        writer.writeAttribute("outputclass","h2");
-        writer.writeCharacters("Detailed Description");
-        writer.writeEndElement(); // p
-        generateBody(inner, marker);
-        //        generateAlsoList(inner, marker);
-    }
+        writer.writeStartElement(CXXCLASSDETAIL);
+        writer.writeStartElement(CXXCLASSDEFINITION);
+        writer.writeStartElement(CXXCLASSACCESSSPECIFIER);
+        writer.writeAttribute("value",inner->accessString());
+        writer.writeEndElement(); // 
+        writeDerivations(cn, marker);
+        writeLocation(cn, marker);
+        writer.writeEndElement(); // 
+        writer.writeStartElement(APIDESC);
+
+        if (!inner->doc().isEmpty()) {
+            writer.writeStartElement("p");
+            writer.writeAttribute("outputclass","h2");
+            writer.writeCharacters("Detailed Description");
+            writer.writeEndElement(); // 
+            generateBody(inner, marker);
+            //        generateAlsoList(inner, marker);
+        }
     
-    writer.writeEndElement(); // apiDesc
-    writer.writeEndElement(); // cxxClassDetail
-    writer.writeEndElement(); // cxxClass
+        writer.writeEndElement(); // 
+        writer.writeEndElement(); // 
+        writer.writeEndElement(); // 
+    }
 
 #ifdef WRITE_HTML    
+    Text subtitleText;
+    if (rawTitle != fullTitle)
+        subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")"
+                     << Atom(Atom::LineBreak);
+
     QString shortVersion;
     shortVersion = project + " " + shortVersion + ": ";
     shortVersion = myTree->version();
@@ -1450,17 +1486,17 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
     generateTitle(title, subtitleText, SmallSubTitle, inner, marker);
 
 #ifdef QDOC_QML
-    if (classe && !classe->qmlElement().isEmpty()) {
-        generateInstantiatedBy(classe,marker);
+    if (cn && !cn->qmlElement().isEmpty()) {
+        generateInstantiatedBy(cn,marker);
     }
 #endif
     
     generateBrief(inner, marker);
     generateIncludes(inner, marker);
     generateStatus(inner, marker);
-    if (classe) {
-        generateInherits(classe, marker);
-        generateInheritedBy(classe, marker);
+    if (cn) {
+        generateInherits(cn, marker);
+        generateInheritedBy(cn, marker);
     }
     generateThreadSafeness(inner, marker);
     generateSince(inner, marker);
@@ -1895,37 +1931,11 @@ void DitaXmlGenerator::generateHeader(const Node* node)
         version = "0.6.0";
     }
 
-#if 0    
-    writer.writeCharacters("\n\n");
-
-    if (node && !node->doc().location().isEmpty()) {
-        writer.writeCharacters("\n");
-    }
-#endif
-
     QString doctype = "";
     writer.writeDTD(doctype);
     writer.writeComment(node->doc().location().fileName());
-    
-#if 0    
-    out() << "\n\n";
-
-    if (node && !node->doc().location().isEmpty())
-        out() << "\n";
-    out().flush();
-#endif    
 }
 
 void DitaXmlGenerator::generateTitle(const QString& title,
@@ -2173,37 +2183,6 @@ void DitaXmlGenerator::generateTableOfContents(const Node *node,
     inLink = false;
 }
 
-#if 0
-void DitaXmlGenerator::generateNavigationBar(const NavigationBar& bar,
-                                           const Node *node,
-                                           CodeMarker *marker)
-{
-    if (bar.prev.begin() != 0 || bar.current.begin() != 0 ||
-         bar.next.begin() != 0) {
-        out() << "";
-        if (bar.prev.begin() != 0) {
-#if 0
-            out() << "[Prev: ";
-            generateText(section.previousHeading(), node, marker);
-            out() << "]\n";
-#endif
-        }
-        if (bar.current.begin() != 0) {
-            out() << "[Home]\n";
-        }
-        if (bar.next.begin() != 0) {
-            out() << "[Next: ";
-            generateText(Text::sectionHeading(bar.next.begin()), node, marker);
-            out() << "]\n";
-        }
-        out() << "
\n";
-    }
-}
-#endif
-
 QString DitaXmlGenerator::generateListOfAllMemberFile(const InnerNode *inner,
                                                    CodeMarker *marker)
 {
@@ -2855,7 +2834,6 @@ void DitaXmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /
     }
 }
 
-#ifdef QDOC_NAME_ALIGNMENT
 void DitaXmlGenerator::generateSection(const NodeList& nl,
                                     const Node *relative,
                                     CodeMarker *marker,
@@ -3220,281 +3198,6 @@ QString DitaXmlGenerator::highlightedCode(const QString& markedCode,
     return html;
 }
 
-#else
-void DitaXmlGenerator::generateSectionList(const Section& section,
-                                        const Node *relative,
-                                        CodeMarker *marker,
-                                        CodeMarker::SynopsisStyle style)
-{
-    if (!section.members.isEmpty()) {
-        bool twoColumn = false;
-        if (style == CodeMarker::SeparateList) {
-            twoColumn = (section.members.count() >= 16);
-        }
-        else if (section.members.first()->type() == Node::Property) {
-            twoColumn = (section.members.count() >= 5);
-        }
-        if (twoColumn)
-            out() << "\n";
-        if (++numTableRows % 2 == 1)
-            out() << "";
-        else
-            out() << "
";
-			
-//                  << "
| ";
-        out() << " \n";
-
-        int i = 0;
-        NodeList::ConstIterator m = section.members.begin();
-        while (m != section.members.end()) {
-            if ((*m)->access() == Node::Private) {
-                ++m;
-                continue;
-            }
-
-            if (twoColumn && i == (int) (section.members.count() + 1) / 2)
-                out() << " | \n";
-
-            out() << "\n";
-        if (twoColumn)
-            out() << "";
-            if (style == CodeMarker::Accessors)
-                out() << "";
-            generateSynopsis(*m, relative, marker, style);
-            if (style == CodeMarker::Accessors)
-                out() << "";
-            out() << "\n";
-            i++;
-            ++m;
-        }
-        out() << " | 
\n
\n";
-    }
-
-    if (style == CodeMarker::Summary && !section.inherited.isEmpty()) {
-        out() << "\n";
-        generateSectionInheritedList(section, relative, marker);
-        out() << "
\n";
-    }
-}
-
-void DitaXmlGenerator::generateSectionInheritedList(const Section& section,
-                                                 const Node *relative,
-                                                 CodeMarker *marker)
-{
-    QList >::ConstIterator p = section.inherited.begin();
-    while (p != section.inherited.end()) {
-        out() << "";
-        out() << (*p).second << " ";
-        if ((*p).second == 1) {
-            out() << section.singularMember;
-        } else {
-            out() << section.pluralMember;
-        }
-        out() << " inherited from "
-              << protectEnc(marker->plainFullName((*p).first, relative))
-              << "\n";
-        ++p;
-    }
-}
-
-void DitaXmlGenerator::generateSynopsis(const Node *node,
-                                     const Node *relative,
-                                     CodeMarker *marker,
-                                     CodeMarker::SynopsisStyle style)
-{
-    QString marked = marker->markedUpSynopsis(node, relative, style);
-    QRegExp templateTag("(<[^@>]*>)");
-    if (marked.indexOf(templateTag) != -1) {
-        QString contents = protectEnc(marked.mid(templateTag.pos(1),
-                                              templateTag.cap(1).length()));
-        marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
-                        contents);
-    }
-    marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])@param>"), "\\1\\2");
-    marked.replace("<@param>", "");
-    marked.replace("@param>", "");
-
-    if (style == CodeMarker::Summary)
-        marked.replace("@name>", "b>");
-
-    if (style == CodeMarker::SeparateList) {
-        QRegExp extraRegExp("<@extra>.*@extra>");
-        extraRegExp.setMinimal(true);
-        marked.replace(extraRegExp, "");
-    } else {
-        marked.replace("<@extra>", "");
-        marked.replace("@extra>", "");
-    }
-
-    if (style != CodeMarker::Detailed) {
-        marked.replace("<@type>", "");
-        marked.replace("@type>", "");
-    }
-    out() << highlightedCode(marked, marker, relative);
-}
-
-QString DitaXmlGenerator::highlightedCode(const QString& markedCode,
-                                       CodeMarker *marker,
-                                       const Node *relative)
-{
-    QString src = markedCode;
-    QString html;
-    QStringRef arg;
-    QStringRef par1;
-
-    const QChar charLangle = '<';
-    const QChar charAt = '@';
-
-    // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(@link>)"
-    static const QString linkTag("link");
-    for (int i = 0, n = src.size(); i < n;) {
-        if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
-            i += 2;
-            if (parseArg(src, linkTag, &i, n, &arg, &par1)) {
-                const Node* node = CodeMarker::nodeForString(par1.toString());
-                QString link = linkForNode(node, relative);
-                addLink(link, arg, &html);
-            }
-            else {
-                html += charLangle;
-                html += charAt;
-            }
-        }
-        else {
-            html += src.at(i++);
-        }
-    }
-
-    if (slow) {
-        // is this block ever used at all?
-        // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(@func>)"
-        src = html;
-        html = QString();
-        static const QString funcTag("func");
-        for (int i = 0, n = src.size(); i < n;) {
-            if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
-                i += 2;
-                if (parseArg(src, funcTag, &i, n, &arg, &par1)) {
-                    QString link = linkForNode(
-                            marker->resolveTarget(par1.toString(),
-                                                  myTree,
-                                                  relative),
-                            relative);
-                    addLink(link, arg, &html);
-                    par1 = QStringRef();
-                }
-                else {
-                    html += charLangle;
-                    html += charAt;
-                }
-            }
-            else {
-                html += src.at(i++);
-            }
-        }
-    }
-
-    // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(@\\2>)" tags
-    src = html;
-    html = QString();
-    static const QString typeTags[] = { "type", "headerfile", "func" };
-    for (int i = 0, n = src.size(); i < n;) {
-        if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
-            i += 2;
-            bool handled = false;
-            for (int k = 0; k != 3; ++k) {
-                if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) {
-                    par1 = QStringRef();
-                    QString link = linkForNode(
-                            marker->resolveTarget(arg.toString(), myTree, relative),
-                            relative);
-                    addLink(link, arg, &html);
-                    handled = true;
-                    break;
-                }
-            }
-            if (!handled) {
-                html += charLangle;
-                html += charAt;
-            }
-        }
-        else {
-            html += src.at(i++);
-        }
-    }
-
-    // replace all
-    // "<@comment>" -> "