tools/qdoc3/htmlgenerator.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
   217       inContents(false),
   217       inContents(false),
   218       inSectionHeading(false),
   218       inSectionHeading(false),
   219       inTableHeader(false),
   219       inTableHeader(false),
   220       numTableRows(0),
   220       numTableRows(0),
   221       threeColumnEnumValueTable(true),
   221       threeColumnEnumValueTable(true),
   222       offlineDocs(true),
   222       application(Online),
   223       creatorDocs(true),
       
   224       funcLeftParen("\\S(\\()"),
   223       funcLeftParen("\\S(\\()"),
   225       myTree(0),
   224       myTree(0),
   226       slow(false),
   225       slow(false),
   227       obsoleteLinks(false)
   226       obsoleteLinks(false)
   228 {
   227 {
   269                                   Config::dot +
   268                                   Config::dot +
   270                                   HTMLGENERATOR_POSTHEADER);
   269                                   HTMLGENERATOR_POSTHEADER);
   271     postPostHeader = config.getString(HtmlGenerator::format() +
   270     postPostHeader = config.getString(HtmlGenerator::format() +
   272                                       Config::dot +
   271                                       Config::dot +
   273                                       HTMLGENERATOR_POSTPOSTHEADER);
   272                                       HTMLGENERATOR_POSTPOSTHEADER);
       
   273     creatorPostHeader = config.getString(HtmlGenerator::format() +
       
   274                                   Config::dot +
       
   275                                   HTMLGENERATOR_CREATORPOSTHEADER);
       
   276     creatorPostPostHeader = config.getString(HtmlGenerator::format() +
       
   277                                       Config::dot +
       
   278                                       HTMLGENERATOR_CREATORPOSTPOSTHEADER);
   274     footer = config.getString(HtmlGenerator::format() +
   279     footer = config.getString(HtmlGenerator::format() +
   275                               Config::dot +
   280                               Config::dot +
   276                               HTMLGENERATOR_FOOTER);
   281                               HTMLGENERATOR_FOOTER);
   277     address = config.getString(HtmlGenerator::format() +
   282     address = config.getString(HtmlGenerator::format() +
   278                                Config::dot +
   283                                Config::dot +
   280     pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() +
   285     pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() +
   281                                           Config::dot +
   286                                           Config::dot +
   282                                           HTMLGENERATOR_GENERATEMACREFS);
   287                                           HTMLGENERATOR_GENERATEMACREFS);
   283 
   288 
   284     project = config.getString(CONFIG_PROJECT);
   289     project = config.getString(CONFIG_PROJECT);
   285     offlineDocs = !config.getBool(CONFIG_ONLINE);
   290 
   286     creatorDocs = false; //!config.getBool(CONFIG_CREATOR);
   291     QString app = config.getString(CONFIG_APPLICATION);
       
   292     if (app == "online")
       
   293         application = Online;
       
   294     else if (app == "creator")
       
   295         application = Creator;
       
   296     else 
       
   297         application = Creator;
       
   298 
   287     projectDescription = config.getString(CONFIG_DESCRIPTION);
   299     projectDescription = config.getString(CONFIG_DESCRIPTION);
   288     if (projectDescription.isEmpty() && !project.isEmpty())
   300     if (projectDescription.isEmpty() && !project.isEmpty())
   289         projectDescription = project + " Reference Documentation";
   301         projectDescription = project + " Reference Documentation";
   290 
   302 
   291     projectUrl = config.getString(CONFIG_URL);
   303     projectUrl = config.getString(CONFIG_URL);
   362     moduleClassMap.clear();
   374     moduleClassMap.clear();
   363     moduleNamespaceMap.clear();
   375     moduleNamespaceMap.clear();
   364     funcIndex.clear();
   376     funcIndex.clear();
   365     legaleseTexts.clear();
   377     legaleseTexts.clear();
   366     serviceClasses.clear();
   378     serviceClasses.clear();
       
   379     qmlClasses.clear();
   367     findAllClasses(tree->root());
   380     findAllClasses(tree->root());
   368     findAllFunctions(tree->root());
   381     findAllFunctions(tree->root());
   369     findAllLegaleseTexts(tree->root());
   382     findAllLegaleseTexts(tree->root());
   370     findAllNamespaces(tree->root());
   383     findAllNamespaces(tree->root());
   371     findAllSince(tree->root());
   384     findAllSince(tree->root());
   596         if (atom->string() == "annotatedclasses") {
   609         if (atom->string() == "annotatedclasses") {
   597             generateAnnotatedList(relative, marker, nonCompatClasses);
   610             generateAnnotatedList(relative, marker, nonCompatClasses);
   598         }
   611         }
   599         else if (atom->string() == "classes") {
   612         else if (atom->string() == "classes") {
   600             generateCompactList(relative, marker, nonCompatClasses, true);
   613             generateCompactList(relative, marker, nonCompatClasses, true);
       
   614         }
       
   615         else if (atom->string() == "qmlclasses") {
       
   616             generateCompactList(relative, marker, qmlClasses, true);
   601         }
   617         }
   602         else if (atom->string().contains("classesbymodule")) {
   618         else if (atom->string().contains("classesbymodule")) {
   603             QString arg = atom->string().trimmed();
   619             QString arg = atom->string().trimmed();
   604             QString moduleName = atom->string().mid(atom->string().indexOf(
   620             QString moduleName = atom->string().mid(atom->string().indexOf(
   605                 "classesbymodule") + 15).trimmed();
   621                 "classesbymodule") + 15).trimmed();
  1475       Don't generate a TOC for the home page.
  1491       Don't generate a TOC for the home page.
  1476     */
  1492     */
  1477     const QmlClassNode* qml_cn = 0;
  1493     const QmlClassNode* qml_cn = 0;
  1478     if (fake->subType() == Node::QmlClass) {
  1494     if (fake->subType() == Node::QmlClass) {
  1479         qml_cn = static_cast<const QmlClassNode*>(fake);
  1495         qml_cn = static_cast<const QmlClassNode*>(fake);
  1480         sections = marker->qmlSections(qml_cn,CodeMarker::Summary);
  1496         sections = marker->qmlSections(qml_cn,CodeMarker::Summary,0);
  1481         generateTableOfContents(fake,marker,&sections);
  1497         generateTableOfContents(fake,marker,&sections);
  1482     }
  1498     }
  1483     else if (fake->name() != QString("index.html"))
  1499     else if (fake->name() != QString("index.html"))
  1484         generateTableOfContents(fake,marker,0);
  1500         generateTableOfContents(fake,marker,0);
  1485 
  1501 
  1557         const ClassNode* cn = qml_cn->classNode();
  1573         const ClassNode* cn = qml_cn->classNode();
  1558         generateBrief(qml_cn, marker);
  1574         generateBrief(qml_cn, marker);
  1559         generateQmlInherits(qml_cn, marker);
  1575         generateQmlInherits(qml_cn, marker);
  1560         generateQmlInheritedBy(qml_cn, marker);
  1576         generateQmlInheritedBy(qml_cn, marker);
  1561         generateQmlInstantiates(qml_cn, marker);
  1577         generateQmlInstantiates(qml_cn, marker);
       
  1578 
       
  1579         QString allQmlMembersLink = generateAllQmlMembersFile(qml_cn, marker);
       
  1580         if (!allQmlMembersLink.isEmpty()) {
       
  1581             out() << "<li><a href=\"" << allQmlMembersLink << "\">"
       
  1582                   << "List of all members, including inherited members</a></li>\n";
       
  1583         }
       
  1584 
  1562         s = sections.begin();
  1585         s = sections.begin();
  1563         while (s != sections.end()) {
  1586         while (s != sections.end()) {
  1564             out() << "<a name=\"" << registerRef((*s).name.toLower())
  1587             out() << "<a name=\"" << registerRef((*s).name.toLower())
  1565                   << "\"></a>" << divNavTop << "\n";
  1588                   << "\"></a>" << divNavTop << "\n";
  1566             out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
  1589             out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
  1576             generateQmlText(cn->doc().body(), cn, marker, fake->name());
  1599             generateQmlText(cn->doc().body(), cn, marker, fake->name());
  1577         generateAlsoList(fake, marker);
  1600         generateAlsoList(fake, marker);
  1578         generateExtractionMark(fake, EndMark);
  1601         generateExtractionMark(fake, EndMark);
  1579         //out() << "<hr />\n";
  1602         //out() << "<hr />\n";
  1580 
  1603 
  1581         sections = marker->qmlSections(qml_cn,CodeMarker::Detailed);
  1604         sections = marker->qmlSections(qml_cn,CodeMarker::Detailed,0);
  1582         s = sections.begin();
  1605         s = sections.begin();
  1583         while (s != sections.end()) {
  1606         while (s != sections.end()) {
  1584             out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
  1607             out() << "<h2>" << protectEnc((*s).name) << "</h2>\n";
  1585             NodeList::ConstIterator m = (*s).members.begin();
  1608             NodeList::ConstIterator m = (*s).members.begin();
  1586             while (m != (*s).members.end()) {
  1609             while (m != (*s).members.end()) {
  1613         out() << "<div class=\"descr\">\n"; // QTBUG-9504
  1636         out() << "<div class=\"descr\">\n"; // QTBUG-9504
  1614         out() << "<h2>" << "Detailed Description" << "</h2>\n";
  1637         out() << "<h2>" << "Detailed Description" << "</h2>\n";
  1615     }
  1638     }
  1616     else {
  1639     else {
  1617         generateExtractionMark(fake, DetailedDescriptionMark);
  1640         generateExtractionMark(fake, DetailedDescriptionMark);
  1618         out() << "<div class=\"descr\">\n"; // QTBUG-9504
  1641         out() << "<div class=\"descr\"> <a name=\"" << registerRef("details") << "\"></a>\n"; // QTBUG-9504
  1619     }
  1642     }
  1620 
  1643 
  1621     generateBody(fake, marker);
  1644     generateBody(fake, marker);
  1622     out() << "</div>\n"; // QTBUG-9504
  1645     out() << "</div>\n"; // QTBUG-9504
  1623     generateAlsoList(fake, marker);
  1646     generateAlsoList(fake, marker);
  1699             breadcrumb << Atom(Atom::AutoLink,name);
  1722             breadcrumb << Atom(Atom::AutoLink,name);
  1700             generateText(breadcrumb, node, marker);
  1723             generateText(breadcrumb, node, marker);
  1701             out() << "</li>\n";
  1724             out() << "</li>\n";
  1702         }
  1725         }
  1703         if (!cn->name().isEmpty())
  1726         if (!cn->name().isEmpty())
  1704             out() << "              <li>" << cn->name() << "</li>\n";
  1727             out() << "              <li>" << protectEnc(cn->name()) << "</li>\n";
  1705     }
  1728     }
  1706     else if (node->type() == Node::Fake) {
  1729     else if (node->type() == Node::Fake) {
  1707         const FakeNode* fn = static_cast<const FakeNode*>(node);
  1730         const FakeNode* fn = static_cast<const FakeNode*>(node);
  1708         if (node->subType() == Node::Module) {
  1731         if (node->subType() == Node::Module) {
  1709             out() << "              <li><a href=\"modules.html\">Modules</a></li>";
  1732             out() << "              <li><a href=\"modules.html\">Modules</a></li>";
  1710             QString name =  node->name();
  1733             QString name =  node->name();
  1711             if (!name.isEmpty())
  1734             if (!name.isEmpty())
  1712                 out() << "              <li>" << name << "</li>\n";
  1735                 out() << "              <li>" << protectEnc(name) << "</li>\n";
  1713         }
  1736         }
  1714         else if (node->subType() == Node::Group) {
  1737         else if (node->subType() == Node::Group) {
  1715             if (fn->name() == QString("modules"))
  1738             if (fn->name() == QString("modules"))
  1716                 out() << "              <li>Modules</li>";
  1739                 out() << "              <li>Modules</li>";
  1717             else {
  1740             else {
  1718                 out() << "              <li>" << title << "</li>";
  1741                 out() << "              <li>" << protectEnc(title) << "</li>";
  1719             }
  1742             }
  1720         }
  1743         }
  1721         else if (node->subType() == Node::Page) {
  1744         else if (node->subType() == Node::Page) {
  1722             if (fn->name() == QString("qdeclarativeexamples.html")) {
  1745             if (fn->name() == QString("qdeclarativeexamples.html")) {
  1723                 out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
  1746                 out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
  1724                 out() << "              <li>QML Examples & Demos</li>";
  1747                 out() << "              <li>QML Examples &amp; Demos</li>";
  1725             }
  1748             }
  1726             else if (fn->name().startsWith("examples-")) {
  1749             else if (fn->name().startsWith("examples-")) {
  1727                 out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
  1750                 out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
  1728                 out() << "              <li>" << title << "</li>";
  1751                 out() << "              <li>" << protectEnc(title) << "</li>";
  1729             }
  1752             }
  1730             else if (fn->name() == QString("namespaces.html")) {
  1753             else if (fn->name() == QString("namespaces.html")) {
  1731                 out() << "              <li>Namespaces</li>";
  1754                 out() << "              <li>Namespaces</li>";
  1732             }
  1755             }
  1733             else {
  1756             else {
  1734                 out() << "              <li>" << title << "</li>";
  1757                 out() << "              <li>" << protectEnc(title) << "</li>";
  1735             }
  1758             }
  1736         }
  1759         }
  1737         else if (node->subType() == Node::QmlClass) {
  1760         else if (node->subType() == Node::QmlClass) {
  1738             out() << "              <li><a href=\"qdeclarativeelements.html\">QML Elements</a></li>";
  1761             out() << "              <li><a href=\"qdeclarativeelements.html\">QML Elements</a></li>";
  1739             out() << "              <li>" << title << "</li>";
  1762             out() << "              <li>" << protectEnc(title) << "</li>";
  1740         }
  1763         }
  1741         else if (node->subType() == Node::Example) {
  1764         else if (node->subType() == Node::Example) {
  1742             out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
  1765             out() << "              <li><a href=\"all-examples.html\">Examples</a></li>";
  1743             QStringList sl = fn->name().split('/');
  1766             QStringList sl = fn->name().split('/');
  1744             if (sl.contains("declarative"))
  1767             if (sl.contains("declarative"))
  1745                 out() << "              <li><a href=\"qdeclarativeexamples.html\">QML Examples & Demos</a></li>";
  1768                 out() << "              <li><a href=\"qdeclarativeexamples.html\">QML Examples &amp; Demos</a></li>";
  1746             else {
  1769             else {
  1747                 QString name = "examples-" + sl.at(0) + ".html";
  1770                 QString name = protectEnc("examples-" + sl.at(0) + ".html"); // this generates an empty link
  1748                 QString t = CodeParser::titleFromName(name);
  1771                 QString t = CodeParser::titleFromName(name);
  1749                 out() << "              <li><a href=\"" << name << "\">"
  1772             }
  1750                       << t << "</a></li>";
  1773             out() << "              <li>" << protectEnc(title) << "</li>";
  1751             }
       
  1752             out() << "              <li>" << title << "</li>";
       
  1753         }
  1774         }
  1754     }
  1775     }
  1755     else if (node->type() == Node::Namespace) {
  1776     else if (node->type() == Node::Namespace) {
  1756         out() << "              <li><a href=\"namespaces.html\">Namespaces</a></li>";
  1777         out() << "              <li><a href=\"namespaces.html\">Namespaces</a></li>";
  1757         out() << "              <li>" << title << "</li>";
  1778         out() << "              <li>" << protectEnc(title) << "</li>";
  1758     }
  1779     }
  1759 }
  1780 }
  1760 
  1781 
  1761 void HtmlGenerator::generateHeader(const QString& title,
  1782 void HtmlGenerator::generateHeader(const QString& title,
  1762                                    const Node *node,
  1783                                    const Node *node,
  1779         if (project == "QSA")
  1800         if (project == "QSA")
  1780             shortVersion = "QSA " + shortVersion + ": ";
  1801             shortVersion = "QSA " + shortVersion + ": ";
  1781         else
  1802         else
  1782             shortVersion = "Qt " + shortVersion + ": ";
  1803             shortVersion = "Qt " + shortVersion + ": ";
  1783     }
  1804     }
  1784 	// Generating page title
  1805 
       
  1806     // Generating page title
  1785     out() << "  <title>" << shortVersion << protectEnc(title) << "</title>\n";
  1807     out() << "  <title>" << shortVersion << protectEnc(title) << "</title>\n";
  1786 	// Adding style sheet
  1808     // Adding style sheet
  1787 	out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />";
  1809     out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />\n";
  1788 	// Adding jquery and functions - providing online tools and search features
  1810     // Adding jquery and functions - providing online tools and search features
  1789 	out() << "  <script src=\"scripts/jquery.js\" type=\"text/javascript\"></script>\n";
  1811     out() << "  <script src=\"scripts/jquery.js\" type=\"text/javascript\"></script>\n";
  1790 	out() << "  <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
  1812     out() << "  <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
  1791 	// Adding style and js for small windows
  1813 
  1792 	out() << "  <script src=\"./scripts/superfish.js\" type=\"text/javascript\"></script>\n";
       
  1793 	out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/superfish.css\" />";
       
  1794 	out() << "  <script src=\"./scripts/narrow.js\" type=\"text/javascript\"></script>\n";
       
  1795 	out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/narrow.css\" />";
       
  1796 	
  1814 	
  1797 	// Adding syntax highlighter 	// future release
  1815     // Adding syntax highlighter 	// future release
  1798 	
  1816 	
  1799 	// Setting assistant configuration
  1817     // Setting some additional style sheet related details depending on configuration (e.g. Online/Creator)
  1800     if (offlineDocs)
  1818 
  1801 	{
  1819     switch (application) {
  1802 		out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />"; // Only for Qt Creator
  1820     case Online:
  1803 		out() << "</head>\n";
  1821     // Adding style and js for small windows
  1804 		out() << "<body class=\"offline \">\n"; // offline for  Assistant
  1822     out() << "  <script src=\"./scripts/superfish.js\" type=\"text/javascript\"></script>\n";
  1805 	}	
  1823     out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/superfish.css\" />";
  1806     if (creatorDocs)
  1824     out() << "  <script src=\"./scripts/narrow.js\" type=\"text/javascript\"></script>\n";
  1807 	{
  1825     out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/narrow.css\" />\n";	
  1808 		out() << "  <link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\" />"; // Only for Qt Creator
  1826         // Browser spec styles
  1809 		out() << "</head>\n";
  1827 	out() << "  <!--[if IE]>\n";
  1810 		out() << "<body class=\"offline narrow creator\">\n"; // offline for Creator
  1828 	out() << "<meta name=\"MSSmartTagsPreventParsing\" content=\"true\">\n";
  1811 	}	
  1829 	out() << "<meta http-equiv=\"imagetoolbar\" content=\"no\">\n";
  1812 	// Setting online doc configuration
  1830 	out() << "<![endif]-->\n";
  1813     else
  1831 	out() << "<!--[if lt IE 7]>\n";
  1814 		{
  1832 	out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie6.css\">\n";
  1815 		// Browser spec styles
  1833 	out() << "<![endif]-->\n";
  1816 		out() << "  <!--[if IE]>\n";
  1834 	out() << "<!--[if IE 7]>\n";
  1817 		out() << "<meta name=\"MSSmartTagsPreventParsing\" content=\"true\">\n";
  1835 	out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie7.css\">\n";
  1818 		out() << "<meta http-equiv=\"imagetoolbar\" content=\"no\">\n";
  1836 	out() << "<![endif]-->\n";
  1819 		out() << "<![endif]-->\n";
  1837 	out() << "<!--[if IE 8]>\n";
  1820 		out() << "<!--[if lt IE 7]>\n";
  1838 	out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie8.css\">\n";
  1821 		out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie6.css\">\n";
  1839 	out() << "<![endif]-->\n";
  1822 		out() << "<![endif]-->\n";
       
  1823 		out() << "<!--[if IE 7]>\n";
       
  1824 		out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie7.css\">\n";
       
  1825 		out() << "<![endif]-->\n";
       
  1826 		out() << "<!--[if IE 8]>\n";
       
  1827 		out() << "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style_ie8.css\">\n";
       
  1828 		out() << "<![endif]-->\n";
       
  1829 		
  1840 		
  1830 		out() << "</head>\n";
  1841 	out() << "</head>\n";
  1831 		// CheckEmptyAndLoadList activating search
  1842 	// CheckEmptyAndLoadList activating search
  1832 		out() << "<body class=\"\" onload=\"CheckEmptyAndLoadList();\">\n";
  1843 	out() << "<body class=\"\" onload=\"CheckEmptyAndLoadList();\">\n";
  1833 		}
  1844         break;
       
  1845     case Creator:
       
  1846 	out() << "</head>\n";
       
  1847 	out() << "<body class=\"offline narrow creator\">\n"; // offline narrow
       
  1848         break;
       
  1849     default:
       
  1850 	out() << "</head>\n";
       
  1851 	out() << "<body>\n";
       
  1852         break;
       
  1853     }
  1834 
  1854 
  1835 #ifdef GENERATE_MAC_REFS    
  1855 #ifdef GENERATE_MAC_REFS    
  1836     if (mainPage)
  1856     if (mainPage)
  1837         generateMacRef(node, marker);
  1857         generateMacRef(node, marker);
  1838 #endif    
  1858 #endif   
  1839     out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version());
  1859  
  1840     generateBreadCrumbs(title,node,marker);
  1860     switch (application) {
  1841     out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
  1861     case Online:
       
  1862         out() << QString(postHeader).replace("\\" + COMMAND_VERSION, myTree->version());
       
  1863         generateBreadCrumbs(title,node,marker);
       
  1864         out() << QString(postPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
       
  1865         break;
       
  1866     case Creator:
       
  1867         out() << QString(creatorPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
       
  1868         generateBreadCrumbs(title,node,marker);
       
  1869         out() << QString(creatorPostPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());	
       
  1870         break;
       
  1871     default: // default -- not used except if one forgets to set any of the above settings to true
       
  1872         out() << QString(creatorPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
       
  1873         generateBreadCrumbs(title,node,marker);
       
  1874         out() << QString(creatorPostPostHeader).replace("\\" + COMMAND_VERSION, myTree->version());
       
  1875         break;
       
  1876     }
       
  1877 
       
  1878         navigationLinks.clear();
       
  1879 
       
  1880     if (node && !node->links().empty()) {
       
  1881         QPair<QString,QString> linkPair;
       
  1882         QPair<QString,QString> anchorPair;
       
  1883         const Node *linkNode;
       
  1884 
       
  1885         if (node->links().contains(Node::PreviousLink)) {
       
  1886             linkPair = node->links()[Node::PreviousLink];
       
  1887             linkNode = findNodeForTarget(linkPair.first, node, marker);
       
  1888             if (!linkNode || linkNode == node)
       
  1889                 anchorPair = linkPair;
       
  1890             else
       
  1891                 anchorPair = anchorForNode(linkNode);
       
  1892 
       
  1893             out() << "  <link rel=\"prev\" href=\""
       
  1894                   << anchorPair.first << "\" />\n";
       
  1895 
       
  1896             navigationLinks += "[Previous: <a href=\"" + anchorPair.first + "\">";
       
  1897             if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
       
  1898                 navigationLinks += protect(anchorPair.second);
       
  1899             else
       
  1900                 navigationLinks += protect(linkPair.second);
       
  1901             navigationLinks += "</a>]\n";
       
  1902         }
       
  1903         if (node->links().contains(Node::NextLink)) {
       
  1904             linkPair = node->links()[Node::NextLink];
       
  1905             linkNode = findNodeForTarget(linkPair.first, node, marker);
       
  1906             if (!linkNode || linkNode == node)
       
  1907                 anchorPair = linkPair;
       
  1908             else
       
  1909                 anchorPair = anchorForNode(linkNode);
       
  1910 
       
  1911             out() << "  <link rel=\"next\" href=\""
       
  1912                   << anchorPair.first << "\" />\n";
       
  1913 
       
  1914             navigationLinks += "[Next: <a href=\"" + anchorPair.first + "\">";
       
  1915             if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
       
  1916                 navigationLinks += protect(anchorPair.second);
       
  1917             else
       
  1918                 navigationLinks += protect(linkPair.second);
       
  1919             navigationLinks += "</a>]\n";
       
  1920         }
       
  1921         if (node->links().contains(Node::StartLink)) {
       
  1922             linkPair = node->links()[Node::StartLink];
       
  1923             linkNode = findNodeForTarget(linkPair.first, node, marker);
       
  1924             if (!linkNode || linkNode == node)
       
  1925                 anchorPair = linkPair;
       
  1926             else
       
  1927                 anchorPair = anchorForNode(linkNode);
       
  1928             out() << "  <link rel=\"start\" href=\""
       
  1929                   << anchorPair.first << "\" />\n";
       
  1930         }
       
  1931     }
  1842 
  1932 
  1843 #if 0 // Removed for new doc format. MWS
  1933 #if 0 // Removed for new doc format. MWS
  1844     if (node && !node->links().empty())
  1934     if (node && !node->links().empty())
  1845         out() << "<p>\n" << navigationLinks << "</p>\n";
  1935         out() << "<p>\n" << navigationLinks << "</p>\n";
  1846 #endif    
  1936 #endif    
  1870     if (node && !node->links().empty())
  1960     if (node && !node->links().empty())
  1871         out() << "<p>\n" << navigationLinks << "</p>\n";
  1961         out() << "<p>\n" << navigationLinks << "</p>\n";
  1872 
  1962 
  1873     out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version())
  1963     out() << QString(footer).replace("\\" + COMMAND_VERSION, myTree->version())
  1874           << QString(address).replace("\\" + COMMAND_VERSION, myTree->version());
  1964           << QString(address).replace("\\" + COMMAND_VERSION, myTree->version());
  1875 	
  1965 
  1876 	    if (offlineDocs)
  1966     switch (application) {
  1877 		{
  1967     case Online:
  1878           out() << "</body>\n";
  1968         out() << "  <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
  1879 		}
  1969         out() << "  <!-- <script type=\"text/javascript\">\n";
  1880 	    if (creatorDocs)
  1970         out() << "  var _gaq = _gaq || [];\n";
  1881 		{
  1971         out() << "  _gaq.push(['_setAccount', 'UA-4457116-5']);\n";
  1882           out() << "</body>\n";
  1972         out() << "  _gaq.push(['_trackPageview']);\n";
  1883 		}
  1973         out() << "  (function() {\n";
  1884 		else
  1974         out() << "  var ga = document.createElement('script'); ";
  1885 		{
  1975         out() << "ga.type = 'text/javascript'; ga.async = true;\n";
  1886 			out() << "  <script src=\"scripts/functions.js\" type=\"text/javascript\"></script>\n";
  1976         out() << "  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + ";
  1887 			out() << "  <!-- <script type=\"text/javascript\">\n";
  1977         out() << "'.google-analytics.com/ga.js';\n";
  1888 			out() << "  var _gaq = _gaq || [];\n";
  1978         out() << "  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n";
  1889 			out() << "  _gaq.push(['_setAccount', 'UA-4457116-5']);\n";
  1979         out() << "  })();\n";
  1890 			out() << "  _gaq.push(['_trackPageview']);\n";
  1980         out() << "  </script> -->\n";
  1891 			out() << "  (function() {\n";
  1981         out() << "</body>\n";
  1892 			out() << "  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\n";
  1982 	break;
  1893 			out() << "  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\n";
  1983     case Creator:
  1894 			out() << "  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\n";
  1984         out() << "</body>\n";
  1895 			out() << "  })();\n";
  1985 	break;
  1896 			out() << "  </script> -->\n";
  1986     default:
  1897 			out() << "</body>\n";
  1987         out() << "</body>\n";
  1898 		}
  1988     }
  1899           out() <<   "</html>\n";
  1989           out() <<   "</html>\n";
  1900 }
  1990 }
  1901 
  1991 
  1902 void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker,
  1992 void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker,
  1903                                   const Node *relative)
  1993                                   const Node *relative)
  1905     Text brief = node->doc().briefText();
  1995     Text brief = node->doc().briefText();
  1906     if (!brief.isEmpty()) {
  1996     if (!brief.isEmpty()) {
  1907         generateExtractionMark(node, BriefMark);
  1997         generateExtractionMark(node, BriefMark);
  1908         out() << "<p>";
  1998         out() << "<p>";
  1909         generateText(brief, node, marker);
  1999         generateText(brief, node, marker);
       
  2000 
  1910         if (!relative || node == relative)
  2001         if (!relative || node == relative)
  1911             out() << " <a href=\"#";
  2002             out() << " <a href=\"#";
  1912         else
  2003         else
  1913             out() << " <a href=\"" << linkForNode(node, relative) << "#";
  2004             out() << " <a href=\"" << linkForNode(node, relative) << "#";
  1914         out() << registerRef("details") << "\">More...</a></p>\n";
  2005         out() << registerRef("details") << "\">More...</a></p>\n";
       
  2006 
       
  2007 
  1915         generateExtractionMark(node, EndMark);
  2008         generateExtractionMark(node, EndMark);
  1916     }
  2009     }
  1917 }
  2010 }
  1918 
  2011 
  1919 void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker)
  2012 void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker)
  1926               << "</pre>";
  2019               << "</pre>";
  1927     }
  2020     }
  1928 }
  2021 }
  1929 
  2022 
  1930 /*!
  2023 /*!
  1931   Generates a table of contents begining at \a node.
  2024   Generates a table of contents beginning at \a node.
  1932  */
  2025  */
  1933 void HtmlGenerator::generateTableOfContents(const Node *node,
  2026 void HtmlGenerator::generateTableOfContents(const Node *node,
  1934                                             CodeMarker *marker,
  2027                                             CodeMarker *marker,
  1935                                             Doc::SectioningUnit sectioningUnit,
  2028                                             Doc::SectioningUnit sectioningUnit,
  1936                                             int numColumns,
  2029                                             int numColumns,
  2012     inLink = false;
  2105     inLink = false;
  2013 }
  2106 }
  2014 
  2107 
  2015 /*!
  2108 /*!
  2016   Revised for the new doc format.
  2109   Revised for the new doc format.
  2017   Generates a table of contents begining at \a node.
  2110   Generates a table of contents beginning at \a node.
  2018  */
  2111  */
  2019 void HtmlGenerator::generateTableOfContents(const Node *node,
  2112 void HtmlGenerator::generateTableOfContents(const Node *node,
  2020                                             CodeMarker *marker,
  2113                                             CodeMarker *marker,
  2021                                             QList<Section>* sections)
  2114                                             QList<Section>* sections)
  2022 {
  2115 {
  2180     QString title = "List of All Members for " + inner->name();
  2273     QString title = "List of All Members for " + inner->name();
  2181     generateHeader(title, inner, marker);
  2274     generateHeader(title, inner, marker);
  2182     generateTitle(title, Text(), SmallSubTitle, inner, marker);
  2275     generateTitle(title, Text(), SmallSubTitle, inner, marker);
  2183     out() << "<p>This is the complete list of members for ";
  2276     out() << "<p>This is the complete list of members for ";
  2184     generateFullName(inner, 0, marker);
  2277     generateFullName(inner, 0, marker);
       
  2278     out() << ", including inherited members.</p>\n";
       
  2279 
       
  2280     Section section = sections.first();
       
  2281     generateSectionList(section, 0, marker, CodeMarker::SeparateList);
       
  2282 
       
  2283     generateFooter();
       
  2284     endSubPage();
       
  2285     return fileName;
       
  2286 }
       
  2287 
       
  2288 /*!
       
  2289   This function creates an html page on which are listed all
       
  2290   the members of QML class \a qml_cn, including the inherited
       
  2291   members. The \a marker is used for formatting stuff.
       
  2292  */
       
  2293 QString HtmlGenerator::generateAllQmlMembersFile(const QmlClassNode* qml_cn,
       
  2294                                                  CodeMarker* marker)
       
  2295 {
       
  2296     QList<Section> sections;
       
  2297     QList<Section>::ConstIterator s;
       
  2298 
       
  2299     sections = marker->qmlSections(qml_cn,CodeMarker::SeparateList,myTree);
       
  2300     if (sections.isEmpty())
       
  2301         return QString();
       
  2302 
       
  2303     QString fileName = fileBase(qml_cn) + "-members." + fileExtension(qml_cn);
       
  2304     beginSubPage(qml_cn->location(), fileName);
       
  2305     QString title = "List of All Members for " + qml_cn->name();
       
  2306     generateHeader(title, qml_cn, marker);
       
  2307     generateTitle(title, Text(), SmallSubTitle, qml_cn, marker);
       
  2308     out() << "<p>This is the complete list of members for ";
       
  2309     generateFullName(qml_cn, 0, marker);
  2185     out() << ", including inherited members.</p>\n";
  2310     out() << ", including inherited members.</p>\n";
  2186 
  2311 
  2187     Section section = sections.first();
  2312     Section section = sections.first();
  2188     generateSectionList(section, 0, marker, CodeMarker::SeparateList);
  2313     generateSectionList(section, 0, marker, CodeMarker::SeparateList);
  2189 
  2314 
  3050             i += 2;
  3175             i += 2;
  3051             bool handled = false;
  3176             bool handled = false;
  3052             if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
  3177             if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
  3053                 par1 = QStringRef();
  3178                 par1 = QStringRef();
  3054                 const Node* n = marker->resolveTarget(arg.toString(), myTree, relative, self);
  3179                 const Node* n = marker->resolveTarget(arg.toString(), myTree, relative, self);
  3055                 addLink(linkForNode(n,relative), arg, &html);
  3180                 if (n && n->subType() == Node::QmlBasicType) {
       
  3181                     if (relative && relative->subType() == Node::QmlClass)
       
  3182                         addLink(linkForNode(n,relative), arg, &html);
       
  3183                     else 
       
  3184                         html += arg.toString();
       
  3185                 }
       
  3186                 else
       
  3187                     addLink(linkForNode(n,relative), arg, &html);
  3056                 handled = true;
  3188                 handled = true;
  3057             }
  3189             }
  3058             else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
  3190             else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
  3059                 par1 = QStringRef();
  3191                 par1 = QStringRef();
  3060                 const Node* n = marker->resolveTarget(arg.toString(), myTree, relative);
  3192                 const Node* n = marker->resolveTarget(arg.toString(), myTree, relative);
  3412         return node->url();
  3544         return node->url();
  3413     if (fileBase(node).isEmpty())
  3545     if (fileBase(node).isEmpty())
  3414         return QString();
  3546         return QString();
  3415     if (node->access() == Node::Private)
  3547     if (node->access() == Node::Private)
  3416         return QString();
  3548         return QString();
  3417 
  3549  
  3418     fn = fileName(node);
  3550     fn = fileName(node);
  3419 /*    if (!node->url().isEmpty())
  3551 /*    if (!node->url().isEmpty())
  3420         return fn;*/
  3552         return fn;*/
  3421 #if 0
  3553 #if 0
  3422     // ### reintroduce this test, without breaking .dcf files
  3554     // ### reintroduce this test, without breaking .dcf files
  3584 
  3716 
  3585                 QString serviceName =
  3717                 QString serviceName =
  3586                     (static_cast<const ClassNode *>(*c))->serviceName();
  3718                     (static_cast<const ClassNode *>(*c))->serviceName();
  3587                 if (!serviceName.isEmpty())
  3719                 if (!serviceName.isEmpty())
  3588                     serviceClasses.insert(serviceName, *c);
  3720                     serviceClasses.insert(serviceName, *c);
       
  3721             }
       
  3722             else if ((*c)->type() == Node::Fake &&
       
  3723                      (*c)->subType() == Node::QmlClass &&
       
  3724                      !(*c)->doc().isEmpty()) {
       
  3725                 QString qmlClassName = (*c)->name();
       
  3726                 qmlClasses.insert(qmlClassName,*c);
  3589             }
  3727             }
  3590             else if ((*c)->isInnerNode()) {
  3728             else if ((*c)->isInnerNode()) {
  3591                 findAllClasses(static_cast<InnerNode *>(*c));
  3729                 findAllClasses(static_cast<InnerNode *>(*c));
  3592             }
  3730             }
  3593         }
  3731         }
  4290         return false;
  4428         return false;
  4291     if (node->name().isEmpty())
  4429     if (node->name().isEmpty())
  4292         return true;
  4430         return true;
  4293     if (node->access() == Node::Private)
  4431     if (node->access() == Node::Private)
  4294         return false;
  4432         return false;
  4295     if (!node->isInnerNode())
  4433 
  4296         return false;
  4434     QString guid = QUuid::createUuid().toString();
  4297 
  4435     QString url = PageGenerator::fileName(node);
  4298     QString title;
  4436     QString title;
  4299     QString rawTitle;
  4437     QString rawTitle;
  4300     QString fullTitle;
  4438     QString fullTitle;
  4301     const InnerNode* inner = static_cast<const InnerNode*>(node);
  4439     QStringList pageWords;
  4302         
  4440     QXmlStreamAttributes attributes;
       
  4441 
  4303     writer.writeStartElement("page");
  4442     writer.writeStartElement("page");
  4304     QXmlStreamAttributes attributes;
  4443 
  4305     QString t;
  4444     if (node->isInnerNode()) {
  4306     t.setNum(id++);
  4445         const InnerNode* inner = static_cast<const InnerNode*>(node);
  4307     switch (node->type()) {
  4446         if (!inner->pageKeywords().isEmpty())
  4308     case Node::Fake:
  4447             pageWords << inner->pageKeywords();
  4309         {
  4448 
  4310             const FakeNode* fake = static_cast<const FakeNode*>(node);
  4449         switch (node->type()) {
  4311             title = fake->fullTitle();
  4450         case Node::Fake:
       
  4451             {
       
  4452                 const FakeNode* fake = static_cast<const FakeNode*>(node);
       
  4453                 title = fake->fullTitle();
       
  4454                 pageWords << title;
       
  4455                 break;
       
  4456             }
       
  4457         case Node::Class:
       
  4458             {
       
  4459                 title = node->name() + " Class Reference";
       
  4460                 pageWords << node->name() << "class" << "reference";
       
  4461                 break;
       
  4462             }
       
  4463         case Node::Namespace:
       
  4464             {
       
  4465                 rawTitle = marker->plainName(inner);
       
  4466                 fullTitle = marker->plainFullName(inner);
       
  4467                 title = rawTitle + " Namespace Reference";
       
  4468                 pageWords << rawTitle << "namespace" << "reference";
       
  4469                 break;
       
  4470             }
       
  4471         default:
       
  4472             title = node->name();
       
  4473             pageWords << title;
  4312             break;
  4474             break;
  4313         }
  4475         }
  4314     case Node::Class:
  4476     }
  4315         {
  4477     else {
  4316             title = node->name() + " Class Reference";
  4478         switch (node->type()) {
       
  4479         case Node::Enum:
       
  4480             {
       
  4481                 title = node->name() + " Enum Reference";
       
  4482                 pageWords << node->name() << "enum" << "type";
       
  4483                 url += "#" + node->name() + "-enum";
       
  4484                 break;
       
  4485             }
       
  4486         case Node::Function:
       
  4487             {
       
  4488                 title = node->name() + " Function Reference";
       
  4489                 pageWords << node->name() << "function";
       
  4490                 url += "#" + node->name();
       
  4491                 break;
       
  4492             }
       
  4493         case Node::Property:
       
  4494             {
       
  4495                 title = node->name() + " Property Reference";
       
  4496                 pageWords << node->name() << "property";
       
  4497                 url += "#" + node->name() + "-prop";
       
  4498                 break;
       
  4499             }
       
  4500         case Node::Typedef:
       
  4501             {
       
  4502                 title = node->name() + " Type Reference";
       
  4503                 pageWords << node->name() << "typedef" << "type";
       
  4504                 url += "#" + node->name();
       
  4505                 break;
       
  4506             }
       
  4507         default:
       
  4508             title = node->name();
       
  4509             pageWords << title;
  4317             break;
  4510             break;
  4318         }
  4511         }
  4319     case Node::Namespace:
  4512 
  4320         {
  4513         Node* parent = node->parent();
  4321             rawTitle = marker->plainName(inner);
  4514         if (parent && ((parent->type() == Node::Class) ||
  4322             fullTitle = marker->plainFullName(inner);
  4515                        (parent->type() == Node::Namespace))) {
  4323             title = rawTitle + " Namespace Reference";
  4516             pageWords << parent->name();
  4324             break;
  4517         }
  4325         }
  4518     }
  4326     default:
  4519 
  4327         title = node->name();
  4520     writer.writeAttribute("id",guid);
  4328         break;
       
  4329     }
       
  4330     writer.writeAttribute("id",t);
       
  4331     writer.writeStartElement("pageWords");
  4521     writer.writeStartElement("pageWords");
  4332     writer.writeCharacters(title);
  4522     writer.writeCharacters(pageWords.join(" "));
  4333     if (!inner->pageKeywords().isEmpty()) {
  4523 
  4334         const QStringList& w = inner->pageKeywords();
       
  4335         for (int i = 0; i < w.size(); ++i) {
       
  4336             writer.writeCharacters(" ");
       
  4337             writer.writeCharacters(w.at(i).toLocal8Bit().constData());
       
  4338         }
       
  4339     }
       
  4340     writer.writeEndElement();
  4524     writer.writeEndElement();
  4341     writer.writeStartElement("pageTitle");
  4525     writer.writeStartElement("pageTitle");
  4342     writer.writeCharacters(title);
  4526     writer.writeCharacters(title);
  4343     writer.writeEndElement();
  4527     writer.writeEndElement();
  4344     writer.writeStartElement("pageUrl");
  4528     writer.writeStartElement("pageUrl");
  4345     writer.writeCharacters(PageGenerator::fileName(node));
  4529     writer.writeCharacters(url);
  4346     writer.writeEndElement();
  4530     writer.writeEndElement();
  4347     writer.writeStartElement("pageType");
  4531     writer.writeStartElement("pageType");
  4348     switch (node->pageType()) {
  4532     switch (node->pageType()) {
  4349     case Node::ApiPage:
  4533     case Node::ApiPage:
  4350         writer.writeCharacters("APIPage");
  4534         writer.writeCharacters("APIPage");
  4358     default:
  4542     default:
  4359         break;
  4543         break;
  4360     }
  4544     }
  4361     writer.writeEndElement();
  4545     writer.writeEndElement();
  4362     writer.writeEndElement();
  4546     writer.writeEndElement();
       
  4547 
       
  4548     if (node->type() == Node::Fake && node->doc().hasTableOfContents()) {
       
  4549         QList<Atom*> toc = node->doc().tableOfContents();
       
  4550         if (!toc.isEmpty()) {
       
  4551             for (int i = 0; i < toc.size(); ++i) {
       
  4552                 Text headingText = Text::sectionHeading(toc.at(i));
       
  4553                 QString s = headingText.toString();
       
  4554                 writer.writeStartElement("page");
       
  4555                 guid = QUuid::createUuid().toString();
       
  4556                 QString internalUrl = url + "#" + Doc::canonicalTitle(s);
       
  4557                 writer.writeAttribute("id",guid);
       
  4558                 writer.writeStartElement("pageWords");
       
  4559                 writer.writeCharacters(pageWords.join(" "));
       
  4560                 writer.writeCharacters(" ");
       
  4561                 writer.writeCharacters(s);
       
  4562                 writer.writeEndElement();
       
  4563                 writer.writeStartElement("pageTitle");
       
  4564                 writer.writeCharacters(s);
       
  4565                 writer.writeEndElement();
       
  4566                 writer.writeStartElement("pageUrl");
       
  4567                 writer.writeCharacters(internalUrl);
       
  4568                 writer.writeEndElement();
       
  4569                 writer.writeStartElement("pageType");
       
  4570                 writer.writeCharacters("Article");
       
  4571                 writer.writeEndElement();
       
  4572                 writer.writeEndElement();
       
  4573             }
       
  4574         }
       
  4575     }
  4363     return true;
  4576     return true;
  4364 }
  4577 }
  4365 
  4578 
  4366 /*!
  4579 /*!
  4367   Traverse the tree recursively and generate the <keyword>
  4580   Traverse the tree recursively and generate the <keyword>