diff options
Diffstat (limited to 'tools/qdoc3/htmlgenerator.cpp')
-rw-r--r-- | tools/qdoc3/htmlgenerator.cpp | 2055 |
1 files changed, 1173 insertions, 882 deletions
diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index a3cdae6..76ee4e8 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -44,6 +44,7 @@ */ #include "codemarker.h" +#include "codeparser.h" #include "helpprojectwriter.h" #include "htmlgenerator.h" #include "node.h" @@ -54,10 +55,19 @@ #include <qdebug.h> #include <qlist.h> #include <qiterator.h> +#include <qtextcodec.h> QT_BEGIN_NAMESPACE #define COMMAND_VERSION Doc::alias("version") +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[] = { @@ -71,6 +81,7 @@ QString HtmlGenerator::sinceTitles[] = " New Typedefs", " New Properties", " New Variables", + " New QML Elements", " New Qml Properties", " New Qml Signals", " New Qml Methods", @@ -201,10 +212,18 @@ static void addLink(const QString &linkTarget, HtmlGenerator::HtmlGenerator() - : helpProjectWriter(0), inLink(false), inContents(false), - inSectionHeading(false), inTableHeader(false), numTableRows(0), - threeColumnEnumValueTable(true), funcLeftParen("\\S(\\()"), - myTree(0), slow(false), obsoleteLinks(false) + : helpProjectWriter(0), + inLink(false), + inContents(false), + inSectionHeading(false), + inTableHeader(false), + numTableRows(0), + threeColumnEnumValueTable(true), + application(Online), + funcLeftParen("\\S(\\()"), + myTree(0), + slow(false), + obsoleteLinks(false) { } @@ -248,6 +267,15 @@ void HtmlGenerator::initializeGenerator(const Config &config) 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); @@ -260,12 +288,29 @@ 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"; projectUrl = config.getString(CONFIG_URL); + outputEncoding = config.getString(CONFIG_OUTPUTENCODING); + if (outputEncoding.isEmpty()) + outputEncoding = QLatin1String("ISO-8859-1"); + outputCodec = QTextCodec::codecForName(outputEncoding.toLocal8Bit()); + + naturalLanguage = config.getString(CONFIG_NATURALLANGUAGE); + if (naturalLanguage.isEmpty()) + naturalLanguage = QLatin1String("en"); + QSet<QString> editionNames = config.subVars(CONFIG_EDITION); QSet<QString>::ConstIterator edition = editionNames.begin(); while (edition != editionNames.end()) { @@ -321,16 +366,6 @@ QString HtmlGenerator::format() */ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) { - // Copy the stylesheets from the directory containing the qdocconf file. - // ### This should be changed to use a special directory in doc/src. - QStringList::ConstIterator styleIter = stylesheets.begin(); - QDir configPath = QDir::current(); - while (styleIter != stylesheets.end()) { - QString filePath = configPath.absoluteFilePath(*styleIter); - Config::copyFile(Location(), filePath, filePath, outputDir()); - ++styleIter; - } - myTree = tree; nonCompatClasses.clear(); mainClasses.clear(); @@ -341,13 +376,11 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) funcIndex.clear(); legaleseTexts.clear(); serviceClasses.clear(); + qmlClasses.clear(); findAllClasses(tree->root()); findAllFunctions(tree->root()); findAllLegaleseTexts(tree->root()); findAllNamespaces(tree->root()); -#ifdef ZZZ_QDOC_QML - findAllQmlClasses(tree->root()); -#endif findAllSince(tree->root()); PageGenerator::generateTree(tree, marker); @@ -389,9 +422,9 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) "qmake Manual", dcfQmakeRoot); - generateIndex(project.toLower().simplified().replace(" ", "-"), - projectUrl, - projectDescription); + QString fileBase = project.toLower().simplified().replace(" ", "-"); + generateIndex(fileBase, projectUrl, projectDescription); + generatePageIndex(outputDir() + "/" + fileBase + ".pageindex", marker); helpProjectWriter->generate(myTree); } @@ -409,6 +442,9 @@ void HtmlGenerator::startText(const Node * /* relative */, sectionNumber.clear(); } +/*! + Generate html from an instance of Atom. + */ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker) @@ -431,11 +467,11 @@ int HtmlGenerator::generateAtom(const Atom *atom, endLink(); } else { - out() << protect(atom->string()); + out() << protectEnc(atom->string()); } } else { - out() << protect(atom->string()); + out() << protectEnc(atom->string()); } break; case Atom::BaseName: @@ -483,7 +519,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, case Atom::C: out() << formattingLeftMap()[ATOM_FORMATTING_TELETYPE]; if (inLink) { - out() << protect(plainCode(atom->string())); + out() << protectEnc(plainCode(atom->string())); } else { out() << highlightedCode(atom->string(), marker, relative); @@ -491,22 +527,22 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << formattingRightMap()[ATOM_FORMATTING_TELETYPE]; break; case Atom::Code: - out() << "<pre>" + out() << "<pre class=\"highlightedCode brush: cpp\">" << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), marker,relative)) << "</pre>\n"; - break; + break; #ifdef QDOC_QML case Atom::Qml: - out() << "<pre>" + out() << "<pre class=\"highlightedCode brush: cpp\">" << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), marker,relative)) << "</pre>\n"; - break; + break; #endif case Atom::CodeNew: out() << "<p>you can rewrite it as</p>\n" - << "<pre>" + << "<pre class=\"highlightedCode brush: cpp\">" << trimmedTrailing(highlightedCode(indent(codeIndent,atom->string()), marker,relative)) << "</pre>\n"; @@ -515,10 +551,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << "<p>For example, if you have code like</p>\n"; // fallthrough case Atom::CodeBad: - out() << "<pre><font color=\"#404040\">" - << trimmedTrailing(protect(plainCode(indent(codeIndent,atom->string())))) - << "</font></pre>\n"; - break; + out() << "<pre class=\"highlightedCode brush: cpp\">" + << trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string())))) + << "</pre>\n"; + break; case Atom::FootnoteLeft: // ### For now if (in_para) { @@ -574,7 +610,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, generateAnnotatedList(relative, marker, nonCompatClasses); } else if (atom->string() == "classes") { - generateCompactList(relative, marker, nonCompatClasses); + generateCompactList(relative, marker, nonCompatClasses, true); + } + else if (atom->string() == "qmlclasses") { + generateCompactList(relative, marker, qmlClasses, true); } else if (atom->string().contains("classesbymodule")) { QString arg = atom->string().trimmed(); @@ -622,10 +661,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, generateClassHierarchy(relative, marker, nonCompatClasses); } else if (atom->string() == "compatclasses") { - generateCompactList(relative, marker, compatClasses); + generateCompactList(relative, marker, compatClasses, false); } else if (atom->string() == "obsoleteclasses") { - generateCompactList(relative, marker, obsoleteClasses); + generateCompactList(relative, marker, obsoleteClasses, false); } else if (atom->string() == "functionindex") { generateFunctionIndex(relative, marker); @@ -634,10 +673,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, generateLegaleseList(relative, marker); } else if (atom->string() == "mainclasses") { - generateCompactList(relative, marker, mainClasses); + generateCompactList(relative, marker, mainClasses, true); } else if (atom->string() == "services") { - generateCompactList(relative, marker, serviceClasses); + generateCompactList(relative, marker, serviceClasses, false); } else if (atom->string() == "overviews") { generateOverviewList(relative, marker); @@ -676,16 +715,23 @@ int HtmlGenerator::generateAtom(const Atom *atom, nsmap = newSinceMaps.find(atom->string()); NewClassMaps::const_iterator ncmap; ncmap = newClassMaps.find(atom->string()); + NewClassMaps::const_iterator nqcmap; + nqcmap = newQmlClassMaps.find(atom->string()); if ((nsmap != newSinceMaps.constEnd()) && !nsmap.value().isEmpty()) { QList<Section> sections; QList<Section>::ConstIterator s; for (int i=0; i<LastSinceType; ++i) - sections.append(Section(sinceTitle(i),QString(),QString())); + sections.append(Section(sinceTitle(i),QString(),QString(),QString())); NodeMultiMap::const_iterator n = nsmap.value().constBegin(); while (n != nsmap.value().constEnd()) { const Node* node = n.value(); switch (node->type()) { + case Node::Fake: + if (node->subType() == Node::QmlClass) { + sections[QmlClass].appendMember((Node*)node); + } + break; case Node::Namespace: sections[Namespace].appendMember((Node*)node); break; @@ -768,9 +814,11 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << "<a name=\"" << Doc::canonicalTitle((*s).name) << "\"></a>\n"; - out() << "<h3>" << protect((*s).name) << "</h3>\n"; + out() << "<h3>" << protectEnc((*s).name) << "</h3>\n"; if (idx == Class) - generateCompactList(0, marker, ncmap.value(), QString("Q")); + generateCompactList(0, marker, ncmap.value(), false, QString("Q")); + else if (idx == QmlClass) + generateCompactList(0, marker, nqcmap.value(), false, QString("Q")); else if (idx == MemberFunction) { ParentMaps parentmaps; ParentMaps::iterator pmap; @@ -792,11 +840,11 @@ int HtmlGenerator::generateAtom(const Atom *atom, << linkForNode(pmap.key(), 0) << "\">"; QStringList pieces = fullName(pmap.key(), 0, marker).split("::"); - out() << protect(pieces.last()); + out() << protectEnc(pieces.last()); out() << "</a>" << ":</p>\n"; generateSection(nlist, 0, marker, CodeMarker::Summary); - out() << "<br />"; + out() << "<br/>"; ++pmap; } } @@ -817,15 +865,15 @@ int HtmlGenerator::generateAtom(const Atom *atom, if (atom->next() != 0) text = atom->next()->string(); if (atom->type() == Atom::Image) - out() << "<p align=\"center\">"; + out() << "<p class=\"centerAlign\">"; if (fileName.isEmpty()) { out() << "<font color=\"red\">[Missing image " - << protect(atom->string()) << "]</font>"; + << protectEnc(atom->string()) << "]</font>"; } else { - out() << "<img src=\"" << protect(fileName) << "\""; + out() << "<img src=\"" << protectEnc(fileName) << "\""; if (!text.isEmpty()) - out() << " alt=\"" << protect(text) << "\""; + out() << " alt=\"" << protectEnc(text) << "\""; out() << " />"; helpProjectWriter->addExtraFile(fileName); } @@ -836,13 +884,13 @@ int HtmlGenerator::generateAtom(const Atom *atom, case Atom::ImageText: break; case Atom::LegaleseLeft: - out() << "<div style=\"padding: 0.5em; background: #e0e0e0; color: black\">"; + out() << "<div class=\"LegaleseLeft\">"; break; case Atom::LegaleseRight: out() << "</div>"; break; case Atom::LineBreak: - out() << "<br />"; + out() << "<br/>"; break; case Atom::Link: { @@ -878,24 +926,26 @@ int HtmlGenerator::generateAtom(const Atom *atom, else if (atom->string() == ATOM_LIST_VALUE) { threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom); if (threeColumnEnumValueTable) { - out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" " - << "cellspacing=\"1\" width=\"100%\">\n" - << "<tr><th width=\"25%\">Constant</th>" - << "<th width=\"15%\">Value</th>" - << "<th width=\"60%\">Description</th></tr>\n"; + out() << "<table class=\"valuelist\">"; + if (++numTableRows % 2 == 1) + out() << "<tr class=\"odd\">"; + else + out() << "<tr class=\"even\">"; + + out() << "<th class=\"tblConst\">Constant</th>" + << "<th class=\"tblval\">Value</th>" + << "<th class=\"tbldscr\">Description</th></tr>\n"; } else { - out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" " - << "cellspacing=\"1\" width=\"40%\">\n" - << "<tr><th width=\"60%\">Constant</th><th " - << "width=\"40%\">Value</th></tr>\n"; + out() << "<table class=\"valuelist\">" + << "<tr><th class=\"tblConst\">Constant</th><th class=\"tblVal\">Value</th></tr>\n"; } } else { - out() << "<ol type="; + out() << "<ol class="; if (atom->string() == ATOM_LIST_UPPERALPHA) { out() << "\"A\""; - } + } /* why type? changed to */ else if (atom->string() == ATOM_LIST_LOWERALPHA) { out() << "\"a\""; } @@ -922,10 +972,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, else { // (atom->string() == ATOM_LIST_VALUE) // ### Trenton - out() << "<tr><td valign=\"top\"><tt>" - << protect(plainCode(marker->markedUpEnumValue(atom->next()->string(), + out() << "<tr><td class=\"topAlign\"><tt>" + << protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(), relative))) - << "</tt></td><td align=\"center\" valign=\"top\">"; + << "</tt></td><td class=\" topAlign\">"; QString itemValue; if (relative->type() == Node::Enum) { @@ -936,7 +986,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, if (itemValue.isEmpty()) out() << "?"; else - out() << "<tt>" << protect(itemValue) << "</tt>"; + out() << "<tt>" << protectEnc(itemValue) << "</tt>"; skipAhead = 1; } @@ -951,7 +1001,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, } else if (atom->string() == ATOM_LIST_VALUE) { if (threeColumnEnumValueTable) { - out() << "</td><td valign=\"top\">"; + out() << "</td><td class=\"topAlign\">"; if (matchAhead(atom, Atom::ListItemRight)) out() << " "; } @@ -981,7 +1031,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << "</dl>\n"; } else if (atom->string() == ATOM_LIST_VALUE) { - out() << "</table></p>\n"; + out() << "</table>\n"; } else { out() << "</ol>\n"; @@ -1026,11 +1076,11 @@ int HtmlGenerator::generateAtom(const Atom *atom, } sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1); } - out() << "<a name=\"sec-" << sectionNumber.join("-") << "\"></a>\n"; + out() << "<a name=\"sec-" << sectionNumber.join("-") << "\"></a>" << divNavTop << "\n"; } #else out() << "<a name=\"" << Doc::canonicalTitle(Text::sectionHeading(atom).toString()) - << "\"></a>\n"; + << "\"></a>" << divNavTop << "\n"; #endif break; case Atom::SectionRight: @@ -1052,7 +1102,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, generateLink(atom, relative, marker); } else { - out() << protect(atom->string()); + out() << protectEnc(atom->string()); } break; case Atom::TableLeft: @@ -1062,32 +1112,28 @@ int HtmlGenerator::generateAtom(const Atom *atom, } if (!atom->string().isEmpty()) { if (atom->string().contains("%")) - out() << "<p><table class=\"generic\" width=\"" << atom->string() << "\" " - << "align=\"center\" cellpadding=\"2\" " - << "cellspacing=\"1\" border=\"0\">\n"; + out() << "<table class=\"generic\">\n "; // width=\"" << atom->string() << "\">\n "; else { - out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" " - << "cellspacing=\"1\" border=\"0\">\n"; + out() << "<table class=\"generic\">\n"; } } else { - out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" " - << "cellspacing=\"1\" border=\"0\">\n"; + out() << "<table class=\"generic\">\n"; } numTableRows = 0; break; case Atom::TableRight: - out() << "</table></p>\n"; + out() << "</table>\n"; break; case Atom::TableHeaderLeft: - out() << "<thead><tr valign=\"top\" class=\"qt-style\">"; + out() << "<thead><tr class=\"qt-style topAlign\">"; inTableHeader = true; break; case Atom::TableHeaderRight: out() << "</tr>"; if (matchAhead(atom, Atom::TableHeaderLeft)) { skipAhead = 1; - out() << "\n<tr valign=\"top\" class=\"qt-style\">"; + out() << "\n<tr class=\"qt-style topAlign\">"; } else { out() << "</thead>\n"; @@ -1096,9 +1142,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, break; case Atom::TableRowLeft: if (++numTableRows % 2 == 1) - out() << "<tr valign=\"top\" class=\"odd\">"; + out() << "<tr class=\"odd topAlign\">"; else - out() << "<tr valign=\"top\" class=\"even\">"; + out() << "<tr class=\"even topAlign\">"; break; case Atom::TableRowRight: out() << "</tr>\n"; @@ -1106,9 +1152,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, case Atom::TableItemLeft: { if (inTableHeader) - out() << "<th"; + out() << "<th "; else - out() << "<td"; + out() << "<td "; QStringList spans = atom->string().split(","); if (spans.size() == 2) { @@ -1116,7 +1162,10 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << " colspan=\"" << spans.at(0) << "\""; if (spans.at(1) != "1") out() << " rowspan=\"" << spans.at(1) << "\""; + if (inTableHeader) out() << ">"; + else + out() << "><p>"; } if (matchAhead(atom, Atom::ParaLeft)) skipAhead = 1; @@ -1126,7 +1175,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, if (inTableHeader) out() << "</th>"; else - out() << "</td>"; + out() << "</p></td>"; if (matchAhead(atom, Atom::ParaLeft)) skipAhead = 1; break; @@ -1163,11 +1212,11 @@ int HtmlGenerator::generateAtom(const Atom *atom, out() << "<a name=\"" << Doc::canonicalTitle(atom->string()) << "\"></a>"; break; case Atom::UnhandledFormat: - out() << "<font color=\"red\"><b><Missing HTML></b></font>"; + out() << "<b class=\"redFont\"><Missing HTML></b>"; break; case Atom::UnknownCommand: - out() << "<font color=\"red\"><b><code>\\" << protect(atom->string()) - << "</code></b></font>"; + out() << "<b class=\"redFont\"><code>\\" << protectEnc(atom->string()) + << "</code></b>"; break; #ifdef QDOC_QML case Atom::QmlText: @@ -1181,6 +1230,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, return skipAhead; } +/*! + Generate a reference page for a C++ class. + */ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, CodeMarker *marker) { @@ -1197,7 +1249,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, namespasse = static_cast<const NamespaceNode *>(inner); rawTitle = marker->plainName(inner); fullTitle = marker->plainFullName(inner); - title = rawTitle + " Namespace Reference"; + title = rawTitle + " Namespace"; } else if (inner->type() == Node::Class) { classe = static_cast<const ClassNode *>(inner); @@ -1216,43 +1268,21 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")" << Atom(Atom::LineBreak); - QString fixedModule = inner->moduleName(); - if (fixedModule == "Qt3SupportLight") - fixedModule = "Qt3Support"; - if (!fixedModule.isEmpty()) - subtitleText << "[" << Atom(Atom::AutoLink, fixedModule) << " module]"; - - if (fixedModule.isEmpty()) { - QMultiMap<QString, QString> publicGroups = myTree->publicGroups(); - QList<QString> groupNames = publicGroups.values(inner->name()); - if (!groupNames.isEmpty()) { - qSort(groupNames.begin(), groupNames.end()); - subtitleText << "["; - for (int j=0; j<groupNames.count(); j++) { - subtitleText << Atom(Atom::AutoLink, groupNames[j]); - if (j<groupNames.count()-1) - subtitleText <<", "; - } - subtitleText << "]"; - } - } - - generateHeader(title, inner, marker, true); - generateTitle(title, subtitleText, SmallSubTitle, inner, marker); - -#ifdef QDOC_QML - if (classe && !classe->qmlElement().isEmpty()) { - generateInstantiatedBy(classe,marker); - } -#endif - + generateHeader(title, inner, marker); + sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay); + generateTableOfContents(inner,marker,§ions); + generateTitle(title, subtitleText, SmallSubTitle, inner, marker); generateBrief(inner, marker); generateIncludes(inner, marker); generateStatus(inner, marker); if (classe) { - generateModuleWarning(classe, marker); generateInherits(classe, marker); generateInheritedBy(classe, marker); +#ifdef QDOC_QML + if (!classe->qmlElement().isEmpty()) { + generateInstantiatedBy(classe,marker); + } +#endif } generateThreadSafeness(inner, marker); generateSince(inner, marker); @@ -1282,7 +1312,9 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, bool needOtherSection = false; - sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay); + /* + sections is built above for the call to generateTableOfContents(). + */ s = sections.begin(); while (s != sections.end()) { if (s->members.isEmpty() && s->reimpMembers.isEmpty()) { @@ -1291,26 +1323,26 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, } else { if (!s->members.isEmpty()) { - out() << "<hr />\n"; + // out() << "<hr />\n"; out() << "<a name=\"" << registerRef((*s).name.toLower()) - << "\"></a>\n"; - out() << "<h2>" << protect((*s).name) << "</h2>\n"; + << "\"></a>" << divNavTop << "\n"; + out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; generateSection(s->members, inner, marker, CodeMarker::Summary); } if (!s->reimpMembers.isEmpty()) { QString name = QString("Reimplemented ") + (*s).name; - out() << "<hr />\n"; + // out() << "<hr />\n"; out() << "<a name=\"" << registerRef(name.toLower()) - << "\"></a>\n"; - out() << "<h2>" << protect(name) << "</h2>\n"; + << "\"></a>" << divNavTop << "\n"; + out() << "<h2>" << protectEnc(name) << "</h2>\n"; generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary); } if (!s->inherited.isEmpty()) { out() << "<ul>\n"; - generateSectionInheritedList(*s, inner, marker, true); + generateSectionInheritedList(*s, inner, marker); out() << "</ul>\n"; } } @@ -1330,20 +1362,26 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, out() << "</ul>\n"; } - out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; + out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << "\n"; if (!inner->doc().isEmpty()) { - out() << "<hr />\n" + generateExtractionMark(inner, DetailedDescriptionMark); + //out() << "<hr />\n" + out() << "<div class=\"descr\">\n" // QTBUG-9504 << "<h2>" << "Detailed Description" << "</h2>\n"; generateBody(inner, marker); + out() << "</div>\n"; // QTBUG-9504 generateAlsoList(inner, marker); + generateExtractionMark(inner, EndMark); } sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { - out() << "<hr />\n"; - out() << "<h2>" << protect((*s).name) << "</h2>\n"; + //out() << "<hr />\n"; + if (!(*s).divClass.isEmpty()) + out() << "<div class=\"" << (*s).divClass << "\">\n"; // QTBUG-9504 + out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; NodeList::ConstIterator m = (*s).members.begin(); while (m != (*s).members.end()) { @@ -1392,6 +1430,8 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, } ++m; } + if (!(*s).divClass.isEmpty()) + out() << "</div>\n"; // QTBUG-9504 ++s; } generateFooter(inner); @@ -1418,6 +1458,10 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, appendDcfSubSection(&dcfClassesRoot, classSection); } +/*! + 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; @@ -1428,14 +1472,33 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) QList<Section> sections; QList<Section>::const_iterator s; - QString htmlTitle = fake->fullTitle(); + QString fullTitle = fake->fullTitle(); + QString htmlTitle = fullTitle; if (fake->subType() == Node::File && !fake->subTitle().isEmpty()) { subTitleSize = SmallSubTitle; htmlTitle += " (" + fake->subTitle() + ")"; } + else if (fake->subType() == Node::QmlBasicType) { + fullTitle = "QML Basic Type: " + fullTitle; + htmlTitle = fullTitle; + } + + generateHeader(htmlTitle, fake, marker); + + /* + Generate the TOC for the new doc format. + Don't generate a TOC for the home page. + */ + const QmlClassNode* qml_cn = 0; + if (fake->subType() == Node::QmlClass) { + qml_cn = static_cast<const QmlClassNode*>(fake); + sections = marker->qmlSections(qml_cn,CodeMarker::Summary,0); + generateTableOfContents(fake,marker,§ions); + } + else if (fake->name() != QString("index.html")) + generateTableOfContents(fake,marker,0); - generateHeader(htmlTitle, fake, marker, true); - generateTitle(fake->fullTitle(), + generateTitle(fullTitle, Text() << fake->subTitle(), subTitleSize, fake, @@ -1447,10 +1510,12 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) generateStatus(fake, marker); if (moduleNamespaceMap.contains(fake->name())) { + out() << "<a name=\"" << registerRef("namespaces") << "\"></a>" << divNavTop << "\n"; out() << "<h2>Namespaces</h2>\n"; generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]); } if (moduleClassMap.contains(fake->name())) { + out() << "<a name=\"" << registerRef("classes") << "\"></a>" << divNavTop << "\n"; out() << "<h2>Classes</h2>\n"; generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]); } @@ -1504,36 +1569,45 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) } #ifdef QDOC_QML else if (fake->subType() == Node::QmlClass) { - const QmlClassNode* qml_cn = static_cast<const QmlClassNode*>(fake); const ClassNode* cn = qml_cn->classNode(); + generateBrief(qml_cn, marker); generateQmlInherits(qml_cn, marker); + generateQmlInheritedBy(qml_cn, marker); generateQmlInstantiates(qml_cn, marker); - generateBrief(qml_cn, marker); - sections = marker->qmlSections(qml_cn,CodeMarker::Summary); + + QString allQmlMembersLink = generateAllQmlMembersFile(qml_cn, marker); + if (!allQmlMembersLink.isEmpty()) { + out() << "<li><a href=\"" << allQmlMembersLink << "\">" + << "List of all members, including inherited members</a></li>\n"; + } + s = sections.begin(); while (s != sections.end()) { - out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n"; - out() << "<h2>" << protect((*s).name) << "</h2>\n"; + out() << "<a name=\"" << registerRef((*s).name.toLower()) + << "\"></a>" << divNavTop << "\n"; + out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; generateQmlSummary(*s,fake,marker); ++s; } - out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; + generateExtractionMark(fake, DetailedDescriptionMark); + out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << "\n"; out() << "<h2>" << "Detailed Description" << "</h2>\n"; generateBody(fake, marker); if (cn) generateQmlText(cn->doc().body(), cn, marker, fake->name()); generateAlsoList(fake, marker); - out() << "<hr />\n"; + generateExtractionMark(fake, EndMark); + //out() << "<hr />\n"; - sections = marker->qmlSections(qml_cn,CodeMarker::Detailed); + sections = marker->qmlSections(qml_cn,CodeMarker::Detailed,0); s = sections.begin(); while (s != sections.end()) { - out() << "<h2>" << protect((*s).name) << "</h2>\n"; + out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; NodeList::ConstIterator m = (*s).members.begin(); while (m != (*s).members.end()) { generateDetailedQmlMember(*m, fake, marker); - out() << "<br />\n"; + out() << "<br/>\n"; fakeSection.keywords += qMakePair((*m)->name(), linkForNode(*m,0)); ++m; @@ -1548,20 +1622,28 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { - out() << "<a name=\"" << registerRef((*s).name) << "\"></a>\n"; - out() << "<h2>" << protect((*s).name) << "</h2>\n"; + out() << "<a name=\"" << registerRef((*s).name) << "\"></a>" << divNavTop << "\n"; + out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; generateSectionList(*s, fake, marker, CodeMarker::Summary); ++s; } Text brief = fake->doc().briefText(); if (fake->subType() == Node::Module && !brief.isEmpty()) { - out() << "<a name=\"" << registerRef("details") << "\"></a>\n"; + generateExtractionMark(fake, DetailedDescriptionMark); + out() << "<a name=\"" << registerRef("details") << "\"></a>" << divNavTop << "\n"; + out() << "<div class=\"descr\">\n"; // QTBUG-9504 out() << "<h2>" << "Detailed Description" << "</h2>\n"; } + else { + generateExtractionMark(fake, DetailedDescriptionMark); + out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504 + } generateBody(fake, marker); + out() << "</div>\n"; // QTBUG-9504 generateAlsoList(fake, marker); + generateExtractionMark(fake, EndMark); if (!fake->groupMembers().isEmpty()) { NodeMap groupMembersMap; @@ -1577,8 +1659,8 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { - out() << "<hr />\n"; - out() << "<h2>" << protect((*s).name) << "</h2>\n"; + //out() << "<hr />\n"; + out() << "<h2>" << protectEnc((*s).name) << "</h2>\n"; NodeList::ConstIterator m = (*s).members.begin(); while (m != (*s).members.end()) { @@ -1614,55 +1696,185 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) } } -QString HtmlGenerator::fileExtension(const Node * /* node */) +/*! + Returns "html" for this subclass of Generator. + */ +QString HtmlGenerator::fileExtension(const Node * /* node */) const { return "html"; } +/*! + Output breadcrumb list in the html file. + */ +void HtmlGenerator::generateBreadCrumbs(const QString& title, + const Node *node, + CodeMarker *marker) +{ + Text breadcrumb; + if (node->type() == Node::Class) { + const ClassNode* cn = static_cast<const ClassNode*>(node); + QString name = node->moduleName(); + out() << " <li><a href=\"modules.html\">Modules</a></li>"; + if (!name.isEmpty()) { + out() << " <li>"; + breadcrumb << Atom(Atom::AutoLink,name); + generateText(breadcrumb, node, marker); + out() << "</li>\n"; + } + if (!cn->name().isEmpty()) + out() << " <li>" << protectEnc(cn->name()) << "</li>\n"; + } + else if (node->type() == Node::Fake) { + const FakeNode* fn = static_cast<const FakeNode*>(node); + if (node->subType() == Node::Module) { + out() << " <li><a href=\"modules.html\">Modules</a></li>"; + QString name = node->name(); + if (!name.isEmpty()) + out() << " <li>" << protectEnc(name) << "</li>\n"; + } + else if (node->subType() == Node::Group) { + if (fn->name() == QString("modules")) + out() << " <li>Modules</li>"; + else { + out() << " <li>" << protectEnc(title) << "</li>"; + } + } + else if (node->subType() == Node::Page) { + if (fn->name() == QString("qdeclarativeexamples.html")) { + out() << " <li><a href=\"all-examples.html\">Examples</a></li>"; + out() << " <li>QML Examples & Demos</li>"; + } + else if (fn->name().startsWith("examples-")) { + out() << " <li><a href=\"all-examples.html\">Examples</a></li>"; + out() << " <li>" << protectEnc(title) << "</li>"; + } + else if (fn->name() == QString("namespaces.html")) { + out() << " <li>Namespaces</li>"; + } + else { + out() << " <li>" << protectEnc(title) << "</li>"; + } + } + else if (node->subType() == Node::QmlClass) { + out() << " <li><a href=\"qdeclarativeelements.html\">QML Elements</a></li>"; + out() << " <li>" << protectEnc(title) << "</li>"; + } + else if (node->subType() == Node::Example) { + out() << " <li><a href=\"all-examples.html\">Examples</a></li>"; + QStringList sl = fn->name().split('/'); + if (sl.contains("declarative")) + out() << " <li><a href=\"qdeclarativeexamples.html\">QML Examples & Demos</a></li>"; + else { + QString name = protectEnc("examples-" + sl.at(0) + ".html"); // this generates an empty link + QString t = CodeParser::titleFromName(name); + } + out() << " <li>" << protectEnc(title) << "</li>"; + } + } + else if (node->type() == Node::Namespace) { + out() << " <li><a href=\"namespaces.html\">Namespaces</a></li>"; + out() << " <li>" << protectEnc(title) << "</li>"; + } +} + void HtmlGenerator::generateHeader(const QString& title, const Node *node, - CodeMarker *marker, - bool mainPage) + CodeMarker *marker) { - out() << "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"; - - out() << "<!DOCTYPE html\n" - " PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n" - "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"; - + out() << QString("<?xml version=\"1.0\" encoding=\"%1\"?>\n").arg(outputEncoding); + out() << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"; + 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; - if ((project != "Qtopia") && (project != "Qt Extended")) { - shortVersion = project + " " + shortVersion + ": "; - if (node && !node->doc().location().isEmpty()) - out() << "<!-- " << node->doc().location().fileName() << " -->\n"; - - 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 + ": "; - } + shortVersion = project + " " + shortVersion + ": "; + if (node && !node->doc().location().isEmpty()) + out() << "<!-- " << node->doc().location().fileName() << " -->\n"; + + 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 + ": "; + } + + // 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; } - out() << "<head>\n" - " <title>" << shortVersion << protect(title) << "</title>\n"; - if (!style.isEmpty()) - out() << " <style type=\"text/css\">" << style << "</style>\n"; - - const QMap<QString, QString> &metaMap = node->doc().metaTagMap(); - if (!metaMap.isEmpty()) { - QMapIterator<QString, QString> i(metaMap); - while (i.hasNext()) { - i.next(); - out() << " <meta name=\"" << protect(i.key()) << "\" contents=\"" - << protect(i.value()) << "\" />\n"; - } +#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; } - navigationLinks.clear(); + navigationLinks.clear(); if (node && !node->links().empty()) { QPair<QString,QString> linkPair; @@ -1687,24 +1899,6 @@ void HtmlGenerator::generateHeader(const QString& title, navigationLinks += protect(linkPair.second); navigationLinks += "</a>]\n"; } - if (node->links().contains(Node::ContentsLink)) { - linkPair = node->links()[Node::ContentsLink]; - linkNode = findNodeForTarget(linkPair.first, node, marker); - if (!linkNode || linkNode == node) - anchorPair = linkPair; - else - anchorPair = anchorForNode(linkNode); - - out() << " <link rel=\"contents\" href=\"" - << anchorPair.first << "\" />\n"; - - navigationLinks += "[<a href=\"" + anchorPair.first + "\">"; - if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty()) - navigationLinks += protect(anchorPair.second); - else - navigationLinks += protect(linkPair.second); - navigationLinks += "</a>]\n"; - } if (node->links().contains(Node::NextLink)) { linkPair = node->links()[Node::NextLink]; linkNode = findNodeForTarget(linkPair.first, node, marker); @@ -1723,16 +1917,6 @@ void HtmlGenerator::generateHeader(const QString& title, navigationLinks += protect(linkPair.second); navigationLinks += "</a>]\n"; } - if (node->links().contains(Node::IndexLink)) { - linkPair = node->links()[Node::IndexLink]; - linkNode = findNodeForTarget(linkPair.first, node, marker); - if (!linkNode || linkNode == node) - anchorPair = linkPair; - else - anchorPair = anchorForNode(linkNode); - out() << " <link rel=\"index\" href=\"" - << anchorPair.first << "\" />\n"; - } if (node->links().contains(Node::StartLink)) { linkPair = node->links()[Node::StartLink]; linkNode = findNodeForTarget(linkPair.first, node, marker); @@ -1745,24 +1929,8 @@ void HtmlGenerator::generateHeader(const QString& title, } } - foreach (const QString &stylesheet, stylesheets) { - out() << " <link href=\"" << stylesheet << "\" rel=\"stylesheet\" " - << "type=\"text/css\" />\n"; - } - - foreach (const QString &customHeadElement, customHeadElements) { - out() << " " << customHeadElement << "\n"; - } - - out() << "</head>\n" - "<body>\n"; - if (mainPage) - generateMacRef(node, marker); - out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version()); - - if (node && !node->links().empty()) - out() << "<p>\n" << navigationLinks << "</p>\n"; + out() << "<p class=\"naviNextPrevious headerNavi\">\n" << navigationLinks << "</p><p/>\n"; } void HtmlGenerator::generateTitle(const QString& title, @@ -1771,28 +1939,51 @@ void HtmlGenerator::generateTitle(const QString& title, const Node *relative, CodeMarker *marker) { - out() << "<h1 class=\"title\">" << protect(title); + if (!title.isEmpty()) + out() << "<h1 class=\"title\">" << protectEnc(title) << "</h1>\n"; if (!subTitle.isEmpty()) { - out() << "<br />"; + out() << "<span"; if (subTitleSize == SmallSubTitle) - out() << "<span class=\"small-subtitle\">"; + out() << " class=\"small-subtitle\">"; else - out() << "<span class=\"subtitle\">"; + out() << " class=\"subtitle\">"; generateText(subTitle, relative, marker); out() << "</span>\n"; } - out() << "</h1>\n"; } void HtmlGenerator::generateFooter(const Node *node) { if (node && !node->links().empty()) - out() << "<p>\n" << navigationLinks << "</p>\n"; + out() << "<p class=\"naviNextPrevious footerNavi\">\n" << navigationLinks << "</p>\n"; out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version()) - << QString(address).replace("\\" + COMMAND_VERSION, myTree->version()) - << "</body>\n" - "</html>\n"; + << 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"; } void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker, @@ -1800,20 +1991,25 @@ void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker, { Text brief = node->doc().briefText(); if (!brief.isEmpty()) { + generateExtractionMark(node, BriefMark); out() << "<p>"; generateText(brief, node, marker); + if (!relative || node == relative) out() << " <a href=\"#"; else out() << " <a href=\"" << linkForNode(node, relative) << "#"; out() << registerRef("details") << "\">More...</a></p>\n"; + + + generateExtractionMark(node, EndMark); } } void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker) { if (!inner->includes().isEmpty()) { - out() << "<pre>" + out() << "<pre class=\"highlightedCode brush: cpp\">" << trimmedTrailing(highlightedCode(indent(codeIndent, marker->markedUpIncludes(inner->includes())), marker,inner)) @@ -1821,6 +2017,9 @@ 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, @@ -1828,6 +2027,7 @@ void HtmlGenerator::generateTableOfContents(const Node *node, const Node *relative) { + return; if (!node->doc().hasTableOfContents()) return; QList<Atom *> toc = node->doc().tableOfContents(); @@ -1843,8 +2043,8 @@ void HtmlGenerator::generateTableOfContents(const Node *node, QString tdTag; if (numColumns > 1) { - tdTag = "<td width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">"; - out() << "<p><table class=\"toc\" width=\"100%\">\n<tr valign=\"top\">" + tdTag = "<td>"; /* width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";*/ + out() << "<table class=\"toc\">\n<tr class=\"topAlign\">" << tdTag << "\n"; } @@ -1896,8 +2096,125 @@ void HtmlGenerator::generateTableOfContents(const Node *node, } if (numColumns > 1) - out() << "</td></tr></table></p>\n"; + out() << "</td></tr></table>\n"; + + inContents = false; + inLink = false; +} + +/*! + Revised for the new doc format. + Generates a table of contents beginning at \a node. + */ +void HtmlGenerator::generateTableOfContents(const Node *node, + CodeMarker *marker, + QList<Section>* sections) +{ + QList<Atom*> toc; + if (node->doc().hasTableOfContents()) + toc = node->doc().tableOfContents(); + if (toc.isEmpty() && !sections && (node->subType() != Node::Module)) + return; + + QStringList sectionNumber; + int detailsBase = 0; + + // disable nested links in table of contents + inContents = true; + inLink = true; + + out() << "<div class=\"toc\">\n"; + out() << "<h3><a name=\"toc\">Contents</a></h3>\n"; + sectionNumber.append("1"); + out() << "<ul>\n"; + + if (node->subType() == Node::Module) { + if (moduleNamespaceMap.contains(node->name())) { + out() << "<li class=\"level" + << sectionNumber.size() + << "\"><a href=\"#" + << registerRef("namespaces") + << "\">Namespaces</a></li>\n"; + } + if (moduleClassMap.contains(node->name())) { + out() << "<li class=\"level" + << sectionNumber.size() + << "\"><a href=\"#" + << registerRef("classes") + << "\">Classes</a></li>\n"; + } + out() << "<li class=\"level" + << sectionNumber.size() + << "\"><a href=\"#" + << registerRef("details") + << "\">Detailed Description</a></li>\n"; + for (int i = 0; i < toc.size(); ++i) { + if (toc.at(i)->string().toInt() == 1) { + detailsBase = 1; + break; + } + } + } + else if (sections && ((node->type() == Node::Class) || + (node->type() == Node::Namespace) || + (node->subType() == Node::QmlClass))) { + QList<Section>::ConstIterator s = sections->begin(); + while (s != sections->end()) { + if (!s->members.isEmpty() || !s->reimpMembers.isEmpty()) { + out() << "<li class=\"level" + << sectionNumber.size() + << "\"><a href=\"#" + << registerRef((*s).pluralMember) + << "\">" << (*s).name + << "</a></li>\n"; + } + ++s; + } + out() << "<li class=\"level" + << sectionNumber.size() + << "\"><a href=\"#" + << registerRef("details") + << "\">Detailed Description</a></li>\n"; + for (int i = 0; i < toc.size(); ++i) { + if (toc.at(i)->string().toInt() == 1) { + detailsBase = 1; + break; + } + } + } + for (int i = 0; i < toc.size(); ++i) { + Atom *atom = toc.at(i); + int nextLevel = atom->string().toInt() + detailsBase; + 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); + } + int numAtoms; + Text headingText = Text::sectionHeading(atom); + QString s = headingText.toString(); + out() << "<li class=\"level" + << sectionNumber.size() + << "\">"; + out() << "<a href=\"" + << "#" + << Doc::canonicalTitle(s) + << "\">"; + generateAtomList(headingText.firstAtom(), node, marker, true, numAtoms); + out() << "</a></li>\n"; + } + while (!sectionNumber.isEmpty()) { + sectionNumber.removeLast(); + } + out() << "</ul>\n"; + out() << "</div>\n"; inContents = false; inLink = false; } @@ -1909,7 +2226,7 @@ void HtmlGenerator::generateNavigationBar(const NavigationBar& bar, { if (bar.prev.begin() != 0 || bar.current.begin() != 0 || bar.next.begin() != 0) { - out() << "<p align=\"right\">"; + out() << "<p class=\"rightAlign\">"; if (bar.prev.begin() != 0) { #if 0 out() << "[<a href=\"" << section.previousBaseName() @@ -1918,17 +2235,19 @@ void HtmlGenerator::generateNavigationBar(const NavigationBar& bar, out() << "</a>]\n"; #endif } - 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"; + 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"; } - out() << "</p>\n"; } } #endif @@ -1948,7 +2267,7 @@ QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, QString fileName = fileBase(inner) + "-members." + fileExtension(inner); beginSubPage(inner->location(), fileName); QString title = "List of All Members for " + inner->name(); - generateHeader(title, inner, marker, false); + generateHeader(title, inner, marker); generateTitle(title, Text(), SmallSubTitle, inner, marker); out() << "<p>This is the complete list of members for "; generateFullName(inner, 0, marker); @@ -1962,6 +2281,38 @@ QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, return fileName; } +/*! + This function creates an html page on which are listed all + the members of QML class \a qml_cn, including the inherited + members. The \a marker is used for formatting stuff. + */ +QString HtmlGenerator::generateAllQmlMembersFile(const QmlClassNode* qml_cn, + CodeMarker* marker) +{ + QList<Section> sections; + QList<Section>::ConstIterator s; + + sections = marker->qmlSections(qml_cn,CodeMarker::SeparateList,myTree); + if (sections.isEmpty()) + return QString(); + + QString fileName = fileBase(qml_cn) + "-members." + fileExtension(qml_cn); + beginSubPage(qml_cn->location(), fileName); + QString title = "List of All Members for " + qml_cn->name(); + generateHeader(title, qml_cn, marker); + generateTitle(title, Text(), SmallSubTitle, qml_cn, marker); + out() << "<p>This is the complete list of members for "; + generateFullName(qml_cn, 0, marker); + out() << ", including inherited members.</p>\n"; + + Section section = sections.first(); + generateSectionList(section, 0, marker, CodeMarker::SeparateList); + + generateFooter(); + endSubPage(); + return fileName; +} + QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, CodeMarker *marker, CodeMarker::Status status) @@ -1992,7 +2343,7 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, } beginSubPage(inner->location(), fileName); - generateHeader(title, inner, marker, false); + generateHeader(title, inner, marker); generateTitle(title, Text(), SmallSubTitle, inner, marker); if (status == CodeMarker::Compat) { @@ -2009,18 +2360,18 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, out() << "<p><ul><li><a href=\"" << linkForNode(inner, 0) << "\">" - << protect(inner->name()) + << protectEnc(inner->name()) << " class reference</a></li></ul></p>\n"; for (i = 0; i < sections.size(); ++i) { - out() << "<h2>" << protect(sections.at(i).name) << "</h2>\n"; + out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n"; generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary); } sections = marker->sections(inner, CodeMarker::Detailed, status); for (i = 0; i < sections.size(); ++i) { - out() << "<hr />\n"; - out() << "<h2>" << protect(sections.at(i).name) << "</h2>\n"; + //out() << "<hr />\n"; + out() << "<h2>" << protectEnc(sections.at(i).name) << "</h2>\n"; NodeList::ConstIterator m = sections.at(i).members.begin(); while (m != sections.at(i).members.end()) { @@ -2085,8 +2436,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *marker, const NodeMap &nodeMap) { - out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" " - << "cellspacing=\"1\" border=\"0\">\n"; + out() << "<table class=\"annotated\">\n"; int row = 0; foreach (const QString &name, nodeMap.keys()) { @@ -2096,29 +2446,29 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative, continue; if (++row % 2 == 1) - out() << "<tr valign=\"top\" class=\"odd\">"; + out() << "<tr class=\"odd topAlign\">"; else - out() << "<tr valign=\"top\" class=\"even\">"; - out() << "<th>"; + out() << "<tr class=\"even topAlign\">"; + out() << "<td class=\"tblName\"><p>"; generateFullName(node, relative, marker); - out() << "</th>"; + out() << "</p></td>"; if (!(node->type() == Node::Fake)) { Text brief = node->doc().trimmedBriefText(name); if (!brief.isEmpty()) { - out() << "<td>"; + out() << "<td class=\"tblDescr\"><p>"; generateText(brief, node, marker); - out() << "</td>"; + out() << "</p></td>"; } } else { - out() << "<td>"; - out() << protect(node->doc().briefText().toString()); - out() << "</td>"; + out() << "<td class=\"tblDescr\"><p>"; + out() << protectEnc(node->doc().briefText().toString()); + out() << "</p></td>"; } out() << "</tr>\n"; } - out() << "</table></p>\n"; + out() << "</table>\n"; } /*! @@ -2133,10 +2483,10 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative, void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker, const NodeMap &classMap, + bool includeAlphabet, QString commonPrefix) { const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_' - const int NumColumns = 4; // number of columns in the result if (classMap.isEmpty()) return; @@ -2205,6 +2555,7 @@ void HtmlGenerator::generateCompactList(const Node *relative, */ NodeMap paragraph[NumParagraphs+1]; QString paragraphName[NumParagraphs+1]; + QSet<char> usedParagraphNames; NodeMap::ConstIterator c = classMap.begin(); while (c != classMap.end()) { @@ -2218,17 +2569,18 @@ void HtmlGenerator::generateCompactList(const Node *relative, else key = pieces.last().toLower(); - int paragraphNo = NumParagraphs - 1; + int paragraphNr = NumParagraphs - 1; if (key[0].digitValue() != -1) { - paragraphNo = key[0].digitValue(); + paragraphNr = key[0].digitValue(); } else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) { - paragraphNo = 10 + key[0].unicode() - 'a'; + paragraphNr = 10 + key[0].unicode() - 'a'; } - paragraphName[paragraphNo] = key[0].toUpper(); - paragraph[paragraphNo].insert(key, c.value()); + paragraphName[paragraphNr] = key[0].toUpper(); + usedParagraphNames.insert(key[0].toLower().cell()); + paragraph[paragraphNr].insert(key, c.value()); ++c; } @@ -2241,108 +2593,105 @@ void HtmlGenerator::generateCompactList(const Node *relative, start at offsets 0, 3, 4, 8, 9, 14, 23. */ int paragraphOffset[NumParagraphs + 1]; // 37 + 1 - int i, j, k; - paragraphOffset[0] = 0; - for (j = 0; j < NumParagraphs; j++) // j = 0..36 - paragraphOffset[j + 1] = paragraphOffset[j] + paragraph[j].count(); + for (int i=0; i<NumParagraphs; i++) // i = 0..36 + paragraphOffset[i+1] = paragraphOffset[i] + paragraph[i].count(); - int firstOffset[NumColumns + 1]; // 4 + 1 - int currentOffset[NumColumns]; // 4 - int currentParagraphNo[NumColumns]; // 4 - int currentOffsetInParagraph[NumColumns]; // 4 + int curParNr = 0; + int curParOffset = 0; - int numRows = (classMap.count() + NumColumns - 1) / NumColumns; - int curParagNo = 0; + /* + Output the alphabet as a row of links. + */ + if (includeAlphabet) { + out() << "<p class=\"centerAlign functionIndex\"><b>"; + for (int i = 0; i < 26; i++) { + QChar ch('a' + i); + if (usedParagraphNames.contains(char('a' + i))) + out() << QString("<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper()); + } + out() << "</b></p>\n"; + } + + /* + Output a <div> element to contain all the <dl> elements. + */ + out() << "<div class=\"flowListDiv\">\n"; - for (i = 0; i < NumColumns; i++) { // i = 0..3 - firstOffset[i] = qMin(i * numRows, classMap.size()); - currentOffset[i] = firstOffset[i]; + for (int i=0; i<classMap.count()-1; i++) { + while ((curParNr < NumParagraphs) && + (curParOffset == paragraph[curParNr].count())) { + ++curParNr; + curParOffset = 0; + } - for (j = curParagNo; j < NumParagraphs; j++) { - if (paragraphOffset[j] > firstOffset[i]) - break; - if (paragraphOffset[j] <= firstOffset[i]) - curParagNo = j; - } - currentParagraphNo[i] = curParagNo; - currentOffsetInParagraph[i] = firstOffset[i] - - paragraphOffset[curParagNo]; - } - firstOffset[NumColumns] = classMap.count(); - - out() << "<p><table class=\"generic\" width=\"100%\">\n"; - for (k = 0; k < numRows; k++) { - out() << "<tr>\n"; - for (i = 0; i < NumColumns; i++) { - if (currentOffset[i] >= firstOffset[i + 1]) { - // this column is finished - out() << "<td>\n</td>\n"; + /* + Starting a new paragraph means starting a new <dl>. + */ + if (curParOffset == 0) { + if (i > 0) + out() << "</dl>\n"; + if (++numTableRows % 2 == 1) + out() << "<dl class=\"flowList odd\">"; + else + out() << "<dl class=\"flowList even\">"; + out() << "<dt class=\"alphaChar\">"; + if (includeAlphabet) { + QChar c = paragraphName[curParNr][0].toLower(); + out() << QString("<a name=\"%1\"></a>").arg(c); } - else { - while ((currentParagraphNo[i] < NumParagraphs) && - (currentOffsetInParagraph[i] == paragraph[currentParagraphNo[i]].count())) { - ++currentParagraphNo[i]; - currentOffsetInParagraph[i] = 0; - } -#if 0 - if (currentParagraphNo[i] >= NumParagraphs) { - qDebug() << "### Internal error ###" << __FILE__ << __LINE__ - << currentParagraphNo[i] << NumParagraphs; - currentParagraphNo[i] = NumParagraphs - 1; - } -#endif - out() << "<td align=\"right\">"; - if (currentOffsetInParagraph[i] == 0) { - // start a new paragraph - out() << "<b>" - << paragraphName[currentParagraphNo[i]] - << " </b>"; - } - out() << "</td>\n"; - - out() << "<td>"; - if ((currentParagraphNo[i] < NumParagraphs) && - !paragraphName[currentParagraphNo[i]].isEmpty()) { - NodeMap::Iterator it; - it = paragraph[currentParagraphNo[i]].begin(); - for (j = 0; j < currentOffsetInParagraph[i]; j++) - ++it; - - // Previously, we used generateFullName() for this, but we - // require some special formatting. - out() << "<a href=\"" - << linkForNode(it.value(), relative) - << "\">"; - QStringList pieces = fullName(it.value(), relative, marker).split("::"); - out() << protect(pieces.last()); - out() << "</a>"; - if (pieces.size() > 1) { - out() << " ("; - generateFullName(it.value()->parent(), relative, marker); - out() << ")"; - } - } - out() << "</td>\n"; + out() << "<b>" + << paragraphName[curParNr] + << "</b>"; + out() << "</dt>\n"; + } - currentOffset[i]++; - currentOffsetInParagraph[i]++; + /* + Output a <dd> for the current offset in the current paragraph. + */ + out() << "<dd>"; + if ((curParNr < NumParagraphs) && + !paragraphName[curParNr].isEmpty()) { + NodeMap::Iterator it; + it = paragraph[curParNr].begin(); + for (int i=0; i<curParOffset; i++) + ++it; + + /* + Previously, we used generateFullName() for this, but we + require some special formatting. + */ + out() << "<a href=\"" << linkForNode(it.value(), relative) << "\">"; + + QStringList pieces; + if (it.value()->subType() == Node::QmlClass) + pieces << it.value()->name(); + else + pieces = fullName(it.value(), relative, marker).split("::"); + out() << protectEnc(pieces.last()); + out() << "</a>"; + if (pieces.size() > 1) { + out() << " ("; + generateFullName(it.value()->parent(), relative, marker); + out() << ")"; } } - out() << "</tr>\n"; + out() << "</dd>\n"; + curParOffset++; } - out() << "</table></p>\n"; + out() << "</dl>\n"; + out() << "</div>\n"; } void HtmlGenerator::generateFunctionIndex(const Node *relative, CodeMarker *marker) { - out() << "<p align=\"center\"><font size=\"+1\"><b>"; + out() << "<p class=\"centerAlign functionIndex\"><b>"; for (int i = 0; i < 26; i++) { QChar ch('a' + i); out() << QString("<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper()); } - out() << "</b></font></p>\n"; + out() << "</b></p>\n"; char nextLetter = 'a'; char currentLetter; @@ -2357,7 +2706,7 @@ void HtmlGenerator::generateFunctionIndex(const Node *relative, #else out() << "<p>"; #endif - out() << protect(f.key()) << ":"; + out() << protectEnc(f.key()) << ":"; currentLetter = f.key()[0].unicode(); while (islower(currentLetter) && currentLetter >= nextLetter) { @@ -2390,7 +2739,7 @@ void HtmlGenerator::generateLegaleseList(const Node *relative, QMap<Text, const Node *>::ConstIterator it = legaleseTexts.begin(); while (it != legaleseTexts.end()) { Text text = it.key(); - out() << "<hr />\n"; + //out() << "<hr />\n"; generateText(text, relative, marker); out() << "<ul>\n"; do { @@ -2403,44 +2752,6 @@ void HtmlGenerator::generateLegaleseList(const Node *relative, } } -/*void HtmlGenerator::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 = protect(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>"), - "<i>\\1<sub>\\2</sub></i>"); - marked.replace("<@param>", "<i>"); - marked.replace("</@param>", "</i>"); - - 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>", " <tt>"); - marked.replace("</@extra>", "</tt>"); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("</@type>", ""); - } - out() << highlightedCode(marked, marker, relative); -}*/ - #ifdef QDOC_QML void HtmlGenerator::generateQmlItem(const Node *node, const Node *relative, @@ -2450,7 +2761,7 @@ void HtmlGenerator::generateQmlItem(const Node *node, QString marked = marker->markedUpQmlItem(node,summary); QRegExp templateTag("(<[^@>]*>)"); if (marked.indexOf(templateTag) != -1) { - QString contents = protect(marked.mid(templateTag.pos(1), + QString contents = protectEnc(marked.mid(templateTag.pos(1), templateTag.cap(1).length())); marked.replace(templateTag.pos(1), templateTag.cap(1).length(), contents); @@ -2463,14 +2774,14 @@ void HtmlGenerator::generateQmlItem(const Node *node, if (summary) marked.replace("@name>", "b>"); - marked.replace("<@extra>", " <tt>"); + marked.replace("<@extra>", "<tt>"); marked.replace("</@extra>", "</tt>"); if (summary) { marked.replace("<@type>", ""); marked.replace("</@type>", ""); } - out() << highlightedCode(marked, marker, relative); + out() << highlightedCode(marked, marker, relative, false, node); } #endif @@ -2556,7 +2867,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m const FakeNode *groupNode = groupTitlesMap[groupTitle]; out() << QString("<h3><a href=\"%1\">%2</a></h3>\n").arg( linkForNode(groupNode, relative)).arg( - protect(groupNode->fullTitle())); + protectEnc(groupNode->fullTitle())); if (fakeNodeMap[groupNode].count() == 0) continue; @@ -2568,7 +2879,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m if (title.startsWith("The ")) title.remove(0, 4); out() << "<li><a href=\"" << linkForNode(fakeNode, relative) << "\">" - << protect(title) << "</a></li>\n"; + << protectEnc(title) << "</a></li>\n"; } out() << "</ul>\n"; } @@ -2582,39 +2893,35 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m if (title.startsWith("The ")) title.remove(0, 4); out() << "<li><a href=\"" << linkForNode(fakeNode, relative) << "\">" - << protect(title) << "</a></li>\n"; + << protectEnc(title) << "</a></li>\n"; } out() << "</ul>\n"; } } -#ifdef QDOC_NAME_ALIGNMENT void HtmlGenerator::generateSection(const NodeList& nl, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style) { - bool name_alignment = true; + bool alignNames = true; if (!nl.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { - name_alignment = false; + alignNames = false; twoColumn = (nl.count() >= 16); } else if (nl.first()->type() == Node::Property) { twoColumn = (nl.count() >= 5); - name_alignment = false; + alignNames = false; } - if (name_alignment) { - out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" " - << "cellspacing=\"0\" width=\"100%\">\n"; + if (alignNames) { + out() << "<table class=\"alignedsummary\">\n"; } else { if (twoColumn) - out() << "<p><table class=\"propsummary\" width=\"100%\" " - << "border=\"0\" cellpadding=\"0\"" - << " cellspacing=\"0\">\n" - << "<tr><td width=\"45%\" valign=\"top\">"; + out() << "<table class=\"propsummary\">\n" + << "<tr><td class=\"topAlign\">"; out() << "<ul>\n"; } @@ -2626,30 +2933,29 @@ void HtmlGenerator::generateSection(const NodeList& nl, continue; } - if (name_alignment) { - out() << "<tr><td class=\"memItemLeft\" " - << "align=\"right\" valign=\"top\">"; + if (alignNames) { + out() << "<tr><td class=\"memItemLeft rightAlign topAlign\"> "; } else { if (twoColumn && i == (int) (nl.count() + 1) / 2) - out() << "</ul></td><td valign=\"top\"><ul>\n"; - out() << "<li><div class=\"fn\">"; + out() << "</ul></td><td class=\"topAlign\"><ul>\n"; + out() << "<li class=\"fn\">"; } - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) + generateSynopsis(*m, relative, marker, style, alignNames); + if (alignNames) out() << "</td></tr>\n"; else - out() << "</div></li>\n"; + out() << "</li>\n"; i++; ++m; } - if (name_alignment) + if (alignNames) out() << "</table>\n"; else { out() << "</ul>\n"; if (twoColumn) - out() << "</td></tr>\n</table></p>\n"; + out() << "</td></tr>\n</table>\n"; } } } @@ -2659,27 +2965,24 @@ void HtmlGenerator::generateSectionList(const Section& section, CodeMarker *marker, CodeMarker::SynopsisStyle style) { - bool name_alignment = true; + bool alignNames = true; if (!section.members.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { - name_alignment = false; + alignNames = false; twoColumn = (section.members.count() >= 16); } else if (section.members.first()->type() == Node::Property) { twoColumn = (section.members.count() >= 5); - name_alignment = false; + alignNames = false; } - if (name_alignment) { - out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" " - << "cellspacing=\"0\" width=\"100%\">\n"; + if (alignNames) { + out() << "<table class=\"alignedsummary\">\n"; } else { if (twoColumn) - out() << "<p><table class=\"propsummary\" width=\"100%\" " - << "border=\"0\" cellpadding=\"0\"" - << " cellspacing=\"0\">\n" - << "<tr><td width=\"45%\" valign=\"top\">"; + out() << "<table class=\"propsummary\">\n" + << "<tr><td class=\"topAlign\">"; out() << "<ul>\n"; } @@ -2691,51 +2994,46 @@ void HtmlGenerator::generateSectionList(const Section& section, continue; } - if (name_alignment) { - out() << "<tr><td class=\"memItemLeft\" " - << "align=\"right\" valign=\"top\">"; + if (alignNames) { + out() << "<tr><td class=\"memItemLeft topAlign rightAlign\"> "; } else { if (twoColumn && i == (int) (section.members.count() + 1) / 2) - out() << "</ul></td><td valign=\"top\"><ul>\n"; - out() << "<li><div class=\"fn\">"; + out() << "</ul></td><td class=\"topAlign\"><ul>\n"; + out() << "<li class=\"fn\">"; } - generateSynopsis(*m, relative, marker, style, name_alignment); - if (name_alignment) + generateSynopsis(*m, relative, marker, style, alignNames); + if (alignNames) out() << "</td></tr>\n"; else - out() << "</div></li>\n"; + out() << "</li>\n"; i++; ++m; } - if (name_alignment) + if (alignNames) out() << "</table>\n"; else { out() << "</ul>\n"; if (twoColumn) - out() << "</td></tr>\n</table></p>\n"; + out() << "</td></tr>\n</table>\n"; } } if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { out() << "<ul>\n"; - generateSectionInheritedList(section, relative, marker, name_alignment); + generateSectionInheritedList(section, relative, marker); out() << "</ul>\n"; } } void HtmlGenerator::generateSectionInheritedList(const Section& section, const Node *relative, - CodeMarker *marker, - bool nameAlignment) + CodeMarker *marker) { QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { - if (nameAlignment) - out() << "<li><div bar=\"2\" class=\"fn\"></div>"; - else - out() << "<li><div class=\"fn\"></div>"; + out() << "<li class=\"fn\">"; out() << (*p).second << " "; if ((*p).second == 1) { out() << section.singularMember; @@ -2745,7 +3043,7 @@ void HtmlGenerator::generateSectionInheritedList(const Section& section, } out() << " inherited from <a href=\"" << fileName((*p).first) << "#" << HtmlGenerator::cleanRef(section.name.toLower()) << "\">" - << protect(marker->plainFullName((*p).first, relative)) + << protectEnc(marker->plainFullName((*p).first, relative)) << "</a></li>\n"; ++p; } @@ -2755,12 +3053,12 @@ void HtmlGenerator::generateSynopsis(const Node *node, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style, - bool nameAlignment) + bool alignNames) { QString marked = marker->markedUpSynopsis(node, relative, style); QRegExp templateTag("(<[^@>]*>)"); if (marked.indexOf(templateTag) != -1) { - QString contents = protect(marked.mid(templateTag.pos(1), + QString contents = protectEnc(marked.mid(templateTag.pos(1), templateTag.cap(1).length())); marked.replace(templateTag.pos(1), templateTag.cap(1).length(), contents); @@ -2780,7 +3078,7 @@ void HtmlGenerator::generateSynopsis(const Node *node, extraRegExp.setMinimal(true); marked.replace(extraRegExp, ""); } else { - marked.replace("<@extra>", " <tt>"); + marked.replace("<@extra>", "<tt>"); marked.replace("</@extra>", "</tt>"); } @@ -2788,14 +3086,14 @@ void HtmlGenerator::generateSynopsis(const Node *node, marked.replace("<@type>", ""); marked.replace("</@type>", ""); } - out() << highlightedCode(marked, marker, relative, style, nameAlignment); + out() << highlightedCode(marked, marker, relative, alignNames); } QString HtmlGenerator::highlightedCode(const QString& markedCode, - CodeMarker *marker, - const Node *relative, - CodeMarker::SynopsisStyle , - bool nameAlignment) + CodeMarker* marker, + const Node* relative, + bool alignNames, + const Node* self) { QString src = markedCode; QString html; @@ -2805,20 +3103,24 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, const QChar charLangle = '<'; const QChar charAt = '@'; - // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" + static const QString typeTag("type"); + static const QString headerTag("headerfile"); + static const QString funcTag("func"); static const QString linkTag("link"); + + // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)" bool done = false; - for (int i = 0, n = src.size(); i < n;) { + for (int i = 0, srcSize = src.size(); i < srcSize;) { if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { - if (nameAlignment && !done) {// && (i != 0)) Why was this here? - html += "</td><td class=\"memItemRight\" valign=\"bottom\">"; + if (alignNames && !done) {// && (i != 0)) Why was this here? + html += "</td><td class=\"memItemRight bottomAlign\">"; done = true; } i += 2; - if (parseArg(src, linkTag, &i, n, &arg, &par1)) { + if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) { html += "<b>"; - QString link = linkForNode( - CodeMarker::nodeForString(par1.toString()), relative); + const Node* n = CodeMarker::nodeForString(par1.toString()); + QString link = linkForNode(n, relative); addLink(link, arg, &html); html += "</b>"; } @@ -2838,16 +3140,14 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // 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;) { + 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, n, &arg, &par1)) { - QString link = linkForNode( - marker->resolveTarget(par1.toString(), - myTree, - relative), - relative); + 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(); } @@ -2865,292 +3165,37 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // 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>" -> "<span class=\"comment\">"; - // "<@preprocessor>" -> "<span class=\"preprocessor\">"; - // "<@string>" -> "<span class=\"string\">"; - // "<@char>" -> "<span class=\"char\">"; - // "</@(?:comment|preprocessor|string|char)>" -> "</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>" - // "<@char>", "<font color=blue>", - // "</@char>", "</font>", - // "<@func>", "<font color=green>", - // "</@func>", "</font>", - // "<@id>", "<i>", - // "</@id>", "</i>", - // "<@keyword>", "<b>", - // "</@keyword>", "</b>", - // "<@number>", "<font color=yellow>", - // "</@number>", "</font>", - // "<@op>", "<b>", - // "</@op>", "</b>", - // "<@param>", "<i>", - // "</@param>", "</i>", - // "<@string>", "<font color=green>", - // "</@string>", "</font>", - }; - for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle) { + for (int i=0, srcSize=src.size(); i<srcSize;) { + if (src.at(i) == charLangle && src.at(i+1) == charAt) { + i += 2; bool handled = false; - for (int k = 0; k != 8; ++k) { - const QString & tag = spanTags[2 * k]; - if (tag == QStringRef(&src, i, tag.length())) { - html += spanTags[2 * k + 1]; - i += tag.length(); - handled = true; - break; + if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative, self); + if (n && n->subType() == Node::QmlBasicType) { + if (relative && relative->subType() == Node::QmlClass) + addLink(linkForNode(n,relative), arg, &html); + else + html += arg.toString(); } + else + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - if (!handled) { - ++i; - if (src.at(i) == charAt || - (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) { - // drop 'our' unknown tags (the ones still containing '@') - while (i < n && src.at(i) != QLatin1Char('>')) - ++i; - ++i; - } - else { - // retain all others - html += charLangle; - } - } - } - else { - html += src.at(i); - ++i; - } - } - - return html; -} - -#else -void HtmlGenerator::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() << "<p><table class=\"generic\" width=\"100%\" border=\"0\" " - << "cellpadding=\"0\" cellspacing=\"0\">\n" - << "<tr><td width=\"45%\" valign=\"top\">"; - out() << "<ul>\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() << "</ul></td><td valign=\"top\"><ul>\n"; - - out() << "<li><div class=\"fn\"></div>"; - if (style == CodeMarker::Accessors) - out() << "<b>"; - generateSynopsis(*m, relative, marker, style); - if (style == CodeMarker::Accessors) - out() << "</b>"; - out() << "</li>\n"; - i++; - ++m; - } - out() << "</ul>\n"; - if (twoColumn) - out() << "</td></tr>\n</table></p>\n"; - } - - if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { - out() << "<ul>\n"; - generateSectionInheritedList(section, relative, marker); - out() << "</ul>\n"; - } -} - -void HtmlGenerator::generateSectionInheritedList(const Section& section, - const Node *relative, - CodeMarker *marker) -{ - QList<QPair<ClassNode *, int> >::ConstIterator p = section.inherited.begin(); - while (p != section.inherited.end()) { - out() << "<li><div bar=\"2\" class=\"fn\"></div>"; - out() << (*p).second << " "; - if ((*p).second == 1) { - out() << section.singularMember; - } else { - out() << section.pluralMember; - } - out() << " inherited from <a href=\"" << fileName((*p).first) - << "#" << HtmlGenerator::cleanRef(section.name.toLower()) << "\">" - << protect(marker->plainFullName((*p).first, relative)) - << "</a></li>\n"; - ++p; - } -} - -void HtmlGenerator::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 = protect(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>"), "<i>\\1<sub>\\2</sub></i>"); - marked.replace("<@param>", "<i>"); - marked.replace("</@param>", "</i>"); - - 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>", " <tt>"); - marked.replace("</@extra>", "</tt>"); - } - - if (style != CodeMarker::Detailed) { - marked.replace("<@type>", ""); - marked.replace("</@type>", ""); - } - out() << highlightedCode(marked, marker, relative); -} - -QString HtmlGenerator::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 if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - else { - html += src.at(i++); + else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) { + par1 = QStringRef(); + const Node* n = marker->resolveTarget(arg.toString(), myTree, relative); + addLink(linkForNode(n,relative), arg, &html); + handled = true; } - } - } - // 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; @@ -3178,22 +3223,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, "</@preprocessor>","</span>", "</@string>", "</span>", "</@char>", "</span>" - // "<@char>", "<font color=blue>", - // "</@char>", "</font>", - // "<@func>", "<font color=green>", - // "</@func>", "</font>", - // "<@id>", "<i>", - // "</@id>", "</i>", - // "<@keyword>", "<b>", - // "</@keyword>", "</b>", - // "<@number>", "<font color=yellow>", - // "</@number>", "</font>", - // "<@op>", "<b>", - // "</@op>", "</b>", - // "<@param>", "<i>", - // "</@param>", "</i>", - // "<@string>", "<font color=green>", - // "</@string>", "</font>", }; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle) { @@ -3230,7 +3259,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, return html; } -#endif void HtmlGenerator::generateLink(const Atom* atom, const Node* /* relative */, @@ -3241,7 +3269,7 @@ void HtmlGenerator::generateLink(const Atom* atom, if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) { // hack for C++: move () outside of link int k = funcLeftParen.pos(1); - out() << protect(atom->string().left(k)); + out() << protectEnc(atom->string().left(k)); if (link.isEmpty()) { if (showBrokenLinks) out() << "</i>"; @@ -3249,21 +3277,21 @@ void HtmlGenerator::generateLink(const Atom* atom, out() << "</a>"; } inLink = false; - out() << protect(atom->string().mid(k)); + out() << protectEnc(atom->string().mid(k)); } else if (marker->recognizeLanguage("Java")) { - // hack for Java: remove () and use <tt> when appropriate + // 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() << protect(atom->string().left(atom->string().length() - 2)); + out() << protectEnc(atom->string().left(atom->string().length() - 2)); } else { - out() << protect(atom->string()); + out() << protectEnc(atom->string()); } out() << "</tt>"; } else { - out() << protect(atom->string()); + out() << protectEnc(atom->string()); } } @@ -3337,7 +3365,12 @@ QString HtmlGenerator::registerRef(const QString& ref) return clean; } -QString HtmlGenerator::protect(const QString& string) +QString HtmlGenerator::protectEnc(const QString &string) +{ + return protect(string, outputEncoding); +} + +QString HtmlGenerator::protect(const QString &string, const QString &outputEncoding) { #define APPEND(x) \ if (html.isEmpty()) { \ @@ -3360,7 +3393,7 @@ QString HtmlGenerator::protect(const QString& string) APPEND(">"); } else if (ch == QLatin1Char('"')) { APPEND("""); - } else if (ch.unicode() > 0x007F + } else if ((outputEncoding == "ISO-8859-1" && ch.unicode() > 0x007F) || (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/')) || (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) { // we escape '*/' and the last dot in 'e.g.' and 'i.e.' for the Javadoc generator @@ -3380,7 +3413,7 @@ QString HtmlGenerator::protect(const QString& string) #undef APPEND } -QString HtmlGenerator::fileBase(const Node *node) +QString HtmlGenerator::fileBase(const Node *node) const { QString result; @@ -3490,7 +3523,7 @@ QString HtmlGenerator::refForNode(const Node *node) ref = node->name() + "-var"; break; case Node::Target: - return protect(node->name()); + return protectEnc(node->name()); } return registerRef(ref); } @@ -3509,10 +3542,13 @@ QString HtmlGenerator::linkForNode(const Node *node, const Node *relative) return QString(); if (node->access() == Node::Private) return QString(); - + fn = fileName(node); -/* if (!node->url().isEmpty()) - return fn;*/ +#if 0 + if (!node->url().isEmpty()) + return fn; +#endif + #if 0 // ### reintroduce this test, without breaking .dcf files if (fn != outFileName()) @@ -3564,7 +3600,7 @@ void HtmlGenerator::generateFullName(const Node *apparentNode, } } out() << "\">"; - out() << protect(fullName(apparentNode, relative, marker)); + out() << protectEnc(fullName(apparentNode, relative, marker)); out() << "</a>"; } @@ -3574,14 +3610,19 @@ void HtmlGenerator::generateDetailedMember(const Node *node, { const EnumNode *enume; +#ifdef GENERATE_MAC_REFS generateMacRef(node, marker); +#endif + generateExtractionMark(node, MemberMark); if (node->type() == Node::Enum && (enume = static_cast<const EnumNode *>(node))->flagsType()) { +#ifdef GENERATE_MAC_REFS generateMacRef(enume->flagsType(), marker); +#endif out() << "<h3 class=\"flags\">"; out() << "<a name=\"" + refForNode(node) + "\"></a>"; generateSynopsis(enume, relative, marker, CodeMarker::Detailed); - out() << "<br />"; + out() << "<br/>"; generateSynopsis(enume->flagsType(), relative, marker, @@ -3592,7 +3633,7 @@ void HtmlGenerator::generateDetailedMember(const Node *node, out() << "<h3 class=\"fn\">"; out() << "<a name=\"" + refForNode(node) + "\"></a>"; generateSynopsis(node, relative, marker, CodeMarker::Detailed); - out() << "</h3>\n"; + out() << "</h3>" << divNavTop << "\n"; } generateStatus(node, marker); @@ -3625,16 +3666,17 @@ void HtmlGenerator::generateDetailedMember(const Node *node, else if (node->type() == Node::Enum) { const EnumNode *enume = static_cast<const EnumNode *>(node); if (enume->flagsType()) { - out() << "<p>The " << protect(enume->flagsType()->name()) + out() << "<p>The " << protectEnc(enume->flagsType()->name()) << " type is a typedef for " << "<a href=\"qflags.html\">QFlags</a><" - << protect(enume->name()) + << protectEnc(enume->name()) << ">. It stores an OR combination of " - << protect(enume->name()) + << protectEnc(enume->name()) << " values.</p>\n"; } } generateAlsoList(node, marker); + generateExtractionMark(node, EndMark); } void HtmlGenerator::findAllClasses(const InnerNode *node) @@ -3676,6 +3718,16 @@ void HtmlGenerator::findAllClasses(const InnerNode *node) if (!serviceName.isEmpty()) serviceClasses.insert(serviceName, *c); } + else if ((*c)->type() == Node::Fake && + (*c)->subType() == Node::QmlClass && + !(*c)->doc().isEmpty()) { + QString qmlClassName = (*c)->name(); + // Remove the "QML:" prefix if present. + if (qmlClassName.startsWith(QLatin1String("QML:"))) + qmlClasses.insert(qmlClassName.mid(4),*c); + else + qmlClasses.insert(qmlClassName,*c); + } else if ((*c)->isInnerNode()) { findAllClasses(static_cast<InnerNode *>(*c)); } @@ -3700,6 +3752,9 @@ void HtmlGenerator::findAllSince(const InnerNode *node) NewClassMaps::iterator ncmap = newClassMaps.find(sinceVersion); if (ncmap == newClassMaps.end()) ncmap = newClassMaps.insert(sinceVersion,NodeMap()); + NewClassMaps::iterator nqcmap = newQmlClassMaps.find(sinceVersion); + if (nqcmap == newQmlClassMaps.end()) + nqcmap = newQmlClassMaps.insert(sinceVersion,NodeMap()); if ((*child)->type() == Node::Function) { FunctionNode *func = static_cast<FunctionNode *>(*child); @@ -3719,6 +3774,15 @@ void HtmlGenerator::findAllSince(const InnerNode *node) nsmap.value().insert(className,(*child)); ncmap.value().insert(className,(*child)); } + else if ((*child)->subType() == Node::QmlClass) { + QString className = (*child)->name(); + if ((*child)->parent() && + (*child)->parent()->type() == Node::Namespace && + !(*child)->parent()->name().isEmpty()) + className = (*child)->parent()->name()+"::"+className; + nsmap.value().insert(className,(*child)); + nqcmap.value().insert(className,(*child)); + } } else { QString name = (*child)->name(); @@ -3736,13 +3800,6 @@ void HtmlGenerator::findAllSince(const InnerNode *node) } } -#if 0 - const QRegExp versionSeparator("[\\-\\.]"); - const int minorIndex = version.indexOf(versionSeparator); - const int patchIndex = version.indexOf(versionSeparator, minorIndex+1); - version = version.left(patchIndex); -#endif - void HtmlGenerator::findAllFunctions(const InnerNode *node) { NodeList::ConstIterator c = node->childNodes().begin(); @@ -3806,29 +3863,6 @@ void HtmlGenerator::findAllNamespaces(const InnerNode *node) } } -#ifdef ZZZ_QDOC_QML -/*! - This function finds all the qml element nodes and - stores them in a map for later use. - */ -void HtmlGenerator::findAllQmlClasses(const InnerNode *node) -{ - NodeList::const_iterator c = node->childNodes().constBegin(); - while (c != node->childNodes().constEnd()) { - if ((*c)->type() == Node::Fake) { - const FakeNode* fakeNode = static_cast<const FakeNode *>(*c); - if (fakeNode->subType() == Node::QmlClass) { - const QmlClassNode* qmlNode = - static_cast<const QmlClassNode*>(fakeNode); - const Node* n = qmlNode->classNode(); - } - qmlClasses.insert(fakeNode->name(),*c); - } - ++c; - } -} -#endif - int HtmlGenerator::hOffset(const Node *node) { switch (node->type()) { @@ -3836,10 +3870,7 @@ int HtmlGenerator::hOffset(const Node *node) case Node::Class: return 2; case Node::Fake: - if (node->doc().briefText().isEmpty()) - return 1; - else - return 2; + return 1; case Node::Enum: case Node::Typedef: case Node::Function: @@ -3939,10 +3970,12 @@ QString HtmlGenerator::getLink(const Atom *atom, } else { *node = marker->resolveTarget(first, myTree, relative); - if (!*node) + if (!*node) { *node = myTree->findFakeNodeByTitle(first); - if (!*node) + } + if (!*node) { *node = myTree->findUnambiguousTarget(first, targetAtom); + } } if (*node) { @@ -4035,7 +4068,7 @@ void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker) switch (node->status()) { case Node::Obsolete: if (node->isInnerNode()) - Generator::generateStatus(node, marker); + Generator::generateStatus(node, marker); break; case Node::Compat: if (node->isInnerNode()) { @@ -4077,6 +4110,10 @@ void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker) } } +#ifdef GENERATE_MAC_REFS +/* + No longer valid. + */ void HtmlGenerator::generateMacRef(const Node *node, CodeMarker *marker) { if (!pleaseGenerateMacRef || marker == 0) @@ -4086,6 +4123,7 @@ void HtmlGenerator::generateMacRef(const Node *node, CodeMarker *marker) foreach (const QString &macRef, macRefs) out() << "<a name=\"" << "//apple_ref/" << macRef << "\"></a>\n"; } +#endif void HtmlGenerator::beginLink(const QString &link, const Node *node, @@ -4137,12 +4175,10 @@ void HtmlGenerator::endLink() inObsoleteLink = false; } -QT_END_NAMESPACE - #ifdef QDOC_QML /*! - Generates the summary for for the \a section. Only used for + Generates the summary for the \a section. Only used for sections of QML element documentation. Currently handles only the QML property group. @@ -4152,32 +4188,16 @@ void HtmlGenerator::generateQmlSummary(const Section& section, CodeMarker *marker) { if (!section.members.isEmpty()) { - NodeList::ConstIterator m; - int count = section.members.size(); - bool twoColumn = false; - if (section.members.first()->type() == Node::QmlProperty) { - twoColumn = (count >= 5); - } - if (twoColumn) - out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\"" - " cellspacing=\"0\">\n" - << "<tr><td width=\"45%\" valign=\"top\">"; out() << "<ul>\n"; - - int row = 0; + NodeList::ConstIterator m; m = section.members.begin(); while (m != section.members.end()) { - if (twoColumn && row == (int) (count + 1) / 2) - out() << "</ul></td><td valign=\"top\"><ul>\n"; - out() << "<li><div class=\"fn\"></div>"; + out() << "<li class=\"fn\">"; generateQmlItem(*m,relative,marker,true); out() << "</li>\n"; - row++; ++m; } out() << "</ul>\n"; - if (twoColumn) - out() << "</td></tr>\n</table></p>\n"; } } @@ -4190,32 +4210,36 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, CodeMarker *marker) { const QmlPropertyNode* qpn = 0; +#ifdef GENERATE_MAC_REFS generateMacRef(node, marker); +#endif + generateExtractionMark(node, MemberMark); out() << "<div class=\"qmlitem\">"; if (node->subType() == Node::QmlPropertyGroup) { const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(node); NodeList::ConstIterator p = qpgn->childNodes().begin(); out() << "<div class=\"qmlproto\">"; - out() << "<table width=\"100%\" class=\"qmlname\">"; + out() << "<table class=\"qmlname\">"; while (p != qpgn->childNodes().end()) { if ((*p)->type() == Node::QmlProperty) { qpn = static_cast<const QmlPropertyNode*>(*p); - out() << "<tr><td>"; + if (++numTableRows % 2 == 1) + out() << "<tr class=\"odd\">"; + else + out() << "<tr class=\"even\">"; + + out() << "<td class=\"tblQmlPropNode\"><p>"; + out() << "<a name=\"" + refForNode(qpn) + "\"></a>"; - if (!qpn->isWritable()) + + if (!qpn->isWritable(myTree)) { out() << "<span class=\"qmlreadonly\">read-only</span>"; - generateQmlItem(qpn, relative, marker, false); - out() << "</td></tr>"; - if (qpgn->isDefault()) { - out() << "</table>" - << "</div></div>" - << "<div class=\"qmlitem\">" - << "<div class=\"qmlproto\">" - << "<table class=\"qmlname\">" - << "<tr><td><font color=\"green\">" - << "default</font></td></tr>"; } + if (qpgn->isDefault()) + out() << "<span class=\"qmldefault\">default</span>"; + generateQmlItem(qpn, relative, marker, false); + out() << "</p></td></tr>"; } ++p; } @@ -4226,11 +4250,16 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, const FunctionNode* qsn = static_cast<const FunctionNode*>(node); out() << "<div class=\"qmlproto\">"; out() << "<table class=\"qmlname\">"; - out() << "<tr><td>"; + //out() << "<tr>"; + if (++numTableRows % 2 == 1) + out() << "<tr class=\"odd\">"; + else + out() << "<tr class=\"even\">"; + out() << "<td class=\"tblQmlFuncNode\"><p>"; out() << "<a name=\"" + refForNode(qsn) + "\"></a>"; generateSynopsis(qsn,relative,marker,CodeMarker::Detailed,false); //generateQmlItem(qsn,relative,marker,false); - out() << "</td></tr>"; + out() << "</p></td></tr>"; out() << "</table>"; out() << "</div>"; } @@ -4238,10 +4267,15 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, const FunctionNode* qmn = static_cast<const FunctionNode*>(node); out() << "<div class=\"qmlproto\">"; out() << "<table class=\"qmlname\">"; - out() << "<tr><td>"; + //out() << "<tr>"; + if (++numTableRows % 2 == 1) + out() << "<tr class=\"odd\">"; + else + out() << "<tr class=\"even\">"; + out() << "<td class=\"tblQmlFuncNode\"><p>"; out() << "<a name=\"" + refForNode(qmn) + "\"></a>"; generateSynopsis(qmn,relative,marker,CodeMarker::Detailed,false); - out() << "</td></tr>"; + out() << "</p></td></tr>"; out() << "</table>"; out() << "</div>"; } @@ -4253,6 +4287,7 @@ void HtmlGenerator::generateDetailedQmlMember(const Node *node, generateAlsoList(node, marker); out() << "</div>"; out() << "</div>"; + generateExtractionMark(node, EndMark); } /*! @@ -4270,22 +4305,40 @@ void HtmlGenerator::generateQmlInherits(const QmlClassNode* cn, const Node* n = myTree->findNode(strList,Node::Fake); if (n && n->subType() == Node::QmlClass) { const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n); - out() << "<p style=\"text-align: center\">"; Text text; - text << "[Inherits "; + text << Atom::ParaLeft << "Inherits "; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); text << Atom(Atom::String, linkPair.second); text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); - text << "]"; + text << Atom::ParaRight; generateText(text, cn, marker); - out() << "</p>"; } } } } /*! + Output the "Inherit by" list for the QML element, + if it is inherited by any other elements. + */ +void HtmlGenerator::generateQmlInheritedBy(const QmlClassNode* cn, + CodeMarker* marker) +{ + if (cn) { + NodeList subs; + QmlClassNode::subclasses(cn->name(),subs); + if (!subs.isEmpty()) { + Text text; + text << Atom::ParaLeft << "Inherited by "; + appendSortedQmlNames(text,cn,subs,marker); + text << Atom::ParaRight; + generateText(text, cn, marker); + } + } +} + +/*! Output the "[Xxx instantiates the C++ class QmlGraphicsXxx]" line for the QML element, if there should be one. @@ -4297,21 +4350,22 @@ void HtmlGenerator::generateQmlInstantiates(const QmlClassNode* qcn, { const ClassNode* cn = qcn->classNode(); if (cn && (cn->status() != Node::Internal)) { - out() << "<p style=\"text-align: center\">"; Text text; - text << "["; + text << Atom::ParaLeft; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(qcn)); text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); - text << Atom(Atom::String, qcn->name()); + QString name = qcn->name(); + if (name.startsWith(QLatin1String("QML:"))) + name = name.mid(4); // remove the "QML:" prefix + text << Atom(Atom::String, name); text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); text << " instantiates the C++ class "; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn)); text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); text << Atom(Atom::String, cn->name()); text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); - text << "]"; + text << Atom::ParaRight; generateText(text, qcn, marker); - out() << "</p>"; } } @@ -4328,9 +4382,8 @@ void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn, if (cn && cn->status() != Node::Internal && !cn->qmlElement().isEmpty()) { const Node* n = myTree->root()->findNode(cn->qmlElement(),Node::Fake); if (n && n->subType() == Node::QmlClass) { - out() << "<p style=\"text-align: center\">"; Text text; - text << "["; + text << Atom::ParaLeft; text << Atom(Atom::LinkNode,CodeMarker::stringForNode(cn)); text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); text << Atom(Atom::String, cn->name()); @@ -4340,11 +4393,249 @@ void HtmlGenerator::generateInstantiatedBy(const ClassNode* cn, text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK); text << Atom(Atom::String, n->name()); text << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); - text << "]"; + text << Atom::ParaRight; generateText(text, cn, marker); - out() << "</p>"; } } } +/*! + Generate the <page> element for the given \a node using the \a writer. + Return true if a <page> element was written; otherwise return false. + */ +bool HtmlGenerator::generatePageElement(QXmlStreamWriter& writer, + const Node* node, + CodeMarker* marker) const +{ + if (node->pageType() == Node::NoPageType) + return false; + if (node->name().isEmpty()) + return true; + if (node->access() == Node::Private) + return false; + + QString guid = QUuid::createUuid().toString(); + QString url = PageGenerator::fileName(node); + QString title; + QString rawTitle; + QString fullTitle; + QStringList pageWords; + QXmlStreamAttributes attributes; + + writer.writeStartElement("page"); + + if (node->isInnerNode()) { + const InnerNode* inner = static_cast<const InnerNode*>(node); + if (!inner->pageKeywords().isEmpty()) + pageWords << inner->pageKeywords(); + + switch (node->type()) { + case Node::Fake: + { + const FakeNode* fake = static_cast<const FakeNode*>(node); + title = fake->fullTitle(); + pageWords << title; + break; + } + case Node::Class: + { + title = node->name() + " Class Reference"; + pageWords << node->name() << "class" << "reference"; + break; + } + case Node::Namespace: + { + rawTitle = marker->plainName(inner); + fullTitle = marker->plainFullName(inner); + title = rawTitle + " Namespace Reference"; + pageWords << rawTitle << "namespace" << "reference"; + break; + } + default: + title = node->name(); + pageWords << title; + break; + } + } + else { + switch (node->type()) { + case Node::Enum: + { + title = node->name() + " Enum Reference"; + pageWords << node->name() << "enum" << "type"; + url += "#" + node->name() + "-enum"; + break; + } + case Node::Function: + { + title = node->name() + " Function Reference"; + pageWords << node->name() << "function"; + url += "#" + node->name(); + break; + } + case Node::Property: + { + title = node->name() + " Property Reference"; + pageWords << node->name() << "property"; + url += "#" + node->name() + "-prop"; + break; + } + case Node::Typedef: + { + title = node->name() + " Type Reference"; + pageWords << node->name() << "typedef" << "type"; + url += "#" + node->name(); + break; + } + default: + title = node->name(); + pageWords << title; + break; + } + + Node* parent = node->parent(); + if (parent && ((parent->type() == Node::Class) || + (parent->type() == Node::Namespace))) { + pageWords << parent->name(); + } + } + + writer.writeAttribute("id",guid); + writer.writeStartElement("pageWords"); + writer.writeCharacters(pageWords.join(" ")); + + writer.writeEndElement(); + writer.writeStartElement("pageTitle"); + writer.writeCharacters(title); + writer.writeEndElement(); + writer.writeStartElement("pageUrl"); + writer.writeCharacters(url); + writer.writeEndElement(); + writer.writeStartElement("pageType"); + switch (node->pageType()) { + case Node::ApiPage: + writer.writeCharacters("APIPage"); + break; + case Node::ArticlePage: + writer.writeCharacters("Article"); + break; + case Node::ExamplePage: + writer.writeCharacters("Example"); + break; + default: + break; + } + writer.writeEndElement(); + writer.writeEndElement(); + + if (node->type() == Node::Fake && node->doc().hasTableOfContents()) { + QList<Atom*> toc = node->doc().tableOfContents(); + if (!toc.isEmpty()) { + for (int i = 0; i < toc.size(); ++i) { + Text headingText = Text::sectionHeading(toc.at(i)); + QString s = headingText.toString(); + writer.writeStartElement("page"); + guid = QUuid::createUuid().toString(); + QString internalUrl = url + "#" + Doc::canonicalTitle(s); + writer.writeAttribute("id",guid); + writer.writeStartElement("pageWords"); + writer.writeCharacters(pageWords.join(" ")); + writer.writeCharacters(" "); + writer.writeCharacters(s); + writer.writeEndElement(); + writer.writeStartElement("pageTitle"); + writer.writeCharacters(s); + writer.writeEndElement(); + writer.writeStartElement("pageUrl"); + writer.writeCharacters(internalUrl); + writer.writeEndElement(); + writer.writeStartElement("pageType"); + writer.writeCharacters("Article"); + writer.writeEndElement(); + writer.writeEndElement(); + } + } + } + return true; +} + +/*! + Traverse the tree recursively and generate the <keyword> + elements. + */ +void HtmlGenerator::generatePageElements(QXmlStreamWriter& writer, const Node* node, CodeMarker* marker) const +{ + if (generatePageElement(writer, node, marker)) { + + if (node->isInnerNode()) { + const InnerNode *inner = static_cast<const InnerNode *>(node); + + // Recurse to write an element for this child node and all its children. + foreach (const Node *child, inner->childNodes()) + generatePageElements(writer, child, marker); + } + } +} + +/*! + Outputs the file containing the index used for searching the html docs. + */ +void HtmlGenerator::generatePageIndex(const QString& fileName, CodeMarker* marker) const +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) + return ; + + QXmlStreamWriter writer(&file); + writer.setAutoFormatting(true); + writer.writeStartDocument(); + writer.writeStartElement("qtPageIndex"); + + generatePageElements(writer, myTree->root(), marker); + + writer.writeEndElement(); // qtPageIndex + writer.writeEndDocument(); + file.close(); +} + +void HtmlGenerator::generateExtractionMark(const Node *node, ExtractionMarkType markType) +{ + if (markType != EndMark) { + out() << "<!-- $$$" + node->name(); + if (markType == MemberMark) { + if (node->type() == Node::Function) { + const FunctionNode *func = static_cast<const FunctionNode *>(node); + if (!func->associatedProperty()) { + if (func->overloadNumber() == 1) + out() << "[overload1]"; + out() << "$$$" + func->name() + func->rawParameters().remove(' '); + } + } else if (node->type() == Node::Property) { + out() << "-prop"; + const PropertyNode *prop = static_cast<const PropertyNode *>(node); + const NodeList &list = prop->functions(); + foreach (const Node *propFuncNode, list) { + if (propFuncNode->type() == Node::Function) { + const FunctionNode *func = static_cast<const FunctionNode *>(propFuncNode); + out() << "$$$" + func->name() + func->rawParameters().remove(' '); + } + } + } else if (node->type() == Node::Enum) { + const EnumNode *enumNode = static_cast<const EnumNode *>(node); + foreach (const EnumItem &item, enumNode->items()) + out() << "$$$" + item.name(); + } + } else if (markType == BriefMark) { + out() << "-brief"; + } else if (markType == DetailedDescriptionMark) { + out() << "-description"; + } + out() << " -->\n"; + } else { + out() << "<!-- @@@" + node->name() + " -->\n"; + } +} + #endif + + QT_END_NAMESPACE |