From a02369f43851932b820042448a47d024a0086bd8 Mon Sep 17 00:00:00 2001
From: Martin Smith 
Date: Tue, 15 Mar 2011 14:58:06 +0100
Subject: qdoc: Changed  structure.
There appears to be a design flaw in the DIKT language
in that it doesn't allow the  element to appear
inside a  .
---
 tools/qdoc3/ditaxmlgenerator.cpp | 422 +++++++++++++++++++++------------------
 tools/qdoc3/ditaxmlgenerator.h   |  43 ++--
 tools/qdoc3/doc.cpp              |   4 +-
 3 files changed, 264 insertions(+), 205 deletions(-)
diff --git a/tools/qdoc3/ditaxmlgenerator.cpp b/tools/qdoc3/ditaxmlgenerator.cpp
index 2c02892..14f18ec 100644
--- a/tools/qdoc3/ditaxmlgenerator.cpp
+++ b/tools/qdoc3/ditaxmlgenerator.cpp
@@ -61,10 +61,6 @@ QT_BEGIN_NAMESPACE
 
 #define COMMAND_VERSION                         Doc::alias("version")
 int DitaXmlGenerator::id = 0;
-bool DitaXmlGenerator::inApiDesc = false;
-bool DitaXmlGenerator::inSection = false;
-bool DitaXmlGenerator::inDetailedDescription = false;
-bool DitaXmlGenerator::inLegaleseText = false;
 
 QString DitaXmlGenerator::sinceTitles[] =
     {
@@ -303,6 +299,19 @@ void DitaXmlGenerator::addLink(const QString& href,
 }
 
 /*!
+  If there are no \c {} or \c {} elements
+  open, start a \c {} element. Otherwise, start a
+  \c {} element.
+ */
+void DitaXmlGenerator::startTitle()
+{
+    if (divNestingLevel > 0)
+        writeStartTag(DT_p);
+    else
+        writeStartTag(DT_title);
+}
+
+/*!
   Push \a t onto the dita tag stack and write the appropriate
   start tag to the DITA XML file.
  */
@@ -334,22 +343,66 @@ DitaXmlGenerator::DitaTag DitaXmlGenerator::currentTag()
 }
 
 /*!
+  If the section nesting level is 0, output a \c{}
+  element with an \e id attribute set to \a idText and
+  an \e outputclass attribute set to \a outputclass.
+  If \a idText is null, no \e id attribute is output.
+  If \a outputclass is empty, no \e outputclass attribute
+  is output.
+
+  The section level is incremented and then returned.
+ */
+int DitaXmlGenerator::enterSection(const QString& outputclass, QString* idText)
+{
+    if (sectionNestingLevel == 0) {
+        writeStartTag(DT_section);
+        if (idText)
+            writeGuidAttribute(*idText);
+        if (!outputclass.isEmpty())
+            xmlWriter().writeAttribute("outputclass",outputclass);
+    }
+    return ++sectionNestingLevel;
+}
+
+/*!
+  If the section nesting level is greater than 0, decrement
+  it. If it becomes 0, output a \c {}. Return the
+  decremented section nesting level.
+ */
+int DitaXmlGenerator::leaveSection()
+{
+    if (sectionNestingLevel > 0) {
+        --sectionNestingLevel;
+        if (sectionNestingLevel == 0)
+            writeEndTag(); // 
+    }
+    return sectionNestingLevel;
+}
+
+/*!
   The default constructor.
  */
 DitaXmlGenerator::DitaXmlGenerator()
-    : inLink(false),
+    : inApiDesc(false),
       inContents(false),
+      inDetailedDescription(false),
+      inLegaleseText(false),
+      inLink(false),
+      inObsoleteLink(false),
       inSectionHeading(false),
       inTableHeader(false),
       inTableBody(false),
-      numTableRows(0),
-      threeColumnEnumValueTable(true),
+      noLinks(false),
+      obsoleteLinks(false),
       offlineDocs(true),
+      threeColumnEnumValueTable(true),
+      codeIndent(0),
+      numTableRows(0),
+      divNestingLevel(0),
+      sectionNestingLevel(0),
+      tableColumnCount(0),
       funcLeftParen("\\S(\\()"),
-      myTree(0),
-      obsoleteLinks(false),
-      noLinks(false),
-      tableColumnCount(0)
+      myTree(0)
 {
     // nothing yet.
 }
@@ -644,7 +697,7 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
         //skipAhead = skipAtoms(atom, Atom::BriefRight);
         //break;
         //}
-        if (inApiDesc || inSection) {
+        if (inApiDesc || inSection()) {
             writeStartTag(DT_p);
             xmlWriter().writeAttribute("outputclass","brief");
         }
@@ -726,10 +779,14 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
         {
             attr = atom->string();
             DitaTag t = currentTag();
-            if ((t == DT_section) || (t == DT_sectiondiv))
+            if ((t == DT_section) || (t == DT_sectiondiv)) {
                 writeStartTag(DT_sectiondiv);
-            else if ((t == DT_body) || (t == DT_bodydiv))
+                divNestingLevel++;
+            }
+            else if ((t == DT_body) || (t == DT_bodydiv)) {
                 writeStartTag(DT_bodydiv);
+                divNestingLevel++;
+            }
             if (!attr.isEmpty()) {
                 if (attr.contains('=')) {
                     int index = 0;
@@ -756,8 +813,11 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
         }
         break;
     case Atom::DivRight:
-        if ((currentTag() == DT_sectiondiv) || (currentTag() == DT_bodydiv))
+        if ((currentTag() == DT_sectiondiv) || (currentTag() == DT_bodydiv)) {
             writeEndTag(); // , , or 
+            if (divNestingLevel > 0)
+                --divNestingLevel;
+        }
         break;
     case Atom::FootnoteLeft:
         // ### For now
@@ -1364,23 +1424,19 @@ int DitaXmlGenerator::generateAtom(const Atom *atom,
         }
         break;
     case Atom::SectionLeft:
-        if (inSection || inApiDesc) {
+        if (inApiDesc) {
+            writeEndTag(); // 
             inApiDesc = false;
-            writeEndTag(); //  or 
         }
-        inSection = true;
-        writeStartTag(DT_section);
-        writeGuidAttribute(Doc::canonicalTitle(Text::sectionHeading(atom).toString()));
-        xmlWriter().writeAttribute("outputclass","details");
+        enterSection("details");
+        //writeGuidAttribute(Doc::canonicalTitle(Text::sectionHeading(atom).toString()));
         break;
     case Atom::SectionRight:
-        if (inSection) {
-            inSection = false;
-            writeEndTag(); // 
-        }
+        leaveSection();
         break;
     case Atom::SectionHeadingLeft:
-        writeStartTag(DT_title);
+        startTitle();
+        writeGuidAttribute(Doc::canonicalTitle(Text::sectionHeading(atom).toString()));
         hx = "h" + QString::number(atom->string().toInt() + hOffset(relative));
         xmlWriter().writeAttribute("outputclass",hx);
         inSectionHeading = true;
@@ -1662,46 +1718,43 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
         bool needOtherSection = false;
         QList summarySections;
         summarySections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
-        s = summarySections.begin();
-        while (s != summarySections.end()) {
-            if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
-                if (!s->inherited.isEmpty())
-                    needOtherSection = true;
-            }
-            else {
-                QString attr;
-                if (!s->members.isEmpty()) {
-                    writeStartTag(DT_section);
-                    attr = cleanRef((*s).name).toLower() + " redundant";
-                    xmlWriter().writeAttribute("outputclass",attr);
-                    writeStartTag(DT_title);
-                    xmlWriter().writeAttribute("outputclass","h2");
-                    writeCharacters(protectEnc((*s).name));
-                    writeEndTag(); // 
-                    generateSection(s->members, inner, marker, CodeMarker::Summary);
-                    generateSectionInheritedList(*s, inner, marker);
-                    writeEndTag(); // 
+        if (!summarySections.isEmpty()) {
+            enterSection("redundant");
+            s = summarySections.begin();
+            while (s != summarySections.end()) {
+                if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
+                    if (!s->inherited.isEmpty())
+                        needOtherSection = true;
                 }
-                if (!s->reimpMembers.isEmpty()) {
-                    QString name = QString("Reimplemented ") + (*s).name;
-                    attr = cleanRef(name).toLower() + " redundant";
-                    writeStartTag(DT_section);
-                    xmlWriter().writeAttribute("outputclass",attr);
-                    writeStartTag(DT_title);
-                    xmlWriter().writeAttribute("outputclass","h2");
-                    writeCharacters(protectEnc(name));
-                    writeEndTag(); // 
-                    generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
-                    generateSectionInheritedList(*s, inner, marker);
-                    writeEndTag(); // 
+                else {
+                    QString attr;
+                    if (!s->members.isEmpty()) {
+                        startTitle();
+                        attr  = cleanRef((*s).name).toLower() + " h2"; 
+                        xmlWriter().writeAttribute("outputclass",attr);
+                        writeCharacters(protectEnc((*s).name));
+                        writeEndTag(); // 
+                        generateSection(s->members, inner, marker, CodeMarker::Summary);
+                        generateSectionInheritedList(*s, inner, marker);
+                    }
+                    if (!s->reimpMembers.isEmpty()) {
+                        QString name = QString("Reimplemented ") + (*s).name;
+                        attr = cleanRef(name).toLower() + " h2";
+                        startTitle();
+                        xmlWriter().writeAttribute("outputclass",attr);
+                        writeCharacters(protectEnc(name));
+                        writeEndTag(); // 
+                        generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
+                        generateSectionInheritedList(*s, inner, marker);
+                    }
                 }
+                ++s;
             }
-            ++s;
+            leaveSection();
         }
         if (needOtherSection) {
-            writeStartTag(DT_section);
-            xmlWriter().writeAttribute("outputclass","additional-inherited-members redundant");
-            writeStartTag(DT_title);
+            enterSection("additional-inherited-members redundant");
+            startTitle();
             xmlWriter().writeAttribute("outputclass","h3");
             xmlWriter().writeCharacters("Additional Inherited Members");
             writeEndTag(); // 
@@ -1711,7 +1764,7 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
                     generateSectionInheritedList(*s, inner, marker);
                 ++s;
             }
-            writeEndTag(); // 
+            leaveSection();
         }
         
         writeDetailedDescription(nsn, marker, false, QString("Detailed Description"));
@@ -1800,46 +1853,43 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
         bool needOtherSection = false;
         QList summarySections;
         summarySections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
-        s = summarySections.begin();
-        while (s != summarySections.end()) {
-            if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
-                if (!s->inherited.isEmpty())
-                    needOtherSection = true;
-            }
-            else {
-                QString attr;
-                if (!s->members.isEmpty()) {
-                    writeStartTag(DT_section);
-                    attr = cleanRef((*s).name).toLower() + " redundant";
-                    xmlWriter().writeAttribute("outputclass",attr);
-                    writeStartTag(DT_title);
-                    xmlWriter().writeAttribute("outputclass","h2");
-                    writeCharacters(protectEnc((*s).name));
-                    writeEndTag(); // 
-                    generateSection(s->members, inner, marker, CodeMarker::Summary);
-                    generateSectionInheritedList(*s, inner, marker);
-                    writeEndTag(); // 
+        if (!summarySections.isEmpty()) {
+            enterSection("redundant");
+            s = summarySections.begin();
+            while (s != summarySections.end()) {
+                if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
+                    if (!s->inherited.isEmpty())
+                        needOtherSection = true;
                 }
-                if (!s->reimpMembers.isEmpty()) {
-                    QString name = QString("Reimplemented ") + (*s).name;
-                    attr = cleanRef(name).toLower() + " redundant";
-                    writeStartTag(DT_section);
-                    xmlWriter().writeAttribute("outputclass",attr);
-                    writeStartTag(DT_title);
-                    xmlWriter().writeAttribute("outputclass","h2");
-                    writeCharacters(protectEnc(name));
-                    writeEndTag(); // 
-                    generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
-                    generateSectionInheritedList(*s, inner, marker);
-                    writeEndTag(); // 
+                else {
+                    QString attr;
+                    if (!s->members.isEmpty()) {
+                        startTitle();
+                        attr = cleanRef((*s).name).toLower() + " h2";
+                        xmlWriter().writeAttribute("outputclass",attr);
+                        writeCharacters(protectEnc((*s).name));
+                        writeEndTag(); // 
+                        generateSection(s->members, inner, marker, CodeMarker::Summary);
+                        generateSectionInheritedList(*s, inner, marker);
+                    }
+                    if (!s->reimpMembers.isEmpty()) {
+                        QString name = QString("Reimplemented ") + (*s).name;
+                        attr = cleanRef(name).toLower() + " h2";
+                        startTitle();
+                        xmlWriter().writeAttribute("outputclass",attr);
+                        writeCharacters(protectEnc(name));
+                        writeEndTag(); // 
+                        generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
+                        generateSectionInheritedList(*s, inner, marker);
+                    }
                 }
+                ++s;
             }
-            ++s;
+            leaveSection();
         }
         if (needOtherSection) {
-            writeStartTag(DT_section);
-            xmlWriter().writeAttribute("outputclass","additional-inherited-members redundant");
-            writeStartTag(DT_title);
+            enterSection("additional-inherited-members redundant");
+            startTitle();
             xmlWriter().writeAttribute("outputclass","h3");
             xmlWriter().writeCharacters("Additional Inherited Members");
             writeEndTag(); // 
@@ -1849,7 +1899,7 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
                     generateSectionInheritedList(*s, inner, marker);
                 ++s;
             }
-            writeEndTag(); // 
+            leaveSection();
         }
         
         writeDetailedDescription(cn, marker, false, QString("Detailed Description"));
@@ -1922,46 +1972,43 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
         bool needOtherSection = false;
         QList summarySections;
         summarySections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay);
-        s = summarySections.begin();
-        while (s != summarySections.end()) {
-            if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
-                if (!s->inherited.isEmpty())
-                    needOtherSection = true;
-            }
-            else {
-                QString attr;
-                if (!s->members.isEmpty()) {
-                    writeStartTag(DT_section);
-                    attr = cleanRef((*s).name).toLower() + " redundant";
-                    xmlWriter().writeAttribute("outputclass",attr);
-                    writeStartTag(DT_title);
-                    xmlWriter().writeAttribute("outputclass","h2");
-                    writeCharacters(protectEnc((*s).name));
-                    writeEndTag(); // 
-                    generateSection(s->members, inner, marker, CodeMarker::Summary);
-                    generateSectionInheritedList(*s, inner, marker);
-                    writeEndTag(); // 
+        if (!summarySections.isEmpty()) {
+            enterSection("redundant");
+            s = summarySections.begin();
+            while (s != summarySections.end()) {
+                if (s->members.isEmpty() && s->reimpMembers.isEmpty()) {
+                    if (!s->inherited.isEmpty())
+                        needOtherSection = true;
                 }
-                if (!s->reimpMembers.isEmpty()) {
-                    QString name = QString("Reimplemented ") + (*s).name;
-                    attr = cleanRef(name).toLower() + " redundant";
-                    writeStartTag(DT_section);
-                    xmlWriter().writeAttribute("outputclass",attr);
-                    writeStartTag(DT_title);
-                    xmlWriter().writeAttribute("outputclass","h2");
-                    writeCharacters(protectEnc(name));
-                    writeEndTag(); // 
-                    generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
-                    generateSectionInheritedList(*s, inner, marker);
-                    writeEndTag(); // 
+                else {
+                    QString attr;
+                    if (!s->members.isEmpty()) {
+                        startTitle();
+                        attr = cleanRef((*s).name).toLower() + " h2";
+                        xmlWriter().writeAttribute("outputclass",attr);
+                        writeCharacters(protectEnc((*s).name));
+                        writeEndTag(); // 
+                        generateSection(s->members, inner, marker, CodeMarker::Summary);
+                        generateSectionInheritedList(*s, inner, marker);
+                    }
+                    if (!s->reimpMembers.isEmpty()) {
+                        QString name = QString("Reimplemented ") + (*s).name;
+                        attr = cleanRef(name).toLower() + " h2";
+                        startTitle();
+                        xmlWriter().writeAttribute("outputclass",attr);
+                        writeCharacters(protectEnc(name));
+                        writeEndTag(); // 
+                        generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
+                        generateSectionInheritedList(*s, inner, marker);
+                    }
                 }
+                ++s;
             }
-            ++s;
+            leaveSection();
         }
         if (needOtherSection) {
-            writeStartTag(DT_section);
-            xmlWriter().writeAttribute("outputclass","additional-inherited-members redundant");
-            writeStartTag(DT_title);
+            enterSection("additional-inherited-members redundant");
+            startTitle();
             xmlWriter().writeAttribute("outputclass","h3");
             xmlWriter().writeCharacters("Additional Inherited Members");
             writeEndTag(); // 
@@ -1971,7 +2018,7 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
                     generateSectionInheritedList(*s, inner, marker);
                 ++s;
             }
-            writeEndTag(); // 
+            leaveSection();
         }
         
         writeDetailedDescription(fn, marker, false, QString("Detailed Description"));
@@ -2042,23 +2089,24 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
 
         QList summarySections;
         summarySections = marker->qmlSections(qcn,CodeMarker::Summary,0);
-        s = summarySections.begin();
-        while (s != summarySections.end()) {
-            QString attr;
-            if (!s->members.isEmpty()) {
-                writeStartTag(DT_section);
-                attr = cleanRef((*s).name).toLower() + " redundant";
-                xmlWriter().writeAttribute("outputclass",attr);
-                writeStartTag(DT_title);
-                xmlWriter().writeAttribute("outputclass","h2");
-                writeCharacters(protectEnc((*s).name));
-                writeEndTag(); // 
-                generateQmlSummary(*s,qcn,marker);
-                //generateSection(s->members, inner, marker, CodeMarker::Summary);
-                //generateSectionInheritedList(*s, inner, marker);
-                writeEndTag(); // 
+        if (!summarySections.isEmpty()) {
+            enterSection("redundant");
+            s = summarySections.begin();
+            while (s != summarySections.end()) {
+                QString attr;
+                if (!s->members.isEmpty()) {
+                    startTitle();
+                    attr = cleanRef((*s).name).toLower() + " h2";
+                    xmlWriter().writeAttribute("outputclass",attr);
+                    writeCharacters(protectEnc((*s).name));
+                    writeEndTag(); // 
+                    generateQmlSummary(*s,qcn,marker);
+                    //generateSection(s->members, inner, marker, CodeMarker::Summary);
+                    //generateSectionInheritedList(*s, inner, marker);
+                }
+                ++s;
             }
-            ++s;
+            leaveSection();
         }
         
         writeDetailedDescription(qcn, marker, false, QString("Detailed Description"));
@@ -2067,29 +2115,27 @@ DitaXmlGenerator::generateClassLikeNode(const InnerNode* inner, CodeMarker* mark
 
         QList detailSections;
         detailSections = marker->qmlSections(qcn,CodeMarker::Detailed,0);
-        s = detailSections.begin();
-        while (s != detailSections.end()) {
-            if (!s->members.isEmpty()) {
-                QString attr;
-                inSection = true;
-                writeStartTag(DT_section);
-                attr = cleanRef((*s).name).toLower();
-                xmlWriter().writeAttribute("outputclass",attr);
-                writeStartTag(DT_title);
-                xmlWriter().writeAttribute("outputclass","h2");
-                writeCharacters(protectEnc((*s).name));
-                writeEndTag(); // 
-                NodeList::ConstIterator m = (*s).members.begin();
-                while (m != (*s).members.end()) {
-                    generateDetailedQmlMember(*m, qcn, marker);
-                    ++m;
+        if (!detailSections.isEmpty()) {
+            enterSection("details");
+            s = detailSections.begin();
+            while (s != detailSections.end()) {
+                if (!s->members.isEmpty()) {
+                    QString attr;
+                    startTitle();
+                    attr = cleanRef((*s).name).toLower() + " h2";
+                    xmlWriter().writeAttribute("outputclass",attr);
+                    writeCharacters(protectEnc((*s).name));
+                    writeEndTag(); // 
+                    NodeList::ConstIterator m = (*s).members.begin();
+                    while (m != (*s).members.end()) {
+                        generateDetailedQmlMember(*m, qcn, marker);
+                        ++m;
+                    }
                 }
-                writeEndTag(); // 
-                inSection = false;
+                ++s;
             }
-            ++s;
+            leaveSection();
         }
-
         writeEndTag(); //         
         writeEndTag(); // 
     }
@@ -2139,24 +2185,22 @@ void DitaXmlGenerator::generateFakeNode(const FakeNode* fake, CodeMarker* marker
     if (fake->subType() == Node::Module) {
         generateStatus(fake, marker);
         if (moduleNamespaceMap.contains(fake->name())) {
-            writeStartTag(DT_section);
-            xmlWriter().writeAttribute("outputclass","namespaces");
-            writeStartTag(DT_title);
+            enterSection("namespaces");
+            startTitle();
             xmlWriter().writeAttribute("outputclass","h2");
             xmlWriter().writeCharacters("Namespaces");
             writeEndTag(); // 
             generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]);
-            writeEndTag(); // 
+            leaveSection();
         }
         if (moduleClassMap.contains(fake->name())) {
-            writeStartTag(DT_section);
-            xmlWriter().writeAttribute("outputclass","classes");
-            writeStartTag(DT_title);
+            enterSection("classes");
+            startTitle();
             xmlWriter().writeAttribute("outputclass","h2");
             xmlWriter().writeCharacters("Classes");
             writeEndTag(); // 
             generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]);
-            writeEndTag(); // 
+            leaveSection();
         }
     }
 
@@ -5333,6 +5377,7 @@ void DitaXmlGenerator::beginSubPage(const Location& location,
     writer->setAutoFormatting(true);
     writer->setAutoFormattingIndent(4);
     writer->writeStartDocument();
+    clearSectionNesting();
 }
 
 /*!
@@ -5342,6 +5387,8 @@ void DitaXmlGenerator::beginSubPage(const Location& location,
  */
 void DitaXmlGenerator::endSubPage()
 {
+    if (inSection())
+        qDebug() << "Missing  in" << outFileName() << sectionNestingLevel;
     xmlWriter().writeEndDocument();
     delete xmlWriterStack.pop();
     PageGenerator::endSubPage();
@@ -5387,19 +5434,17 @@ void DitaXmlGenerator::writeDetailedDescription(const Node* node,
             xmlWriter().writeAttribute("outputclass","details");
         }
         else {
-            inSection = true;
-            writeStartTag(DT_section);
-            if (!title.isEmpty()) {
-                writeGuidAttribute(title);
-                xmlWriter().writeAttribute("outputclass","details");
-                writeStartTag(DT_title);
+            QString t = title;
+            if (!t.isEmpty()) {
+                enterSection("details",&t); 
+                startTitle();
                 xmlWriter().writeAttribute("outputclass","h2");
                 writeCharacters(title);
                 writeEndTag(); // 
             }
             else {
-                writeGuidAttribute("Detailed Description");
-                xmlWriter().writeAttribute("outputclass","details");
+                t = "Detailed Description";
+                enterSection("details",&t); 
             }
         }
         generateBody(node, marker);
@@ -5407,9 +5452,8 @@ void DitaXmlGenerator::writeDetailedDescription(const Node* node,
             writeEndTag(); // 
             inApiDesc = false;
         }
-        else if (inSection) {
-            writeEndTag(); // 
-            inSection = false;
+        else if (inSection()) {
+            leaveSection();
         }
     }
     inDetailedDescription = false;
diff --git a/tools/qdoc3/ditaxmlgenerator.h b/tools/qdoc3/ditaxmlgenerator.h
index 3e66318..d35af76 100644
--- a/tools/qdoc3/ditaxmlgenerator.h
+++ b/tools/qdoc3/ditaxmlgenerator.h
@@ -438,23 +438,42 @@ class DitaXmlGenerator : public PageGenerator
     void addLink(const QString& href, const QStringRef& text);
     void writeDitaMap();
     void writeStartTag(DitaTag t);
+    void startTitle();
     void writeEndTag(DitaTag t=DT_NONE);
     DitaTag currentTag();
+    void clearSectionNesting() { sectionNestingLevel = 0; } 
+    int enterSection(const QString& outputclass, QString* idText=0);
+    int leaveSection();
+    bool inSection() const { return (sectionNestingLevel > 0); }
+    int currentSectionNestingLevel() const { return sectionNestingLevel; }
+    
 
  private:
-    QMap refMap;
-    QMap name2guidMap;
-    GuidMaps guidMaps;
-    int codeIndent;
+    /*
+      These flags indicate which elements the generator
+      is currently outputting.
+     */
+    bool inApiDesc;
+    bool inContents;
+    bool inDetailedDescription;
+    bool inLegaleseText;
     bool inLink;
     bool inObsoleteLink;
-    bool inContents;
     bool inSectionHeading;
     bool inTableHeader;
     bool inTableBody;
-    int numTableRows;
-    bool threeColumnEnumValueTable;
+
+    bool noLinks;
+    bool obsoleteLinks;
     bool offlineDocs;
+    bool threeColumnEnumValueTable;
+
+    int codeIndent;
+    int numTableRows;
+    int divNestingLevel;
+    int sectionNestingLevel;
+    int tableColumnCount;
+
     QString link;
     QStringList sectionNumber;
     QRegExp funcLeftParen;
@@ -473,9 +492,9 @@ class DitaXmlGenerator : public PageGenerator
     QStringList stylesheets;
     QStringList customHeadElements;
     const Tree* myTree;
-    bool obsoleteLinks;
-    bool noLinks;
-    int tableColumnCount;
+    QMap refMap;
+    QMap name2guidMap;
+    GuidMaps guidMaps;
     QMap moduleClassMap;
     QMap moduleNamespaceMap;
     NodeMap nonCompatClasses;
@@ -494,10 +513,6 @@ class DitaXmlGenerator : public PageGenerator
     NewClassMaps newClassMaps;
     NewClassMaps newQmlClassMaps;
     static int id;
-    static bool inApiDesc;
-    static bool inSection;
-    static bool inDetailedDescription;
-    static bool inLegaleseText;
     static QString ditaTags[];
     QStack xmlWriterStack;
     QStack tagStack;
diff --git a/tools/qdoc3/doc.cpp b/tools/qdoc3/doc.cpp
index 346bf95..5f563be 100644
--- a/tools/qdoc3/doc.cpp
+++ b/tools/qdoc3/doc.cpp
@@ -646,7 +646,7 @@ void DocParser::parse(const QString& source,
                         }
                         break;
                     case CMD_ENDCHAPTER:
-                        endSection(0, cmd);
+                        endSection(Doc::Chapter, cmd);
                         break;
                     case CMD_ENDCODE:
                         closeCommand(cmd);
@@ -1458,7 +1458,7 @@ void DocParser::parse(const QString& source,
         location().warning(tr("Missing '\\%1'").arg(cmdName(CMD_ENDIF)));
     }
 
-    while (currentSectioningUnit > Doc::Chapter) {
+    while (currentSectioningUnit >= Doc::Chapter) {
         int delta = currentSectioningUnit - priv->extra->sectioningUnit;
         append(Atom::SectionRight, QString::number(delta));
         currentSectioningUnit = Doc::SectioningUnit(int(currentSectioningUnit) - 1);
-- 
cgit v0.12