diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2011-02-10 22:35:31 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2011-02-10 22:35:31 (GMT) |
commit | ca13ba801144763b1ca7c39b2ef8594de94e2d3e (patch) | |
tree | 7600e31df6ce715a5bc28c0c97983bac9484c7cb /tools/qdoc3/htmlgenerator.cpp | |
parent | ab38731fe5dcfaa1a7a70bc290a8856b5b01524d (diff) | |
parent | ec20a6da3edea3031f1705c3b13e24dc2c7c6de5 (diff) | |
download | Qt-ca13ba801144763b1ca7c39b2ef8594de94e2d3e.zip Qt-ca13ba801144763b1ca7c39b2ef8594de94e2d3e.tar.gz Qt-ca13ba801144763b1ca7c39b2ef8594de94e2d3e.tar.bz2 |
Merge remote-tracking branch 'origin/4.7' into HEAD
Diffstat (limited to 'tools/qdoc3/htmlgenerator.cpp')
-rw-r--r-- | tools/qdoc3/htmlgenerator.cpp | 787 |
1 files changed, 271 insertions, 516 deletions
diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 9ddf6e8..0ff28af 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -56,6 +56,7 @@ #include <qlist.h> #include <qiterator.h> #include <qtextcodec.h> +#include <QUuid> QT_BEGIN_NAMESPACE @@ -63,10 +64,6 @@ QT_BEGIN_NAMESPACE int HtmlGenerator::id = 0; bool HtmlGenerator::debugging_on = false; -#if 0 -QString HtmlGenerator::divNavTop = "<div class=\"navTop\"><a href=\"#toc\"><img src=\"./images/bullet_up.png\"></a></div>"; -#endif - QString HtmlGenerator::divNavTop = ""; QString HtmlGenerator::sinceTitles[] = @@ -93,7 +90,7 @@ static bool showBrokenLinks = false; static QRegExp linkTag("(<@link node=\"([^\"]+)\">).*(</@link>)"); static QRegExp funcTag("(<@func target=\"([^\"]*)\">)(.*)(</@func>)"); static QRegExp typeTag("(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)"); -static QRegExp spanTag("</@(?:comment|preprocessor|string|char)>"); +static QRegExp spanTag("</@(?:comment|preprocessor|string|char|number|op|type|name|keyword)>"); static QRegExp unknownTag("</?@[^>]*>"); bool parseArg(const QString &src, @@ -214,15 +211,14 @@ static void addLink(const QString &linkTarget, HtmlGenerator::HtmlGenerator() : helpProjectWriter(0), inLink(false), + inObsoleteLink(false), inContents(false), inSectionHeading(false), inTableHeader(false), numTableRows(0), threeColumnEnumValueTable(true), - application(Online), funcLeftParen("\\S(\\()"), myTree(0), - slow(false), obsoleteLinks(false) { } @@ -263,19 +259,16 @@ void HtmlGenerator::initializeGenerator(const Config &config) style = config.getString(HtmlGenerator::format() + Config::dot + - HTMLGENERATOR_STYLE); + CONFIG_STYLE); + endHeader = config.getString(HtmlGenerator::format() + + Config::dot + + CONFIG_ENDHEADER); postHeader = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_POSTHEADER); postPostHeader = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_POSTPOSTHEADER); - creatorPostHeader = config.getString(HtmlGenerator::format() + - Config::dot + - HTMLGENERATOR_CREATORPOSTHEADER); - creatorPostPostHeader = config.getString(HtmlGenerator::format() + - Config::dot + - HTMLGENERATOR_CREATORPOSTPOSTHEADER); footer = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_FOOTER); @@ -288,14 +281,6 @@ void HtmlGenerator::initializeGenerator(const Config &config) project = config.getString(CONFIG_PROJECT); - QString app = config.getString(CONFIG_APPLICATION); - if (app == "online") - application = Online; - else if (app == "creator") - application = Creator; - else - application = Creator; - projectDescription = config.getString(CONFIG_DESCRIPTION); if (projectDescription.isEmpty() && !project.isEmpty()) projectDescription = project + " Reference Documentation"; @@ -334,19 +319,18 @@ void HtmlGenerator::initializeGenerator(const Config &config) ++edition; } - slow = config.getBool(CONFIG_SLOW); - - stylesheets = config.getStringList(HtmlGenerator::format() + - Config::dot + - HTMLGENERATOR_STYLESHEETS); - customHeadElements = config.getStringList(HtmlGenerator::format() + - Config::dot + - HTMLGENERATOR_CUSTOMHEADELEMENTS); codeIndent = config.getInt(CONFIG_CODEINDENT); helpProjectWriter = new HelpProjectWriter(config, project.toLower() + ".qhp"); + + // Documentation template handling + headerScripts = config.getString(HtmlGenerator::format() + Config::dot + + CONFIG_HEADERSCRIPTS); + headerStyles = config.getString(HtmlGenerator::format() + + Config::dot + + CONFIG_HEADERSTYLES); } void HtmlGenerator::terminateGenerator() @@ -360,11 +344,11 @@ QString HtmlGenerator::format() } /*! - This is where the html files and dcf files are written. - \note The html file generation is done in the base class, + This is where the HTML files are written. + \note The HTML file generation is done in the base class, PageGenerator::generateTree(). */ -void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) +void HtmlGenerator::generateTree(const Tree *tree) { myTree = tree; nonCompatClasses.clear(); @@ -383,48 +367,11 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) findAllNamespaces(tree->root()); findAllSince(tree->root()); - PageGenerator::generateTree(tree, marker); - - dcfClassesRoot.ref = "classes.html"; - dcfClassesRoot.title = "Classes"; - qSort(dcfClassesRoot.subsections); - - dcfOverviewsRoot.ref = "overviews.html"; - dcfOverviewsRoot.title = "Overviews"; - qSort(dcfOverviewsRoot.subsections); - - dcfExamplesRoot.ref = "examples.html"; - dcfExamplesRoot.title = "Tutorial & Examples"; - qSort(dcfExamplesRoot.subsections); - - DcfSection qtRoot; - appendDcfSubSection(&qtRoot, dcfClassesRoot); - appendDcfSubSection(&qtRoot, dcfOverviewsRoot); - appendDcfSubSection(&qtRoot, dcfExamplesRoot); - - generateDcf(project.toLower().simplified().replace(" ", "-"), - "index.html", - projectDescription, qtRoot); - generateDcf("designer", - "designer-manual.html", - "Qt Designer Manual", - dcfDesignerRoot); - generateDcf("linguist", - "linguist-manual.html", - "Qt Linguist Manual", - dcfLinguistRoot); - generateDcf("assistant", - "assistant-manual.html", - "Qt Assistant Manual", - dcfAssistantRoot); - generateDcf("qmake", - "qmake-manual.html", - "qmake Manual", - dcfQmakeRoot); + PageGenerator::generateTree(tree); QString fileBase = project.toLower().simplified().replace(" ", "-"); generateIndex(fileBase, projectUrl, projectDescription); - generatePageIndex(outputDir() + "/" + fileBase + ".pageindex", marker); + generatePageIndex(outputDir() + "/" + fileBase + ".pageindex"); helpProjectWriter->generate(myTree); } @@ -517,24 +464,33 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << "</p>\n"; break; case Atom::C: + // This may at one time have been used to mark up C++ code but it is + // now widely used to write teletype text. As a result, text marked + // with the \c command is not passed to a code marker. out() << formattingLeftMap()[ATOM_FORMATTING_TELETYPE]; if (inLink) { out() << protectEnc(plainCode(atom->string())); } else { - out() << highlightedCode(atom->string(), marker, relative); + out() << protectEnc(plainCode(atom->string())); } out() << formattingRightMap()[ATOM_FORMATTING_TELETYPE]; break; case Atom::Code: - out() << "<pre class=\"highlightedCode brush: cpp\">" + out() << "<pre class=\"cpp\">" << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), marker,relative)) << "</pre>\n"; break; #ifdef QDOC_QML case Atom::Qml: - out() << "<pre class=\"highlightedCode brush: cpp\">" + out() << "<pre class=\"qml\">" + << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), + marker,relative)) + << "</pre>\n"; + break; + case Atom::JavaScript: + out() << "<pre class=\"js\">" << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), marker,relative)) << "</pre>\n"; @@ -542,7 +498,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, #endif case Atom::CodeNew: out() << "<p>you can rewrite it as</p>\n" - << "<pre class=\"highlightedCode brush: cpp\">" + << "<pre class=\"cpp\">" << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), marker,relative)) << "</pre>\n"; @@ -551,10 +507,17 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << "<p>For example, if you have code like</p>\n"; // fallthrough case Atom::CodeBad: - out() << "<pre class=\"highlightedCode brush: cpp\">" + out() << "<pre class=\"cpp\">" << trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string())))) << "</pre>\n"; break; + case Atom::Div: + out() << "<div"; + if (!atom->string().isEmpty()) + out() << " class=\"" << atom->string() << "\">"; + else + out() << ">"; + break; case Atom::FootnoteLeft: // ### For now if (in_para) { @@ -1062,26 +1025,8 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << atom->string(); break; case Atom::SectionLeft: -#if 0 - { - int nextLevel = atom->string().toInt(); - if (sectionNumber.size() < nextLevel) { - do { - sectionNumber.append("1"); - } while (sectionNumber.size() < nextLevel); - } - else { - while (sectionNumber.size() > nextLevel) { - sectionNumber.removeLast(); - } - sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1); - } - out() << "<a name=\"sec-" << sectionNumber.join("-") << "\"></a>" << divNavTop << "\n"; - } -#else out() << "<a name=\"" << Doc::canonicalTitle(Text::sectionHeading(atom).toString()) << "\"></a>" << divNavTop << "\n"; -#endif break; case Atom::SectionRight: break; @@ -1180,33 +1125,6 @@ int HtmlGenerator::generateAtom(const Atom *atom, skipAhead = 1; break; case Atom::TableOfContents: - { - int numColumns = 1; - const Node *node = relative; - - Doc::SectioningUnit sectioningUnit = Doc::Section4; - QStringList params = atom->string().split(","); - QString columnText = params.at(0); - QStringList pieces = columnText.split(" ", QString::SkipEmptyParts); - if (pieces.size() >= 2) { - columnText = pieces.at(0); - pieces.pop_front(); - QString path = pieces.join(" ").trimmed(); - node = findNodeForTarget(path, relative, marker, atom); - } - - if (params.size() == 2) { - numColumns = qMax(columnText.toInt(), numColumns); - sectioningUnit = (Doc::SectioningUnit)params.at(1).toInt(); - } - - if (node) - generateTableOfContents(node, - marker, - sectioningUnit, - numColumns, - relative); - } break; case Atom::Target: out() << "<a name=\"" << Doc::canonicalTitle(atom->string()) << "\"></a>"; @@ -1218,6 +1136,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << "<b class=\"redFont\"><code>\\" << protectEnc(atom->string()) << "</code></b>"; break; + case Atom::EndDiv: + out() << "</div>"; + break; #ifdef QDOC_QML case Atom::QmlText: case Atom::EndQmlText: @@ -1258,11 +1179,6 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, title = rawTitle + " Class Reference"; } - DcfSection classSection; - classSection.title = title; - classSection.ref = linkForNode(inner, 0); - classSection.keywords += qMakePair(inner->name(), classSection.ref); - Text subtitleText; if (rawTitle != fullTitle) subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")" @@ -1425,8 +1341,6 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, names << plainCode(marker->markedUpEnumValue(enumName, enume)); } - foreach (const QString &name, names) - classSection.keywords += qMakePair(name,linkForNode(*m,0)); } ++m; } @@ -1435,39 +1349,15 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, ++s; } generateFooter(inner); - - if (!membersLink.isEmpty()) { - DcfSection membersSection; - membersSection.title = "List of all members"; - membersSection.ref = membersLink; - appendDcfSubSection(&classSection, membersSection); - } - if (!obsoleteLink.isEmpty()) { - DcfSection obsoleteSection; - obsoleteSection.title = "Obsolete members"; - obsoleteSection.ref = obsoleteLink; - appendDcfSubSection(&classSection, obsoleteSection); - } - if (!compatLink.isEmpty()) { - DcfSection compatSection; - compatSection.title = "Qt 3 support members"; - compatSection.ref = compatLink; - appendDcfSubSection(&classSection, compatSection); - } - - appendDcfSubSection(&dcfClassesRoot, classSection); } /*! - Generate the html page for a qdoc file that doesn't map - to an underlying c++ file. + Generate the HTML page for a qdoc file that doesn't map + to an underlying C++ file. */ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) { SubTitleSize subTitleSize = LargeSubTitle; - DcfSection fakeSection; - fakeSection.title = fake->fullTitle(); - fakeSection.ref = linkForNode(fake, 0); QList<Section> sections; QList<Section>::const_iterator s; @@ -1481,6 +1371,9 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) else if (fake->subType() == Node::QmlBasicType) { fullTitle = "QML Basic Type: " + fullTitle; htmlTitle = fullTitle; + + // Replace the marker with a QML code marker. + marker = CodeMarker::markerForLanguage(QLatin1String("QML")); } generateHeader(htmlTitle, fake, marker); @@ -1494,6 +1387,9 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) qml_cn = static_cast<const QmlClassNode*>(fake); sections = marker->qmlSections(qml_cn,CodeMarker::Summary,0); generateTableOfContents(fake,marker,§ions); + + // Replace the marker with a QML code marker. + marker = CodeMarker::markerForLanguage(QLatin1String("QML")); } else if (fake->name() != QString("index.html")) generateTableOfContents(fake,marker,0); @@ -1547,25 +1443,6 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) << "Qt 3 support members</a></li>\n"; out() << "</ul>\n"; - - if (!membersLink.isEmpty()) { - DcfSection membersSection; - membersSection.title = "List of all members"; - membersSection.ref = membersLink; - appendDcfSubSection(&fakeSection, membersSection); - } - if (!obsoleteLink.isEmpty()) { - DcfSection obsoleteSection; - obsoleteSection.title = "Obsolete members"; - obsoleteSection.ref = obsoleteLink; - appendDcfSubSection(&fakeSection, obsoleteSection); - } - if (!compatLink.isEmpty()) { - DcfSection compatSection; - compatSection.title = "Qt 3 support members"; - compatSection.ref = compatLink; - appendDcfSubSection(&fakeSection, compatSection); - } } #ifdef QDOC_QML else if (fake->subType() == Node::QmlClass) { @@ -1608,8 +1485,6 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) while (m != (*s).members.end()) { generateDetailedQmlMember(*m, fake, marker); out() << "<br/>\n"; - fakeSection.keywords += qMakePair((*m)->name(), - linkForNode(*m,0)); ++m; } ++s; @@ -1618,7 +1493,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) return; } #endif - + sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { @@ -1654,8 +1529,6 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) generateAnnotatedList(fake, marker, groupMembersMap); } - fakeSection.keywords += qMakePair(fakeSection.title, fakeSection.ref); - sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { @@ -1665,35 +1538,11 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) NodeList::ConstIterator m = (*s).members.begin(); while (m != (*s).members.end()) { generateDetailedMember(*m, fake, marker); - fakeSection.keywords += qMakePair((*m)->name(), linkForNode(*m, 0)); ++m; } ++s; } generateFooter(fake); - - if (fake->subType() == Node::Example) { - appendDcfSubSection(&dcfExamplesRoot, fakeSection); - } - else if (fake->subType() != Node::File) { - QString contentsPage = fake->links().value(Node::ContentsLink).first; - - if (contentsPage == "Qt Designer Manual") { - appendDcfSubSection(&dcfDesignerRoot, fakeSection); - } - else if (contentsPage == "Qt Linguist Manual") { - appendDcfSubSection(&dcfLinguistRoot, fakeSection); - } - else if (contentsPage == "Qt Assistant Manual") { - appendDcfSubSection(&dcfAssistantRoot, fakeSection); - } - else if (contentsPage == "qmake Manual") { - appendDcfSubSection(&dcfQmakeRoot, fakeSection); - } - else { - appendDcfSubSection(&dcfOverviewsRoot, fakeSection); - } - } } /*! @@ -1787,94 +1636,35 @@ void HtmlGenerator::generateHeader(const QString& title, out() << QString("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"%1\" lang=\"%1\">\n").arg(naturalLanguage); out() << "<head>\n"; out() << " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n"; - QString shortVersion; - shortVersion = project + " " + shortVersion + ": "; if (node && !node->doc().location().isEmpty()) out() << "<!-- " << node->doc().location().fileName() << " -->\n"; - shortVersion = myTree->version(); + QString shortVersion = myTree->version(); if (shortVersion.count(QChar('.')) == 2) shortVersion.truncate(shortVersion.lastIndexOf(QChar('.'))); - if (!shortVersion.isEmpty()) { - if (project == "QSA") - shortVersion = "QSA " + shortVersion + ": "; - else - shortVersion = "Qt " + shortVersion + ": "; - } + if (!project.isEmpty()) + shortVersion = project + QLatin1String(" ") + shortVersion + QLatin1String(": "); + else + shortVersion = QLatin1String("Qt ") + shortVersion + QLatin1String(": "); // Generating page title out() << " <title>" << shortVersion << protectEnc(title) << "</title>\n"; - // Adding style sheet - out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />\n"; - // Adding jquery and functions - providing online tools and search features - out() << " <script src=\"scripts/jquery.js\" type=\"text/javascript\"></script>\n"; - out() << " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n"; - - - // Adding syntax highlighter // future release - - // Setting some additional style sheet related details depending on configuration (e.g. Online/Creator) - - switch (application) { - case Online: - // Adding style and js for small windows - out() << " <script src=\"./scripts/superfish.js\" type=\"text/javascript\"></script>\n"; - out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/superfish.css\" />"; - out() << " <script src=\"./scripts/narrow.js\" type=\"text/javascript\"></script>\n"; - out() << " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/narrow.css\" />\n"; - // Browser spec styles - out() << " <!--[if IE]>\n"; - out() << "<meta name=\"MSSmartTagsPreventParsing\" content=\"true\">\n"; - out() << "<meta http-equiv=\"imagetoolbar\" content=\"no\">\n"; - out() << "<![endif]-->\n"; - out() << "<!--[if lt IE 7]>\n"; - out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie6.css\">\n"; - out() << "<![endif]-->\n"; - out() << "<!--[if IE 7]>\n"; - out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie7.css\">\n"; - out() << "<![endif]-->\n"; - out() << "<!--[if IE 8]>\n"; - out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie8.css\">\n"; - out() << "<![endif]-->\n"; - - out() << "</head>\n"; - // CheckEmptyAndLoadList activating search - out() << "<body class=\"\" onload=\"CheckEmptyAndLoadList();\">\n"; - break; - case Creator: - out() << "</head>\n"; - out() << "<body class=\"offline narrow creator\">\n"; // offline narrow - break; - default: - out() << "</head>\n"; - out() << "<body>\n"; - break; - } + + // Include style sheet and script links. + out() << headerStyles; + out() << headerScripts; + out() << endHeader; #ifdef GENERATE_MAC_REFS if (mainPage) generateMacRef(node, marker); #endif - switch (application) { - case Online: - out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - generateBreadCrumbs(title,node,marker); - out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - break; - case Creator: - out() << QString(creatorPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - generateBreadCrumbs(title,node,marker); - out() << QString(creatorPostPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - break; - default: // default -- not used except if one forgets to set any of the above settings to true - out() << QString(creatorPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - generateBreadCrumbs(title,node,marker); - out() << QString(creatorPostPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - break; - } + out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version()); + generateBreadCrumbs(title,node,marker); + out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - navigationLinks.clear(); + navigationLinks.clear(); if (node && !node->links().empty()) { QPair<QString,QString> linkPair; @@ -1960,30 +1750,8 @@ void HtmlGenerator::generateFooter(const Node *node) out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version()) << QString(address).replace("\\" + COMMAND_VERSION, myTree->version()); - switch (application) { - case Online: - out() << " <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n"; - out() << " <script type=\"text/javascript\">\n"; - out() << " var _gaq = _gaq || [];\n"; - out() << " _gaq.push(['_setAccount', 'UA-4457116-5']);\n"; - out() << " _gaq.push(['_trackPageview']);\n"; - out() << " (function() {\n"; - out() << " var ga = document.createElement('script'); "; - out() << "ga.type = 'text/javascript'; ga.async = true;\n"; - out() << " ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + "; - out() << "'.google-analytics.com/ga.js';\n"; - out() << " var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n"; - out() << " })();\n"; - out() << " </script>\n"; - out() << "</body>\n"; - break; - case Creator: - out() << "</body>\n"; - break; - default: - out() << "</body>\n"; - } - out() << "</html>\n"; + out() << "</body>\n"; + out() << "</html>\n"; } void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker, @@ -2009,7 +1777,7 @@ void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker, void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker) { if (!inner->includes().isEmpty()) { - out() << "<pre class=\"highlightedCode brush: cpp\">" + out() << "<pre class=\"cpp\">" << trimmedTrailing(highlightedCode(indent(codeIndent, marker->markedUpIncludes(inner->includes())), marker,inner)) @@ -2018,91 +1786,6 @@ void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker) } /*! - Generates a table of contents beginning at \a node. - */ -void HtmlGenerator::generateTableOfContents(const Node *node, - CodeMarker *marker, - Doc::SectioningUnit sectioningUnit, - int numColumns, - const Node *relative) - -{ - return; - if (!node->doc().hasTableOfContents()) - return; - QList<Atom *> toc = node->doc().tableOfContents(); - if (toc.isEmpty()) - return; - - QString nodeName = ""; - if (node != relative) - nodeName = node->name(); - - QStringList sectionNumber; - int columnSize = 0; - - QString tdTag; - if (numColumns > 1) { - tdTag = "<td>"; /* width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";*/ - out() << "<table class=\"toc\">\n<tr class=\"topAlign\">" - << tdTag << "\n"; - } - - // disable nested links in table of contents - inContents = true; - inLink = true; - - for (int i = 0; i < toc.size(); ++i) { - Atom *atom = toc.at(i); - - int nextLevel = atom->string().toInt(); - if (nextLevel > (int)sectioningUnit) - continue; - - if (sectionNumber.size() < nextLevel) { - do { - out() << "<ul>"; - sectionNumber.append("1"); - } while (sectionNumber.size() < nextLevel); - } - else { - while (sectionNumber.size() > nextLevel) { - out() << "</ul>\n"; - sectionNumber.removeLast(); - } - sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1); - } - int numAtoms; - Text headingText = Text::sectionHeading(atom); - - if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) { - out() << "</ul></td>" << tdTag << "<ul>\n"; - columnSize = 0; - } - out() << "<li>"; - out() << "<a href=\"" - << nodeName - << "#" - << Doc::canonicalTitle(headingText.toString()) - << "\">"; - generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms); - out() << "</a></li>\n"; - - ++columnSize; - } - while (!sectionNumber.isEmpty()) { - out() << "</ul>\n"; - sectionNumber.removeLast(); - } - - if (numColumns > 1) - out() << "</td></tr></table>\n"; - - inContents = false; - inLink = false; -} - -/*! Revised for the new doc format. Generates a table of contents beginning at \a node. */ @@ -2219,39 +1902,6 @@ void HtmlGenerator::generateTableOfContents(const Node *node, inLink = false; } -#if 0 -void HtmlGenerator::generateNavigationBar(const NavigationBar& bar, - const Node *node, - CodeMarker *marker) -{ - if (bar.prev.begin() != 0 || bar.current.begin() != 0 || - bar.next.begin() != 0) { - out() << "<p class=\"rightAlign\">"; - if (bar.prev.begin() != 0) { -#if 0 - out() << "[<a href=\"" << section.previousBaseName() - << ".html\">Prev: "; - generateText(section.previousHeading(), node, marker); - out() << "</a>]\n"; -#endif - } - if (fake->name() != QString("index.html")) { - if (bar.current.begin() != 0) { - out() << "[<a href=\"" << "home" - << ".html\">Home</a>]\n"; - } - if (bar.next.begin() != 0) { - out() << "[<a href=\"" << fileBase(node, bar.next) - << ".html\">Next: "; - generateText(Text::sectionHeading(bar.next.begin()), node, marker); - out() << "</a>]\n"; - } - out() << "</p>\n"; - } - } -} -#endif - QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker) { @@ -2421,7 +2071,7 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative, NodeMap newTop; foreach (const RelatedClass &d, child->derivedClasses()) { - if (d.access != Node::Private) + if (d.access != Node::Private && !d.node->doc().isEmpty()) newTop.insert(d.node->name(), d.node); } if (!newTop.isEmpty()) { @@ -3111,8 +2761,8 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" bool done = false; for (int i = 0, srcSize = src.size(); i < srcSize;) { - if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { - if (alignNames && !done) {// && (i != 0)) Why was this here? + if (src.at(i) == charLangle && src.at(i + 1) == charAt) { + if (alignNames && !done) { html += "</td><td class=\"memItemRight bottomAlign\">"; done = true; } @@ -3135,31 +2785,28 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, } - if (slow) { - // is this block ever used at all? - // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" - src = html; - html = QString(); - for (int i = 0, srcSize = src.size(); i < srcSize;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { - i += 2; - if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { - const Node* n = marker->resolveTarget(par1.toString(), - myTree, - relative); - QString link = linkForNode(n, relative); - addLink(link, arg, &html); - par1 = QStringRef(); - } - else { - html += charLangle; - html += charAt; - } + // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)(</@func>)" + src = html; + html = QString(); + for (int i = 0, srcSize = src.size(); i < srcSize;) { + if (src.at(i) == charLangle && src.at(i + 1) == charAt) { + i += 2; + if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { + const Node* n = marker->resolveTarget(par1.toString(), + myTree, + relative); + QString link = linkForNode(n, relative); + addLink(link, arg, &html); + par1 = QStringRef(); } else { - html += src.at(i++); + html += charLangle; + html += charAt; } } + else { + html += src.at(i++); + } } // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)(</@\\2>)" tags @@ -3173,6 +2820,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) { par1 = QStringRef(); const Node* n = marker->resolveTarget(arg.toString(), myTree, relative, self); + html += QLatin1String("<span class=\"type\">"); if (n && n->subType() == Node::QmlBasicType) { if (relative && relative->subType() == Node::QmlClass) addLink(linkForNode(n,relative), arg, &html); @@ -3181,6 +2829,7 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, } else addLink(linkForNode(n,relative), arg, &html); + html += QLatin1String("</span>"); handled = true; } else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) { @@ -3211,23 +2860,40 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // "<@preprocessor>" -> "<span class=\"preprocessor\">"; // "<@string>" -> "<span class=\"string\">"; // "<@char>" -> "<span class=\"char\">"; - // "</@(?:comment|preprocessor|string|char)>" -> "</span>" + // "<@number>" -> "<span class=\"number\">"; + // "<@op>" -> "<span class=\"operator\">"; + // "<@type>" -> "<span class=\"type\">"; + // "<@name>" -> "<span class=\"name\">"; + // "<@keyword>" -> "<span class=\"keyword\">"; + // "</@(?:comment|preprocessor|string|char|number|op|type|name|keyword)>" -> "</span>" src = html; html = QString(); static const QString spanTags[] = { - "<@comment>", "<span class=\"comment\">", - "<@preprocessor>", "<span class=\"preprocessor\">", - "<@string>", "<span class=\"string\">", - "<@char>", "<span class=\"char\">", - "</@comment>", "</span>", - "</@preprocessor>","</span>", - "</@string>", "</span>", - "</@char>", "</span>" + "<@comment>", "<span class=\"comment\">", + "<@preprocessor>", "<span class=\"preprocessor\">", + "<@string>", "<span class=\"string\">", + "<@char>", "<span class=\"char\">", + "<@number>", "<span class=\"number\">", + "<@op>", "<span class=\"operator\">", + "<@type>", "<span class=\"type\">", + "<@name>", "<span class=\"name\">", + "<@keyword>", "<span class=\"keyword\">", + "</@comment>", "</span>", + "</@preprocessor>", "</span>", + "</@string>", "</span>", + "</@char>", "</span>", + "</@number>", "</span>", + "</@op>", "</span>", + "</@type>", "</span>", + "</@name>", "</span>", + "</@keyword>", "</span>", }; + // Update the upper bound of k in the following code to match the length + // of the above array. for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle) { bool handled = false; - for (int k = 0; k != 8; ++k) { + for (int k = 0; k != 18; ++k) { const QString & tag = spanTags[2 * k]; if (tag == QStringRef(&src, i, tag.length())) { html += spanTags[2 * k + 1]; @@ -3278,18 +2944,6 @@ void HtmlGenerator::generateLink(const Atom* atom, } inLink = false; out() << protectEnc(atom->string().mid(k)); - } else if (marker->recognizeLanguage("Java")) { - // hack for Java: remove () and use <tt> when appropriate - bool func = atom->string().endsWith("()"); - bool tt = (func || atom->string().contains(camelCase)); - if (tt) - out() << "<tt>"; - if (func) { - out() << protectEnc(atom->string().left(atom->string().length() - 2)); - } else { - out() << protectEnc(atom->string()); - } - out() << "</tt>"; } else { out() << protectEnc(atom->string()); } @@ -3434,29 +3088,6 @@ QString HtmlGenerator::fileBase(const Node *node) const return result; } -#if 0 -QString HtmlGenerator::fileBase(const Node *node, - const SectionIterator& section) -{ - QStringList::ConstIterator s = section.sectionNumber().end(); - QStringList::ConstIterator b = section.baseNameStack().end(); - - QString suffix; - QString base = fileBase(node); - - while (s != section.sectionNumber().begin()) { - --s; - --b; - if (!(*b).isEmpty()) { - base = *b; - break; - } - suffix.prepend("-" + *s); - } - return base + suffix; -} -#endif - QString HtmlGenerator::fileName(const Node *node) { if (node->type() == Node::Fake) { @@ -3544,15 +3175,9 @@ QString HtmlGenerator::linkForNode(const Node *node, const Node *relative) return QString(); fn = fileName(node); -#if 0 - if (!node->url().isEmpty()) - return fn; -#endif +/* if (!node->url().isEmpty()) + return fn;*/ -#if 0 - // ### reintroduce this test, without breaking .dcf files - if (fn != outFileName()) -#endif link += fn; if (!node->isInnerNode() || node->subType() == Node::QmlPropertyGroup) { @@ -3811,6 +3436,7 @@ void HtmlGenerator::findAllFunctions(const InnerNode *node) else if ((*c)->type() == Node::Function) { const FunctionNode *func = static_cast<const FunctionNode *>(*c); if ((func->status() > Node::Obsolete) && + !func->isInternal() && (func->metaness() != FunctionNode::Ctor) && (func->metaness() != FunctionNode::Dtor)) { funcIndex[(*c)->name()].insert(myTree->fullDocumentName((*c)->parent()), *c); @@ -4016,14 +3642,6 @@ QString HtmlGenerator::getLink(const Atom *atom, << (*node)->name() << "no relative"; } } -#if 0 - else if ((*node)->status() == Node::Deprecated) { - qDebug() << "Link to Deprecated entity"; - } - else if ((*node)->status() == Node::Internal) { - qDebug() << "Link to Internal entity"; - } -#endif } while (!path.isEmpty()) { @@ -4044,16 +3662,6 @@ QString HtmlGenerator::getLink(const Atom *atom, return link; } -void HtmlGenerator::generateDcf(const QString &fileBase, - const QString &startPage, - const QString &title, - DcfSection &dcfRoot) -{ - dcfRoot.ref = startPage; - dcfRoot.title = title; - generateDcfSections(dcfRoot, outputDir() + "/" + fileBase + ".dcf", fileBase + "/reference"); -} - void HtmlGenerator::generateIndex(const QString &fileBase, const QString &url, const QString &title) @@ -4580,12 +4188,14 @@ void HtmlGenerator::generatePageElements(QXmlStreamWriter& writer, const Node* n /*! Outputs the file containing the index used for searching the html docs. */ -void HtmlGenerator::generatePageIndex(const QString& fileName, CodeMarker* marker) const +void HtmlGenerator::generatePageIndex(const QString& fileName) const { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) return ; + CodeMarker *marker = CodeMarker::markerForFileName(fileName); + QXmlStreamWriter writer(&file); writer.setAutoFormatting(true); writer.writeStartDocument(); @@ -4636,6 +4246,151 @@ void HtmlGenerator::generateExtractionMark(const Node *node, ExtractionMarkType } } +/*! + Returns the full document location for HTML-based documentation. + */ +QString HtmlGenerator::fullDocumentLocation(const Node *node) +{ + if (!node) + return ""; + if (!node->url().isEmpty()) + return node->url(); + + QString parentName; + QString anchorRef; + + if (node->type() == Node::Namespace) { + + // The root namespace has no name - check for this before creating + // an attribute containing the location of any documentation. + + if (!node->fileBase().isEmpty()) + parentName = node->fileBase() + ".html"; + else + return ""; + } + else if (node->type() == Node::Fake) { +#ifdef QDOC_QML + if ((node->subType() == Node::QmlClass) || + (node->subType() == Node::QmlBasicType)) { + QString fb = node->fileBase(); + if (fb.startsWith(Generator::outputPrefix(QLatin1String("QML")))) + return fb + ".html"; + else + return Generator::outputPrefix(QLatin1String("QML")) + node->fileBase() + QLatin1String(".html"); + } else +#endif + parentName = node->fileBase() + ".html"; + } + else if (node->fileBase().isEmpty()) + return ""; + + Node *parentNode = 0; + + if ((parentNode = node->relates())) + parentName = fullDocumentLocation(node->relates()); + else if ((parentNode = node->parent())) { + if (parentNode->subType() == Node::QmlPropertyGroup) { + parentNode = parentNode->parent(); + parentName = fullDocumentLocation(parentNode); + } + else + parentName = fullDocumentLocation(node->parent()); + } + + switch (node->type()) { + case Node::Class: + case Node::Namespace: + if (parentNode && !parentNode->name().isEmpty()) + parentName = parentName.replace(".html", "") + "-" + + node->fileBase().toLower() + ".html"; + else + parentName = node->fileBase() + ".html"; + break; + case Node::Function: + { + /* + Functions can be destructors, overloaded, or + have associated properties. + */ + const FunctionNode *functionNode = + static_cast<const FunctionNode *>(node); + + if (functionNode->metaness() == FunctionNode::Dtor) + anchorRef = "#dtor." + functionNode->name().mid(1); + + else if (functionNode->associatedProperty()) + return fullDocumentLocation(functionNode->associatedProperty()); + + else if (functionNode->overloadNumber() > 1) + anchorRef = "#" + functionNode->name() + + "-" + QString::number(functionNode->overloadNumber()); + else + anchorRef = "#" + functionNode->name(); + } + + /* + Use node->name() instead of node->fileBase() as + the latter returns the name in lower-case. For + HTML anchors, we need to preserve the case. + */ + break; + case Node::Enum: + anchorRef = "#" + node->name() + "-enum"; + break; + case Node::Typedef: + anchorRef = "#" + node->name() + "-typedef"; + break; + case Node::Property: + anchorRef = "#" + node->name() + "-prop"; + break; + case Node::QmlProperty: + anchorRef = "#" + node->name() + "-prop"; + break; + case Node::QmlSignal: + anchorRef = "#" + node->name() + "-signal"; + break; + case Node::QmlMethod: + anchorRef = "#" + node->name() + "-method"; + break; + case Node::Variable: + anchorRef = "#" + node->name() + "-var"; + break; + case Node::Target: + anchorRef = "#" + Doc::canonicalTitle(node->name()); + break; + case Node::Fake: + { + /* + Use node->fileBase() for fake nodes because they are represented + by pages whose file names are lower-case. + */ + parentName = node->fileBase(); + parentName.replace("/", "-").replace(".", "-"); + parentName += ".html"; + } + break; + default: + break; + } + + // Various objects can be compat (deprecated) or obsolete. + if (node->type() != Node::Class && node->type() != Node::Namespace) { + switch (node->status()) { + case Node::Compat: + parentName.replace(".html", "-qt3.html"); + break; + case Node::Obsolete: + parentName.replace(".html", "-obsolete.html"); + break; + default: + ; + } + } + + return parentName.toLower() + anchorRef; +} + #endif - QT_END_NAMESPACE +QT_END_NAMESPACE |