From 12f64cce218a5bf76372dd48d54f9fa761fe2955 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 2 Jul 2010 18:21:25 +0200 Subject: qdoc: Added a solution for creating tables of contents for manuals. Reviewed-by: Trust Me --- tools/qdoc3/doc/qdoc-manual.qdoc | 21 +++++++ tools/qdoc3/helpprojectwriter.cpp | 124 +++++++++++++++++++++++++++----------- tools/qdoc3/helpprojectwriter.h | 1 + 3 files changed, 112 insertions(+), 34 deletions(-) diff --git a/tools/qdoc3/doc/qdoc-manual.qdoc b/tools/qdoc3/doc/qdoc-manual.qdoc index 57c17ba..c3ab731 100644 --- a/tools/qdoc3/doc/qdoc-manual.qdoc +++ b/tools/qdoc3/doc/qdoc-manual.qdoc @@ -8075,6 +8075,27 @@ qhp.Qt.subprojects.examples.indexTitle = Qt Examples qhp.Qt.subprojects.examples.selectors = fake:example \endcode + + To create a table of contents for a manual, create a subproject with + a \c{type} property and set it to \c{manual}. The page in the documentation + referred to by the \c{indexTitle} property must contain a list of links + that acts as a table of contents for the whole manual. QDoc will take the + information in this list and create a table of contents for the subproject. + + For example, the configuration file for Qt Creator defines only one + subproject for its documentation, including all the documentation in a + single manual: + + \code + qhp.QtCreator.subprojects = manual + qhp.QtCreator.subprojects.manual.title = Qt Creator Manual + qhp.QtCreator.subprojects.manual.indexTitle = Qt Creator Manual + qhp.QtCreator.subprojects.manual.type = manual + \endcode + + In this example, the page entitled "Qt Creator Manual" contains a nested + list of links to pages in the documentation which is duplicated in + Qt Assistant's Contents tab. */ /*! diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp index edba097..98246c4 100644 --- a/tools/qdoc3/helpprojectwriter.cpp +++ b/tools/qdoc3/helpprojectwriter.cpp @@ -41,7 +41,7 @@ #include #include -#include +//#include #include "atom.h" #include "helpprojectwriter.h" @@ -91,6 +91,7 @@ HelpProjectWriter::HelpProjectWriter(const Config &config, const QString &defaul subproject.title = config.getString(subprefix + "title"); subproject.indexTitle = config.getString(subprefix + "indexTitle"); subproject.sortPages = config.getBool(subprefix + "sortPages"); + subproject.type = config.getString(subprefix + "type"); readSelectors(subproject, config.getStringList(subprefix + "selectors")); project.subprojects[name] = subproject; } @@ -625,44 +626,99 @@ void HelpProjectWriter::generateProject(HelpProject &project) foreach (const QString &name, project.subprojects.keys()) { SubProject subproject = project.subprojects[name]; - if (!name.isEmpty()) { - writer.writeStartElement("section"); - QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle)); - writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); - writer.writeAttribute("title", subproject.title); - project.files.insert(indexPath); - } - if (subproject.sortPages) { - QStringList titles = subproject.nodes.keys(); - titles.sort(); - foreach (const QString &title, titles) - writeNode(project, writer, subproject.nodes[title]); + if (subproject.type == QLatin1String("manual")) { + + const FakeNode *indexPage = tree->findFakeNodeByTitle(subproject.indexTitle); + if (indexPage) { + Text indexBody = indexPage->doc().body(); + const Atom *atom = indexBody.firstAtom(); + QStack sectionStack; + bool inItem = false; + + while (atom) { + switch (atom->type()) { + case Atom::ListLeft: + sectionStack.push(0); + break; + case Atom::ListRight: + if (sectionStack.pop() > 0) + writer.writeEndElement(); // section + break; + case Atom::ListItemLeft: + inItem = true; + break; + case Atom::ListItemRight: + inItem = false; + break; + case Atom::Link: + if (inItem) { + if (sectionStack.top() > 0) + writer.writeEndElement(); // section + + const FakeNode *page = tree->findFakeNodeByTitle(atom->string()); + writer.writeStartElement("section"); + QString indexPath = tree->fullDocumentLocation(page); + writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); + writer.writeAttribute("title", atom->string()); + project.files.insert(indexPath); + + sectionStack.top() += 1; + } + break; + default: + ; + } + + if (atom == indexBody.lastAtom()) + break; + atom = atom->next(); + } + } else + rootNode->doc().location().warning( + tr("Failed to find index: %1").arg(subproject.indexTitle) + ); + } else { - // Find a contents node and navigate from there, using the NextLink values. - foreach (const Node *node, subproject.nodes) { - QString nextTitle = node->links().value(Node::NextLink).first; - if (!nextTitle.isEmpty() && - node->links().value(Node::ContentsLink).first.isEmpty()) { - - FakeNode *nextPage = const_cast(tree->findFakeNodeByTitle(nextTitle)); - - // Write the contents node. - writeNode(project, writer, node); - - while (nextPage) { - writeNode(project, writer, nextPage); - nextTitle = nextPage->links().value(Node::NextLink).first; - if(nextTitle.isEmpty()) - break; - nextPage = const_cast(tree->findFakeNodeByTitle(nextTitle)); + + if (!name.isEmpty()) { + writer.writeStartElement("section"); + QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle)); + writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); + writer.writeAttribute("title", subproject.title); + project.files.insert(indexPath); + } + if (subproject.sortPages) { + QStringList titles = subproject.nodes.keys(); + titles.sort(); + foreach (const QString &title, titles) + writeNode(project, writer, subproject.nodes[title]); + } else { + // Find a contents node and navigate from there, using the NextLink values. + foreach (const Node *node, subproject.nodes) { + QString nextTitle = node->links().value(Node::NextLink).first; + if (!nextTitle.isEmpty() && + node->links().value(Node::ContentsLink).first.isEmpty()) { + + FakeNode *nextPage = const_cast(tree->findFakeNodeByTitle(nextTitle)); + + // Write the contents node. + writeNode(project, writer, node); + + while (nextPage) { + writeNode(project, writer, nextPage); + nextTitle = nextPage->links().value(Node::NextLink).first; + if(nextTitle.isEmpty()) + break; + nextPage = const_cast(tree->findFakeNodeByTitle(nextTitle)); + } + break; } - break; } } - } - if (!name.isEmpty()) - writer.writeEndElement(); // section + if (!name.isEmpty()) + writer.writeEndElement(); // section + } } writer.writeEndElement(); // section diff --git a/tools/qdoc3/helpprojectwriter.h b/tools/qdoc3/helpprojectwriter.h index 511a9dd..7a67dff 100644 --- a/tools/qdoc3/helpprojectwriter.h +++ b/tools/qdoc3/helpprojectwriter.h @@ -60,6 +60,7 @@ struct SubProject QString indexTitle; QHash > selectors; bool sortPages; + QString type; QHash nodes; }; -- cgit v0.12