29#include <QtCore/qlist.h>
30#include <QtCore/qmap.h>
31#include <QtCore/quuid.h>
32#include <QtCore/qversionnumber.h>
33#include <QtCore/qregularexpression.h>
41using namespace Qt::StringLiterals;
48static const auto headingStart =
"<h3 class=\"%1\" translate=\"no\" id=\"%2\">"_L1;
53static void addLink(
const QString &linkTarget, QStringView nestedStuff, QString *res)
55 if (!linkTarget.isEmpty()) {
56 *res += QLatin1String(
"<a href=\"");
58 *res += QLatin1String(
"\" translate=\"no\">");
60 *res += QLatin1String(
"</a>");
67
68
69
70
73 auto result{classSet};
74 if (node->isInternal())
75 result +=
" internal"_L1;
80
81
82
85 if (!s_inUnorderedList) {
87 s_inUnorderedList =
true;
92
93
94
97 if (s_inUnorderedList) {
99 s_inUnorderedList =
false;
104
105
106
109 if (m_helpProjectWriter) {
110 delete m_helpProjectWriter;
111 m_helpProjectWriter =
nullptr;
114 if (m_manifestWriter) {
115 delete m_manifestWriter;
116 m_manifestWriter =
nullptr;
121
122
123
143 {
nullptr,
nullptr,
nullptr } };
146 config = &Config::instance();
149
150
151
152 for (
int i = 0; defaults[i].key; ++i) {
153 formattingLeftMap().insert(QLatin1String(defaults[i].key), QLatin1String(defaults[i].left));
154 formattingRightMap().insert(QLatin1String(defaults[i].key),
155 QLatin1String(defaults[i].right));
158 QString formatDot{HtmlGenerator::format() + Config::dot};
159 m_endHeader = config->get(formatDot +
CONFIG_ENDHEADER).asString(
"</head>\n<body>\n"_L1);
173 .asString(m_project +
" Reference Documentation"_L1);
175 m_projectUrl = config->get(
CONFIG_URL).asString();
184
185
186
187 if (m_helpProjectWriter)
188 m_helpProjectWriter->reset(m_project.toLower() +
".qhp",
this);
190 m_helpProjectWriter =
new HelpProjectWriter(m_project.toLower() +
".qhp",
this);
192 if (!m_manifestWriter)
205 .asString(m_homepage);
212 .asString(m_landingpage);
219 .asString(
"C++ Classes"_L1);
226 .asString(
"QML Types"_L1);
235
236
248
249
250
251
252
253
254
260 Node *qflags = m_qdb->findClassNode(QStringList(
"QFlags"_L1));
262 m_qflagsHref = linkForNode(qflags,
nullptr);
266 const QString fileBase =
"%1/%2"_L1.arg(
268 m_project.toLower().simplified().replace(
' '_L1,
'-'_L1)
275 const QString &rootTitle = m_landingpage.isEmpty() ? m_homepage : m_landingpage;
276 tocWriter
.generateTOC(
"%1_toc.xml"_L1.arg(fileBase), rootTitle);
278
279
280 if (!tagFile_.isEmpty()) {
288
289
292 SubTitleSize subTitleSize = LargeSubTitle;
293 QString fullTitle = en->fullTitle();
295 beginSubPage(en, linkForExampleFile(resolved_file.get_query()));
296 generateHeader(fullTitle, en, marker);
302 QString code = quoter.quoteTo(en->location(), QString(), QString());
303 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
307 generateText(text, en, codeMarker);
312
313
316 qsizetype idx, skipAhead = 0;
317 static bool in_para =
false;
318 Genus genus = Genus::DontCare;
322 QString name = atom->string();
323 if (relative && relative->name() == name.replace(QLatin1String(
"()"), QLatin1String())) {
324 out() << protectEnc(atom->string());
332 if (!m_inLink && !m_inContents && !m_inSectionHeading) {
333 const Node *node =
nullptr;
334 QString link = getAutoLink(atom, relative, &node, genus);
335 if (link.isEmpty()) {
340 QStringLiteral(
"Can't autolink to '%1'").arg(atom->string()));
345 if (link.isEmpty()) {
346 out() << protectEnc(atom->string());
348 beginLink(link, node, relative);
353 out() << protectEnc(atom->string());
360 skipAhead = skipAtoms(atom, Atom::BriefRight);
375 out() << protectEnc(plainCode(atom->string()));
379 out() <<
"<p class=\"figCaption\">";
390 out() <<
"<pre class=\"qml\" translate=\"no\"><code class=\"qml\">"
391 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative,
393 m_codePrefix, m_codeSuffix)
394 <<
"</code></pre>\n";
398 if (atom->strings().count() == 2)
399 out() <<
"<pre class=\"" << atom->string(1) <<
"\" translate=\"no\"><code class=\"" << atom->string(1) <<
"\">";
401 out() <<
"<pre class=\"cpp\" translate=\"no\"><code class=\"cpp\">";
403 out() << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative),
404 m_codePrefix, m_codeSuffix)
405 <<
"</code></pre>\n";
408 out() <<
"<pre class=\"cpp plain\" translate=\"no\"><code class=\"text\">"
409 << trimmedTrailing(protectEnc(plainCode(indent(m_codeIndent, atom->string()))),
410 m_codePrefix, m_codeSuffix)
411 <<
"</code></pre>\n";
414 out() <<
"<details>\n";
415 if (!atom->string().isEmpty())
416 out() <<
"<summary>" << protectEnc(atom->string()) <<
"</summary>\n";
418 out() <<
"<summary>...</summary>\n";
421 out() <<
"</details>\n";
425 if (!atom->string().isEmpty())
426 out() <<
' ' << atom->string();
449 if (atom->string().startsWith(
"span "))
450 out() <<
'<' + atom->string() <<
'>';
452 out() << formattingLeftMap()[atom->string()];
460 const Node *node{
nullptr};
461 const Atom tm_link(Atom::NavLink, m_trademarkspage);
462 if (
const auto &link = getLink(&tm_link, relative, &node);
463 !link.isEmpty() && node != relative)
464 out() <<
"<a href=\"%1\">%2</a>"_L1.arg(link, formattingRightMap()[atom->string()]);
466 out() << formattingRightMap()[atom->string()];
469 }
else if (atom->string().startsWith(
"span ")) {
472 out() << formattingRightMap()[atom->string()];
476 if (
const auto *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group); cn)
477 generateList(cn, marker, atom->string(), Generator::sortOrder(atom->strings().last()));
480 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
481 if (atom->string() == QLatin1String(
"annotatedclasses")) {
482 generateAnnotatedList(relative, marker, m_qdb->getCppClasses().values(), sortOrder);
483 }
else if (atom->string() == QLatin1String(
"annotatedexamples")) {
484 generateAnnotatedLists(relative, marker, m_qdb->getExamples());
485 }
else if (atom->string() == QLatin1String(
"annotatedattributions")) {
486 generateAnnotatedLists(relative, marker, m_qdb->getAttributions());
487 }
else if (atom->string() == QLatin1String(
"classes")) {
488 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true,
490 }
else if (atom->string().contains(
"classes ")) {
491 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
492 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true, rootName);
493 }
else if (atom->string() == QLatin1String(
"qmlvaluetypes")
494 || atom->string() == QLatin1String(
"qmlbasictypes")) {
495 generateCompactList(Generic, relative, m_qdb->getQmlValueTypes(),
true,
497 }
else if (atom->string() == QLatin1String(
"qmltypes")) {
498 generateCompactList(Generic, relative, m_qdb->getQmlTypes(),
true, QStringLiteral(
""));
499 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
501 QString moduleName = atom->string().mid(idx + 8).trimmed();
503 if (
const auto *cn = qdb->getCollectionNode(moduleName, moduleType)) {
505 switch (moduleType) {
509 generateAnnotatedList(relative, marker, map.values(), sortOrder);
512 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
516 generateAnnotatedList(relative, marker, map.values(), sortOrder);
519 generateAnnotatedList(relative, marker, cn->members(), sortOrder);
523 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
524 generateClassHierarchy(relative, m_qdb->getCppClasses());
525 }
else if (atom->string() == QLatin1String(
"obsoleteclasses")) {
526 generateCompactList(Generic, relative, m_qdb->getObsoleteClasses(),
false,
527 QStringLiteral(
"Q"));
528 }
else if (atom->string() == QLatin1String(
"obsoleteqmltypes")) {
529 generateCompactList(Generic, relative, m_qdb->getObsoleteQmlTypes(),
false,
531 }
else if (atom->string() == QLatin1String(
"obsoletecppmembers")) {
532 generateCompactList(Obsolete, relative, m_qdb->getClassesWithObsoleteMembers(),
false,
533 QStringLiteral(
"Q"));
534 }
else if (atom->string() == QLatin1String(
"obsoleteqmlmembers")) {
535 generateCompactList(Obsolete, relative, m_qdb->getQmlTypesWithObsoleteMembers(),
false,
537 }
else if (atom->string() == QLatin1String(
"functionindex")) {
538 generateFunctionIndex(relative);
539 }
else if (atom->string() == QLatin1String(
"attributions")) {
540 generateAnnotatedList(relative, marker, m_qdb->getAttributions().values(), sortOrder);
541 }
else if (atom->string() == QLatin1String(
"legalese")) {
542 generateLegaleseList(relative, marker);
543 }
else if (atom->string() == QLatin1String(
"overviews")) {
544 generateList(relative, marker,
"overviews", sortOrder);
545 }
else if (atom->string() == QLatin1String(
"cpp-modules")) {
546 generateList(relative, marker,
"cpp-modules", sortOrder);
547 }
else if (atom->string() == QLatin1String(
"qml-modules")) {
548 generateList(relative, marker,
"qml-modules", sortOrder);
549 }
else if (atom->string() == QLatin1String(
"namespaces")) {
550 generateAnnotatedList(relative, marker, m_qdb->getNamespaces().values(), sortOrder);
551 }
else if (atom->string() == QLatin1String(
"related")) {
552 generateList(relative, marker,
"related", sortOrder);
554 const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group);
556 if (!generateGroupList(
const_cast<CollectionNode *>(cn), sortOrder))
558 QString(
"'\\generatelist %1' group is empty").arg(atom->string()));
561 QString(
"'\\generatelist %1' no such group").arg(atom->string()));
566 const NodeMultiMap &nsmap = m_qdb->getSinceMap(atom->string());
570 const NodeMultiMap &ncmap = m_qdb->getClassMap(atom->string());
571 const NodeMultiMap &nqcmap = m_qdb->getQmlTypeMap(atom->string());
576 for (
const auto §ion : sinceSections) {
577 if (!section.members().isEmpty()) {
579 <<
"<a href=\"#" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
580 << section.title() <<
"</a></li>\n";
586 for (
const auto §ion : sinceSections) {
587 if (!section.members().isEmpty()) {
588 out() <<
"<h3 id=\"" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
589 << protectEnc(section.title()) <<
"</h3>\n";
590 if (index == Sections::SinceClasses)
591 generateCompactList(Generic, relative, ncmap,
false, QStringLiteral(
"Q"));
592 else if (index == Sections::SinceQmlTypes)
593 generateCompactList(Generic, relative, nqcmap,
false, QStringLiteral(
""));
594 else if (index == Sections::SinceMemberFunctions
595 || index == Sections::SinceQmlMethods
596 || index == Sections::SinceQmlProperties) {
598 QMap<QString, NodeMultiMap> parentmaps;
600 const QList<Node *> &members = section.members();
601 for (
const auto &member : members) {
602 QString parent_full_name = (*member).parent()->fullName();
604 auto parent_entry = parentmaps.find(parent_full_name);
605 if (parent_entry == parentmaps.end())
606 parent_entry = parentmaps.insert(parent_full_name, NodeMultiMap());
607 parent_entry->insert(member->name(), member);
610 for (
auto map = parentmaps.begin(); map != parentmaps.end(); ++map) {
611 NodeVector nv = map->values().toVector();
612 auto parent = nv.front()->parent();
614 out() << ((index == Sections::SinceMemberFunctions) ?
"<p>Class " :
"<p>QML Type ");
616 out() <<
"<a href=\"" << linkForNode(parent, relative) <<
"\" translate=\"no\">";
617 QStringList pieces = parent->fullName().split(
"::");
618 out() << protectEnc(pieces.last());
622 generateSection(nv, relative, marker);
625 }
else if (index == Sections::SinceEnumValues) {
626 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
627 const auto map_it = m_qdb->newEnumValueMaps().constFind(atom->string());
628 for (
auto it = map_it->cbegin(); it != map_it->cend(); ++it) {
629 out() <<
"<tr><td class=\"memItemLeft\"> enum value </td><td class=\"memItemRight\">"
630 <<
"<b><a href=\"" << linkForNode(it.value(),
nullptr) <<
"\">"
631 << it.key() <<
"</a></b></td></tr>\n";
633 out() <<
"</table></div>\n";
635 generateSection(section.members(), relative, marker);
653 out() <<
"<p class=\"centerAlign\">";
655 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
656 if (!maybe_resolved_file) {
659 QStringLiteral(
"Missing image: %1").arg(protectEnc(atom->string())));
660 out() <<
"<font color=\"red\">[Missing image " << protectEnc(atom->string())
664 QString file_name{QFileInfo{file.get_path()}.fileName()};
684 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
686 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
688 out() <<
"<img src=\"%1\""_L1.arg(protectEnc(imgPath));
690 const QString altAndTitleText = protectEnc(text);
691 out() <<
" alt=\"" << altAndTitleText;
693 out() <<
"\" title=\"" << altAndTitleText;
697 m_helpProjectWriter->addExtraFile(imgPath);
698 setImageFileName(relative, imgPath);
710 QString admonType = atom->typeString();
713 out() <<
"<div class=\"admonition " << admonType.toLower() <<
"\">\n"
716 out() << admonType <<
": ";
726 out() <<
"<div class=\"LegaleseLeft\">";
740 const Node *node =
nullptr;
741 QString link = getLink(atom, relative, &node);
743 Location location = atom->isLinkAtom() ?
static_cast<
const LinkAtom*>(atom)->location
744 : relative->doc().location();
746 QStringLiteral(
"Can't link to '%1'").arg(atom->string()));
748 beginLink(link, node, relative);
752 QString link = linkForExampleFile(atom->string());
757 QString link = atom->string();
758 link =
"images/used-in-examples/" + link;
763 const Node *node =
static_cast<
const Node*>(Utilities::nodeForString(atom->string()));
764 beginLink(linkForNode(node, relative), node, relative);
777 out() << R"(<div class="table"><table class="valuelist">)";
778 m_threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
779 if (m_threeColumnEnumValueTable) {
780 if (++m_numTableRows % 2 == 1)
781 out() << R"(<tr valign="top" class="odd">)";
783 out() << R"(<tr valign="top" class="even">)";
785 out() <<
"<th class=\"tblConst\">Constant</th>";
789 out() <<
"<th class=\"tblval\">Value</th>";
791 out() <<
"<th class=\"tbldscr\">Description</th></tr>\n";
793 out() <<
"<tr><th class=\"tblConst\">Constant</th><th "
794 "class=\"tblVal\">Value</th></tr>\n";
811 out() << QString(R"(<ol class="%1" type="%1" start="%2">)")
812 .arg(olType, atom
->next()->string());
814 out() << QString(R"(<ol class="%1" type="%1">)").arg(olType);
823 std::pair<QString,
int> pair = getAtomListValue(atom);
824 skipAhead = pair.second;
825 QString t = protectEnc(plainCode(marker->markedUpEnumValue(pair.first, relative)));
826 out() <<
"<tr><td class=\"topAlign\"><code translate=\"no\">" << t <<
"</code>";
829 out() <<
"</td><td class=\"topAlign tblval\">";
830 const auto *enume =
static_cast<
const EnumNode *>(relative);
831 QString itemValue = enume->itemValue(atom->next()->string());
832 if (itemValue.isEmpty())
835 out() <<
"<code translate=\"no\">" << protectEnc(itemValue) <<
"</code>";
848 if (m_threeColumnEnumValueTable) {
849 out() <<
"</td><td class=\"topAlign\">";
856 if (matchAhead(atom, Atom::ParaLeft))
863 out() <<
"</td></tr>\n";
874 out() <<
"</table></div>\n";
895 out() <<
"<blockquote>";
898 out() <<
"</blockquote>\n";
901 out() << atom->string();
907 int unit = atom->string().toInt() +
hOffset(relative
);
908 out() <<
"<h" + QString::number(unit) + QLatin1Char(
' ') <<
"id=\""
909 << Tree::refForAtom(atom) <<
"\">";
910 m_inSectionHeading =
true;
913 case Atom::SectionHeadingRight:
914 out() <<
"</h" + QString::number(atom->string().toInt() + hOffset(relative)) +
">\n";
915 m_inSectionHeading =
false;
922 if (m_inLink && !m_inContents && !m_inSectionHeading) {
925 out() << protectEnc(atom->string());
929 std::pair<QString, QString> pair = getTableWidthAttr(atom);
930 QString attr = pair.second;
931 QString width = pair.first;
938 out() << R"(<div class="table"><table class=")" << attr <<
'"';
939 if (!width.isEmpty())
940 out() <<
" width=\"" << width <<
'"';
945 out() <<
"</table></div>\n";
948 out() <<
"<thead><tr class=\"qt-style\">";
949 m_inTableHeader =
true;
955 out() <<
"\n<tr class=\"qt-style\">";
957 out() <<
"</thead>\n";
958 m_inTableHeader =
false;
962 if (!atom->string().isEmpty())
963 out() <<
"<tr " << atom->string() <<
'>';
964 else if (++m_numTableRows % 2 == 1)
965 out() << R"(<tr valign="top" class="odd">)";
967 out() << R"(<tr valign="top" class="even">)";
978 for (
int i = 0; i < atom->count(); ++i) {
981 const QString &p = atom->string(i);
982 if (p.contains(
'=')) {
985 QStringList spans = p.split(QLatin1Char(
','));
986 if (spans.size() == 2) {
987 if (spans.at(0) !=
"1")
988 out() <<
" colspan=\"" << spans.at(0) <<
'"';
989 if (spans.at(1) !=
"1")
990 out() <<
" rowspan=\"" << spans.at(1) <<
'"';
995 if (matchAhead(atom, Atom::ParaLeft))
1004 if (matchAhead(atom, Atom::ParaLeft))
1014 out() <<
"<span id=\"" << Utilities::asAsciiPrintable(atom->string()) <<
"\"></span>";
1017 out() <<
"<b class=\"redFont\"><Missing HTML></b>";
1019 case Atom::UnknownCommand:
1020 out() << R"(<b class="redFont"><code translate=\"no\">\)" << protectEnc(atom->string()) <<
"</code></b>";
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1068 auto link_for_group = [
this](
const CollectionNode *group) -> QString {
1069 QString target{linkForNode(group,
nullptr)};
1070 return (target.isEmpty()) ? protectEnc(group->name()) :
"<a href=\"" + target +
"\">" + protectEnc(group->fullTitle()) +
"</a>";
1075 const QStringList &groups_names{node->groupNames()};
1076 if (groups_names.isEmpty())
1079 std::vector<CollectionNode *> groups_nodes(groups_names.size(),
nullptr);
1080 std::transform(groups_names.cbegin(), groups_names.cend(), groups_nodes.begin(),
1083 m_qdb->mergeCollections(group);
1084 return (group && group
->wasSeen()) ? group :
nullptr;
1086 groups_nodes.erase(
std::remove(groups_nodes.begin(), groups_nodes.end(),
nullptr), groups_nodes.end());
1088 if (!groups_nodes.empty()) {
1089 text += node->name() +
" is part of ";
1091 for (std::vector<CollectionNode *>::size_type index{0}; index < groups_nodes.size(); ++index) {
1092 text += link_for_group(groups_nodes[index]) + Utilities::separator(index, groups_nodes.size());
1099
1100
1101
1102
1113 QString typeWord = aggregate->typeWord(
true);
1116 fullTitle = aggregate->plainFullName();
1117 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1118 ns =
static_cast<NamespaceNode *>(aggregate);
1120 fullTitle = aggregate->plainFullName();
1121 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1123 title = fullTitle = aggregate->fullTitle();
1124 if (!aggregate->doc().title().isEmpty())
1125 titleText << aggregate->name() <<
" - "_L1 << aggregate->doc().title();
1130 if (aggregate
->parent()->isInAPI() || templateDecl) {
1132 subtitleText <<
"%1 "_L1.arg((*templateDecl).to_qstring());
1133 subtitleText << aggregate->typeWord(
false) <<
" "_L1;
1134 auto ancestors = fullTitle.split(
"::"_L1);
1135 ancestors.pop_back();
1136 for (
const auto &a : ancestors)
1137 subtitleText << Atom(Atom::AutoLink, a) <<
"::"_L1;
1138 subtitleText << aggregate->plainName();
1141 generateHeader(title, aggregate, marker);
1142 generateTableOfContents(aggregate, marker, &summarySections);
1144 generateTitle(titleText, subtitleText, SmallSubTitle, aggregate, marker);
1146 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1150 brief <<
"The " << ns->name() <<
" namespace includes the following elements from module "
1153 addNodeLink(brief, fullNamespace,
" here.");
1155 generateText(brief, ns, marker);
1158 generateBrief(aggregate, marker);
1160 const auto parentIsClass = aggregate
->parent()->isClassNode();
1163 generateRequisites(aggregate, marker);
1168 QString membersLink = generateAllMembersFile(sections.allMembersSection(), marker);
1169 if (!membersLink.isEmpty()) {
1170 openUnorderedList();
1171 out() <<
"<li><a href=\"" << membersLink <<
"\">"
1172 <<
"List of all members, including inherited members</a></li>\n";
1174 QString obsoleteLink = generateObsoleteMembersFile(sections, marker);
1175 if (!obsoleteLink.isEmpty()) {
1176 openUnorderedList();
1177 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1178 <<
"Deprecated members</a></li>\n";
1181 if (QString groups_text{groupReferenceText(aggregate)}; !groups_text.isEmpty()) {
1182 openUnorderedList();
1184 out() <<
"<li>" << groups_text <<
"</li>\n";
1187 closeUnorderedList();
1192 bool needOtherSection =
false;
1194 for (
const auto §ion : summarySections) {
1195 if (section.members().isEmpty() && section.reimplementedMembers().isEmpty()) {
1196 if (!section.inheritedMembers().isEmpty())
1197 needOtherSection =
true;
1199 if (!section.members().isEmpty()) {
1200 QString ref = registerRef(section.title().toLower());
1201 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1202 generateSection(section.members(), aggregate, marker);
1204 if (!section.reimplementedMembers().isEmpty()) {
1205 QString name = QString(
"Reimplemented ") + section.title();
1206 QString ref = registerRef(name.toLower());
1207 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(name) <<
"</h2>\n";
1208 generateSection(section.reimplementedMembers(), aggregate, marker);
1211 if (!section.inheritedMembers().isEmpty()) {
1213 generateSectionInheritedList(section, aggregate);
1219 if (needOtherSection) {
1220 out() <<
"<h3>Additional Inherited Members</h3>\n"
1223 for (
const auto §ion : summarySections) {
1224 if (section.members().isEmpty() && !section.inheritedMembers().isEmpty())
1225 generateSectionInheritedList(section, aggregate);
1230 if (aggregate
->doc().isEmpty()) {
1231 QString command =
"documentation";
1233 command = R"('\class' comment)";
1236 QStringLiteral(
"No %1 for '%2'").arg(command, aggregate->plainSignature()));
1239 generateExtractionMark(aggregate, DetailedDescriptionMark);
1240 out() <<
"<div class=\"descr\">\n"
1241 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1242 <<
"Detailed Description"
1245 out() <<
"</div>\n";
1246 generateAlsoList(aggregate, marker);
1247 generateExtractionMark(aggregate, EndMark);
1250 for (
const auto §ion : detailsSections) {
1251 bool headerGenerated =
false;
1252 if (section.isEmpty())
1255 const QList<Node *> &members = section.members();
1256 for (
const auto &member : members) {
1257 if (!headerGenerated) {
1258 if (!section.divClass().isEmpty())
1259 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1260 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1261 headerGenerated =
true;
1263 if (!member->isClassNode())
1264 generateDetailedMember(member, aggregate, marker);
1267 if (
const auto &attrs = getClassAttr(member,
""_L1); !attrs.isEmpty())
1268 out() <<
" class=\"%1\""_L1.arg(attrs);
1269 out() <<
"> class ";
1270 generateFullName(member, aggregate);
1272 generateBrief(member, marker, aggregate);
1275 if (headerGenerated && !section.divClass().isEmpty())
1276 out() <<
"</div>\n";
1278 generateFooter(aggregate);
1291 QString rawTitle = aggregate->plainName();
1292 QString fullTitle = aggregate->plainFullName();
1293 QString title = rawTitle +
" Proxy Page";
1294 generateHeader(title, aggregate, marker);
1295 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1296 generateBrief(aggregate, marker);
1297 for (
const auto §ion : summarySections) {
1298 if (!section.members().isEmpty()) {
1299 QString ref = registerRef(section.title().toLower());
1300 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1301 generateSection(section.members(), aggregate, marker);
1305 if (!aggregate
->doc().isEmpty()) {
1306 generateExtractionMark(aggregate, DetailedDescriptionMark);
1307 out() <<
"<div class=\"descr\">\n"
1308 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1309 <<
"Detailed Description"
1312 out() <<
"</div>\n";
1313 generateAlsoList(aggregate, marker);
1314 generateExtractionMark(aggregate, EndMark);
1317 for (
const auto §ion : detailsSections) {
1318 if (section.isEmpty())
1321 if (!section.divClass().isEmpty())
1322 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1323 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1325 const QList<Node *> &members = section.members();
1326 for (
const auto &member : members) {
1327 if (!member->isClassNode()) {
1328 generateDetailedMember(member, aggregate, marker);
1331 if (
const auto &attrs = getClassAttr(member,
""_L1); !attrs.isEmpty())
1332 out() <<
" class=\"%1\""_L1.arg(attrs);
1333 out() <<
"> class ";
1334 generateFullName(member, aggregate);
1336 generateBrief(member, marker, aggregate);
1339 if (!section.divClass().isEmpty())
1340 out() <<
"</div>\n";
1342 generateFooter(aggregate);
1346
1347
1348
1352 SubTitleSize subTitleSize = LargeSubTitle;
1353 QString htmlTitle = qcn->name();
1355 htmlTitle.append(
" QML Value Type");
1357 htmlTitle.append(
" QML Type");
1360 htmlTitle.append(
" (Singleton)"_L1);
1362 generateHeader(htmlTitle, qcn, marker);
1365 marker = CodeMarker::markerForLanguage(QLatin1String(
"QML"));
1366 generateTitle(htmlTitle,
Text() << qcn->subtitle(), subTitleSize, qcn, marker);
1367 generateBrief(qcn, marker);
1368 generateQmlRequisites(qcn, marker);
1372 out() <<
"<p><strong>Note:</strong> This type is a QML singleton. "_L1
1373 <<
"There is only one instance of this type in the QML engine.</p>\n"_L1;
1376 QString allQmlMembersLink;
1379 if (!qcn->isQmlBasicType())
1380 allQmlMembersLink = generateAllQmlMembersFile(sections, marker);
1381 QString obsoleteLink = generateObsoleteQmlMembersFile(sections, marker);
1382 if (!allQmlMembersLink.isEmpty() || !obsoleteLink.isEmpty()) {
1383 openUnorderedList();
1385 if (!allQmlMembersLink.isEmpty()) {
1386 out() <<
"<li><a href=\"" << allQmlMembersLink <<
"\">"
1387 <<
"List of all members, including inherited members</a></li>\n";
1389 if (!obsoleteLink.isEmpty()) {
1390 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1391 <<
"Deprecated members</a></li>\n";
1395 if (QString groups_text{groupReferenceText(qcn)}; !groups_text.isEmpty()) {
1396 openUnorderedList();
1398 out() <<
"<li>" << groups_text <<
"</li>\n";
1401 closeUnorderedList();
1404 for (
const auto §ion : qmlSummarySections) {
1405 if (!section.isEmpty()) {
1406 QString ref = registerRef(section.title().toLower());
1407 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1408 generateQmlSummary(section.members(), qcn, marker);
1412 generateExtractionMark(qcn, DetailedDescriptionMark);
1413 out() <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1414 <<
"Detailed Description"
1417 generateAlsoList(qcn, marker);
1418 generateExtractionMark(qcn, EndMark);
1421 for (
const auto §ion : qmlDetailsSections) {
1422 if (section.isEmpty())
1424 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1425 const QList<Node *> &members = section.members();
1426 for (
const auto member : members)
1427 generateDetailedQmlMember(member, qcn, marker);
1429 generateFooter(qcn);
1434
1435
1436
1439 generateHeader(pn->fullTitle(), pn, marker);
1441
1442
1443
1444 if ((pn->name() != QLatin1String(
"index.html")))
1445 generateTableOfContents(pn, marker,
nullptr);
1447 generateTitle(pn
->doc().title(),
Text() << pn->subtitle(), LargeSubTitle, pn, marker);
1449 generateBrief(pn, marker,
nullptr,
false);
1452 generateExtractionMark(pn, DetailedDescriptionMark);
1453 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1457 out() <<
"</div>\n";
1458 generateAlsoList(pn, marker);
1459 generateExtractionMark(pn, EndMark);
1465
1466
1469 SubTitleSize subTitleSize = LargeSubTitle;
1472 generateHeader(cn->fullTitle(), cn, marker);
1473 generateTableOfContents(cn, marker,
nullptr);
1474 generateTitle(cn
->doc().title(),
Text() << cn->subtitle(), subTitleSize, cn, marker);
1477 if (cn
->genus() != Genus::DOC && cn
->genus() != Genus::DontCare) {
1479 generateBrief(cn, marker);
1487 if (!nmm.isEmpty()) {
1488 ref = registerRef(
"namespaces");
1489 out() <<
"<h2 id=\"" << ref <<
"\">Namespaces</h2>\n";
1490 generateAnnotatedList(cn, marker, nmm.values());
1493 if (!nmm.isEmpty()) {
1494 ref = registerRef(
"classes");
1495 out() <<
"<h2 id=\"" << ref <<
"\">Classes</h2>\n";
1496 generateAnnotatedList(cn, marker, nmm.values());
1502 generateExtractionMark(cn, DetailedDescriptionMark);
1503 ref = registerRef(
"details");
1504 out() <<
"<div class=\"descr\">\n";
1505 out() <<
"<h2 id=\"" << ref <<
"\">"
1506 <<
"Detailed Description"
1509 generateExtractionMark(cn, DetailedDescriptionMark);
1510 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1515 out() <<
"</div>\n";
1516 generateAlsoList(cn, marker);
1517 generateExtractionMark(cn, EndMark);
1520 if (cn->isGroup() || cn->isQmlModule())
1521 generateAnnotatedList(cn, marker, cn->members());
1527
1528
1529
1530
1533 SubTitleSize subTitleSize = LargeSubTitle;
1534 QString fullTitle = cn->name();
1536 generateHeader(fullTitle, cn, marker);
1537 generateTitle(fullTitle,
Text() << cn->subtitle(), subTitleSize, cn, marker);
1540 brief <<
"Each function or type documented here is related to a class or "
1541 <<
"namespace that is documented in a different module. The reference "
1542 <<
"page for that class or namespace will link to the function or type "
1545 generateText(brief, cn, marker);
1549 for (
const auto &member : members)
1550 generateDetailedMember(member, cn, marker);
1556
1557
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585void HtmlGenerator::generateNavigationBar(
const QString &title,
const Node *node,
1586 CodeMarker *marker,
const QString &buildversion,
1589 if (m_noNavigationBar || node ==
nullptr)
1600 auto addNavItem = [&](
const QString &link,
const QString &title) {
1601 navigationbar << Atom(itemLeft) << Atom(
Atom::NavLink, link)
1608 auto addNavItemNode = [&](
const Node *node,
const QString &title) {
1609 navigationbar << Atom(itemLeft);
1610 addNodeLink(navigationbar, node, title);
1611 navigationbar << Atom(itemRight);
1615 const auto *moduleNode = m_qdb->getModuleNode(node);
1616 QString moduleState;
1617 if (moduleNode && !moduleNode->state().isEmpty())
1618 moduleState = QStringLiteral(
" (%1)").arg(moduleNode->state());
1620 if (m_hometitle == title)
1622 if (!m_homepage.isEmpty())
1623 addNavItem(m_homepage, m_hometitle);
1624 if (!m_landingpage.isEmpty() && m_landingtitle != title)
1625 addNavItem(m_landingpage, m_landingtitle);
1628 if (!m_cppclassespage.isEmpty() && !m_cppclassestitle.isEmpty())
1629 addNavItem(m_cppclassespage, m_cppclassestitle);
1630 if (!node->physicalModuleName().isEmpty()) {
1634 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_cppclassespage))
1635 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1637 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1639 if (!m_qmltypespage.isEmpty() && !m_qmltypestitle.isEmpty())
1640 addNavItem(m_qmltypespage, m_qmltypestitle);
1644 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_qmltypespage)) {
1645 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1647 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1650 auto currentNode{
static_cast<
const PageNode*>(node)};
1651 std::deque<
const Node *> navNodes;
1653 qsizetype navItems = 0;
1654 while (currentNode->navigationParent() && ++navItems < 16) {
1655 if (
std::find(navNodes.cbegin(), navNodes.cend(),
1656 currentNode->navigationParent()) == navNodes.cend())
1657 navNodes.push_front(currentNode->navigationParent());
1658 currentNode = currentNode->navigationParent();
1662 if (navNodes.empty()) {
1663 const QStringList groups =
static_cast<
const PageNode *>(node)->groupNames();
1664 for (
const auto &groupName : groups) {
1665 const auto *groupNode = m_qdb->findNodeByNameAndType(QStringList{groupName}, &Node::isGroup);
1666 if (groupNode && !groupNode->title().isEmpty()) {
1667 navNodes.push_front(groupNode);
1672 while (!navNodes.empty()) {
1673 if (navNodes.front()->isPageNode())
1674 addNavItemNode(navNodes.front(), navNodes.front()->title());
1675 navNodes.pop_front();
1679 navigationbar << Atom(itemLeft) << Atom(
Atom::String, title) << Atom(itemRight);
1683 generateText(navigationbar, node, marker);
1685 if (buildversion.isEmpty())
1691 out() <<
"</tr></table><table class=\"buildversion\"><tr>\n"
1692 << R"(<td id="buildversion" width="100%" align="right">)";
1694 out() <<
"<li id=\"buildversion\">";
1698 if (!m_landingpage.isEmpty() && m_landingtitle != title) {
1699 navigationbar << Atom(Atom::NavLink, m_landingpage)
1701 << Atom(Atom::String, buildversion)
1703 generateText(navigationbar, node, marker);
1705 out() << buildversion;
1715 out() <<
"<!DOCTYPE html>\n";
1716 out() << QString(
"<html lang=\"%1\">\n").arg(naturalLanguage);
1717 out() <<
"<head>\n";
1718 out() <<
" <meta charset=\"utf-8\">\n";
1723 out() <<
" <meta name=\"description\" content=\""
1724 << protectEnc(node->doc().briefText().toString())
1731 QStringList keywords;
1732 for (
const auto &kw : metaTags->values(u"keywords"_s))
1733 keywords << kw.split(
','_L1, Qt::SkipEmptyParts);
1735 if (!keywords.isEmpty()) {
1736 std::transform(keywords.begin(), keywords.end(), keywords.begin(),
1737 [](
const QString &k) {
return k.trimmed(); });
1738 out() <<
" <meta name=\"keywords\" content=\""
1739 << protectEnc(keywords.join(
','_L1))
1746 QString titleSuffix;
1747 if (!m_landingtitle.isEmpty()) {
1749 titleSuffix = m_landingtitle;
1750 }
else if (!m_hometitle.isEmpty()) {
1753 if (title != m_hometitle)
1754 titleSuffix = m_hometitle;
1757 titleSuffix = m_productName.isEmpty() ? m_project : m_productName;
1759 if (title == titleSuffix)
1760 titleSuffix.clear();
1762 out() <<
" <title>";
1763 if (!titleSuffix.isEmpty() && !title.isEmpty()) {
1764 out() <<
"%1 | %2"_L1.arg(protectEnc(title), titleSuffix);
1766 out() << protectEnc(title);
1771 QVersionNumber projectVersion = QVersionNumber::fromString(m_qdb->version());
1772 if (!projectVersion.isNull()) {
1773 QVersionNumber titleVersion;
1774 static const QRegularExpression re(QLatin1String(R"(\d+\.\d+)"));
1775 const QString &versionedTitle = titleSuffix.isEmpty() ? title : titleSuffix;
1776 auto match = re.match(versionedTitle);
1777 if (match.hasMatch())
1778 titleVersion = QVersionNumber::fromString(match.captured());
1779 if (titleVersion.isNull() || !titleVersion.isPrefixOf(projectVersion)) {
1781 if (!m_productName.isEmpty() && titleSuffix != m_productName)
1782 out() <<
" | %1"_L1.arg(m_productName);
1783 out() <<
" %1"_L1.arg(projectVersion.toString());
1786 out() <<
"</title>\n";
1789 out() << m_headerStyles;
1790 out() << m_headerScripts;
1791 out() << m_endHeader;
1793 out() << QString(m_postHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1794 bool usingTable = m_postHeader.trimmed().endsWith(QLatin1String(
"<tr>"));
1795 generateNavigationBar(title, node, marker, m_buildversion, usingTable);
1796 out() << QString(m_postPostHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1798 m_navigationLinks.clear();
1801 if (node && !node->links().empty()) {
1802 std::pair<QString, QString> linkPair;
1803 std::pair<QString, QString> anchorPair;
1804 const Node *linkNode;
1805 bool useSeparator =
false;
1807 if (node->links().contains(Node::PreviousLink)) {
1808 linkPair = node->links()[Node::PreviousLink];
1809 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1812 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1813 if (linkNode ==
nullptr || linkNode == node)
1814 anchorPair = linkPair;
1816 anchorPair = anchorForNode(linkNode);
1818 out() << R"( <link rel="prev" href=")" << anchorPair.first <<
"\" />\n";
1820 m_navigationLinks += R"(<a class="prevPage" href=")" + anchorPair.first +
"\">";
1821 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1822 m_navigationLinks += protect(anchorPair.second);
1824 m_navigationLinks += protect(linkPair.second);
1825 m_navigationLinks +=
"</a>\n";
1826 useSeparator = !m_navigationSeparator.isEmpty();
1828 if (node->links().contains(Node::NextLink)) {
1829 linkPair = node->links()[Node::NextLink];
1830 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1833 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1834 if (linkNode ==
nullptr || linkNode == node)
1835 anchorPair = linkPair;
1837 anchorPair = anchorForNode(linkNode);
1839 out() << R"( <link rel="next" href=")" << anchorPair.first <<
"\" />\n";
1842 m_navigationLinks += m_navigationSeparator;
1844 m_navigationLinks += R"(<a class="nextPage" href=")" + anchorPair.first +
"\">";
1845 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1846 m_navigationLinks += protect(anchorPair.second);
1848 m_navigationLinks += protect(linkPair.second);
1849 m_navigationLinks +=
"</a>\n";
1851 if (node->links().contains(Node::StartLink)) {
1852 linkPair = node->links()[Node::StartLink];
1853 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1856 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1857 if (linkNode ==
nullptr || linkNode == node)
1858 anchorPair =
std::move(linkPair);
1860 anchorPair = anchorForNode(linkNode);
1861 out() << R"( <link rel="start" href=")" << anchorPair.first <<
"\" />\n";
1865 if (node && !node->links().empty())
1866 out() <<
"<p class=\"naviNextPrevious headerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1870 SubTitleSize subTitleSize,
const Node *relative,
1873 out() << QString(m_prologue).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1876 attribute = R"( translate="no")";
1879 out() <<
"<h1 class=\"title\"" << attribute <<
">";
1880 generateText(title, relative, marker);
1885 if (subTitleSize == SmallSubTitle)
1886 out() <<
" class=\"small-subtitle\"" << attribute <<
">";
1888 out() <<
" class=\"subtitle\"" << attribute <<
">";
1889 generateText(subtitle, relative, marker);
1890 out() <<
"</span>\n";
1896 if (node && !node->links().empty())
1897 out() <<
"<p class=\"naviNextPrevious footerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1899 out() << QString(m_footer).replace(
"\\" +
COMMAND_VERSION, m_qdb->version())
1900 << QString(m_address).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1902 out() <<
"</body>\n";
1903 out() <<
"</html>\n";
1907
1908
1909
1912 QMap<QString, Text> requisites;
1915 const QString headerText =
"Header";
1916 const QString sinceText =
"Since";
1917 const QString inheritedByText =
"Inherited By";
1918 const QString inheritsText =
"Inherits";
1919 const QString nativeTypeText =
"In QML";
1920 const QString qtVariableText =
"qmake";
1921 const QString cmakeText =
"CMake";
1922 const QString statusText =
"Status";
1925 const QStringList requisiteorder { headerText, cmakeText, qtVariableText, sinceText,
1926 nativeTypeText, inheritsText, inheritedByText, statusText };
1928 addIncludeFileToMap(aggregate, requisites, text, headerText);
1929 addSinceToMap(aggregate, requisites, &text, sinceText);
1932 addCMakeInfoToMap(aggregate, requisites, &text, cmakeText);
1933 addQtVariableToMap(aggregate, requisites, &text, qtVariableText);
1937 auto *classe =
dynamic_cast<
ClassNode *>(aggregate);
1939 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1941 if (InclusionFilter::isIncluded(policy, context))
1942 addQmlNativeTypesToMap(requisites, &text, nativeTypeText, classe);
1945 addInheritsToMap(requisites, &text, inheritsText, classe);
1946 addInheritedByToMap(requisites, &text, inheritedByText, classe);
1950 addStatusToMap(aggregate, requisites, text, statusText);
1952 if (!requisites.isEmpty()) {
1954 generateTheTable(requisiteorder, requisites, aggregate, marker);
1959
1960
1961void HtmlGenerator::generateTheTable(
const QStringList &requisiteOrder,
1962 const QMap<QString, Text> &requisites,
1965 out() <<
"<div class=\"table\"><table class=\"alignedsummary requisites\" translate=\"no\">\n";
1967 for (
auto it = requisiteOrder.constBegin(); it != requisiteOrder.constEnd(); ++it) {
1969 if (requisites.contains(*it)) {
1971 <<
"<td class=\"memItemLeft rightAlign topAlign\"> " << *it
1973 "</td><td class=\"memItemRight bottomAlign\"> ";
1975 generateText(requisites.value(*it), aggregate, marker);
1976 out() <<
"</td></tr>\n";
1979 out() <<
"</table></div>\n";
1983
1984
1985
1986void HtmlGenerator::addInheritedByToMap(QMap<QString, Text> &requisites,
Text *text,
1987 const QString &inheritedByText,
ClassNode *classe)
1989 if (!classe->derivedClasses().isEmpty()) {
1992 int count = appendSortedNames(*text, classe, classe->derivedClasses());
1995 requisites.insert(inheritedByText, *text);
2000
2001
2002
2003void HtmlGenerator::addInheritsToMap(QMap<QString, Text> &requisites,
Text *text,
2004 const QString &inheritsText,
ClassNode *classe)
2006 if (!classe->baseClasses().isEmpty()) {
2009 const auto baseClasses = classe->baseClasses();
2010 for (
const auto &cls : baseClasses) {
2012 appendFullName(*text, cls.m_node, classe);
2014 if (cls.m_access == Access::Protected) {
2015 *text <<
" (protected)";
2016 }
else if (cls.m_access == Access::Private) {
2017 *text <<
" (private)";
2019 *text << Utilities::comma(index++, classe->baseClasses().size());
2024 requisites.insert(inheritsText, *text);
2029
2030
2031
2032void HtmlGenerator::addQmlNativeTypesToMap(QMap<QString, Text> &requisites,
Text *text,
2033 const QString &nativeTypeText,
ClassNode *classe)
const
2040 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2042 qsizetype index { 0 };
2044 for (
const auto &item : std::as_const(nativeTypes)) {
2045 addNodeLink(*text, item);
2046 *text << Utilities::comma(index++, nativeTypes.size());
2048 requisites.insert(nativeTypeText, *text);
2052
2053
2054
2056 Text *text,
const QString &CMakeInfo)
const
2058 if (!aggregate->physicalModuleName().isEmpty() && text !=
nullptr) {
2060 m_qdb->getCollectionNode(aggregate->physicalModuleName(), NodeType::Module);
2062 const auto result = cmakeRequisite(cn);
2075 requisites.insert(CMakeInfo, *text);
2080
2081
2082
2084 Text *text,
const QString &qtVariableText)
const
2086 if (!aggregate->physicalModuleName().isEmpty()) {
2088 m_qdb->getCollectionNode(aggregate->physicalModuleName(), NodeType::Module);
2090 if (cn && !cn->qtVariable().isEmpty()) {
2093 requisites.insert(qtVariableText, *text);
2099
2100
2101
2102
2104 Text *text,
const QString &sinceText)
const
2106 if (!aggregate->since().isEmpty() && text !=
nullptr) {
2109 requisites.insert(sinceText, *text);
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2125 Text &text,
const QString &statusText)
const
2127 auto status{formatStatus(aggregate, m_qdb)};
2133 spanClass = u"deprecated"_s;
2135 spanClass = Utilities::asAsciiPrintable(status.value());
2138 text << Atom(Atom::String, status.value())
2140 "class=\"status %1\""_L1.arg(spanClass))
2142 requisites.insert(statusText, text);
2146
2147
2148
2149
2151 QMap<QString, Text> &requisites,
Text& text,
2152 const QString &headerText)
2154 if (aggregate->includeFile()) {
2156 text << openCodeTag <<
"#include <%1>"_L1.arg(*aggregate->includeFile()) << closeCodeTag;
2157 requisites.insert(headerText, text);
2162
2163
2164
2170 QMap<QString, Text> requisites;
2173 const QString importText =
"Import Statement";
2174 const QString sinceText =
"Since";
2175 const QString inheritedByText =
"Inherited By";
2176 const QString inheritsText =
"Inherits";
2177 const QString nativeTypeText =
"In C++";
2178 const QString statusText =
"Status";
2181 QString logicalModuleVersion;
2186 bool generate_import =
true;
2188 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2192 if (generate_import) {
2196 requisites.insert(importText, text);
2199 qcn
->doc().location().warning(QStringLiteral(
"Could not resolve QML import statement for type '%1'").arg(qcn->name()),
2204 if (!qcn->since().isEmpty()) {
2207 requisites.insert(sinceText, text);
2212 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2216 addNodeLink(text, cn);
2217 requisites.insert(nativeTypeText, text);
2225 QStringList knownTypeNames{qcn->name()};
2227 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2235 knownTypeNames << base->name();
2238 addNodeLink(text, base);
2241 for (
const auto sub : std::as_const(subs)) {
2242 if (knownTypeNames.contains(sub->name())) {
2243 text << Atom(Atom::String,
" (%1)"_L1.arg(base->logicalModuleName()));
2248 requisites.insert(inheritsText, text);
2252 if (!subs.isEmpty()) {
2255 int count = appendSortedQmlNames(text, qcn, knownTypeNames, subs);
2258 requisites.insert(inheritedByText, text);
2262 addStatusToMap(qcn, requisites, text, statusText);
2265 const QStringList requisiteorder {
std::move(importText),
std::move(sinceText),
2266 std::move(nativeTypeText),
std::move(inheritsText),
2267 std::move(inheritedByText),
std::move(statusText)};
2269 if (!requisites.isEmpty())
2270 generateTheTable(requisiteorder, requisites, qcn, marker);
2282 QStringLiteral(
"'\\brief' statement does not end with a full stop."));
2284 generateExtractionMark(node, BriefMark);
2286 generateText(brief, node, marker);
2289 if (!relative || node == relative)
2290 out() <<
" <a href=\"#";
2292 out() <<
" <a href=\"" << linkForNode(node, relative) <<
'#';
2293 out() << registerRef(
"details") <<
"\">More...</a>";
2297 generateExtractionMark(node, EndMark);
2302
2303
2304
2310 toc = node
->doc().tableOfContents();
2311 if (tocDepth == 0 || (toc.isEmpty() && !sections && !node
->isModule())) {
2316 int sectionNumber = 1;
2317 int detailsBase = 0;
2320 m_inContents =
true;
2322 out() <<
"<div class=\"sidebar\">\n";
2323 out() <<
"<div class=\"toc\">\n";
2324 out() <<
"<h3 id=\"toc\">Contents</h3>\n";
2327 openUnorderedList();
2328 if (!
static_cast<
const CollectionNode *>(node)->noAutoList()) {
2330 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2331 << registerRef(
"namespaces") <<
"\">Namespaces</a></li>\n";
2334 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2335 << registerRef(
"classes") <<
"\">Classes</a></li>\n";
2338 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#" << registerRef(
"details")
2339 <<
"\">Detailed Description</a></li>\n";
2340 for (
const auto &entry : std::as_const(toc)) {
2341 if (entry->string().toInt() == 1) {
2347 for (
const auto §ion : *sections) {
2348 if (!section.members().isEmpty()) {
2349 openUnorderedList();
2350 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2351 << registerRef(section.plural()) <<
"\">" << section.title() <<
"</a></li>\n";
2353 if (!section.reimplementedMembers().isEmpty()) {
2354 openUnorderedList();
2355 QString ref = QString(
"Reimplemented ") + section.plural();
2356 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2357 << registerRef(ref.toLower()) <<
"\">"
2358 << QString(
"Reimplemented ") + section.title() <<
"</a></li>\n";
2362 openUnorderedList();
2363 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2364 << registerRef(
"details") <<
"\">Detailed Description</a></li>\n";
2366 for (
const auto &entry : toc) {
2367 if (entry->string().toInt() == 1) {
2374 for (
const auto &atom : toc) {
2375 sectionNumber = atom->string().toInt() + detailsBase;
2378 if (sectionNumber <= tocDepth || tocDepth < 0) {
2379 openUnorderedList();
2381 Text headingText = Text::sectionHeading(atom);
2382 out() <<
"<li class=\"level" << sectionNumber <<
"\">";
2383 out() <<
"<a href=\"" <<
'#' << Tree::refForAtom(atom) <<
"\">";
2384 generateAtomList(headingText.firstAtom(), node, marker,
true, numAtoms);
2385 out() <<
"</a></li>\n";
2388 closeUnorderedList();
2389 out() <<
"</div>\n";
2390 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2391 out() <<
"</div>\n";
2392 m_inContents =
false;
2397
2398
2401 out() <<
"<div class=\"sidebar\">";
2402 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2403 out() <<
"</div>\n";
2412 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2413 beginSubPage(aggregate, fileName);
2414 QString title =
"List of All Members for " + aggregate->plainFullName();
2415 generateHeader(title, aggregate, marker);
2417 generateTitle(title,
Text(), SmallSubTitle, aggregate, marker);
2418 out() <<
"<p>This is the complete list of members for ";
2419 generateFullName(aggregate,
nullptr);
2420 out() <<
", including inherited members.</p>\n";
2422 generateSectionList(section, aggregate, marker);
2430
2431
2432
2433
2434
2442 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2443 beginSubPage(aggregate, fileName);
2444 QString title =
"List of All Members for " + aggregate->name();
2445 generateHeader(title, aggregate, marker);
2447 generateTitle(title,
Text(), SmallSubTitle, aggregate, marker);
2448 out() <<
"<p>This is the complete list of members for ";
2449 generateFullName(aggregate,
nullptr);
2450 out() <<
", including inherited members.</p>\n";
2453 for (
int i = 0; i < cknl.size(); i++) {
2454 const auto &ckn = cknl[i];
2457 if (nodes.isEmpty())
2460 out() <<
"<p>The following members are inherited from ";
2461 generateFullName(qcn,
nullptr);
2464 openUnorderedList();
2465 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2466 for (
int j = 0; j < nodes.size(); j++) {
2467 Node *node = nodes[j];
2474 std::function<
void(
Node *)> generate = [&](Node *n) {
2475 out() <<
"<li class=\"fn\" translate=\"no\">";
2476 generateQmlItem(n, aggregate, marker,
true);
2477 if (n->isQmlProperty()) {
2478 auto qpn =
static_cast<QmlPropertyNode *>(n);
2479 QStringList hints = qpn->hints();
2480 if (qpn->isAttached())
2481 hints <<
"attached"_L1;
2482 if (!hints.isEmpty())
2483 out() <<
" [" << hints.join(
' '_L1) <<
"]";
2484 }
else if (n->isAttached()) {
2486 out() <<
" [attached]";
2489 if (n->isPropertyGroup()) {
2491 const QList<Node *> &collective =
2492 static_cast<SharedCommentNode *>(n)->collective();
2493 std::for_each(collective.begin(), collective.end(), generate);
2500 closeUnorderedList();
2517 QString title =
"Obsolete Members for " + aggregate->plainFullName();
2518 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2520 beginSubPage(aggregate, fileName);
2521 generateHeader(title, aggregate, marker);
2523 generateTitle(title,
Text(), SmallSubTitle, aggregate, marker);
2525 out() <<
"<p><b>The following members of class "
2526 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\" translate=\"no\">"
2527 << protectEnc(aggregate->name()) <<
"</a>"
2528 <<
" are deprecated.</b> "
2529 <<
"They are provided to keep old source code working. "
2530 <<
"We strongly advise against using them in new code.</p>\n";
2532 for (
const auto §ion : summary_spv) {
2533 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2534 generateSectionList(*section, aggregate, marker,
true);
2537 for (
const auto §ion : details_spv) {
2538 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2540 const NodeVector &members = section->obsoleteMembers();
2541 for (
const auto &member : members)
2542 generateDetailedMember(member, aggregate, marker);
2551
2552
2553
2554
2563 QString title =
"Obsolete Members for " + aggregate->name();
2564 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2566 beginSubPage(aggregate, fileName);
2567 generateHeader(title, aggregate, marker);
2569 generateTitle(title,
Text(), SmallSubTitle, aggregate, marker);
2571 out() <<
"<p><b>The following members of QML type "
2572 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\">"
2573 << protectEnc(aggregate->name()) <<
"</a>"
2574 <<
" are deprecated.</b> "
2575 <<
"They are provided to keep old source code working. "
2576 <<
"We strongly advise against using them in new code.</p>\n";
2578 for (
const auto §ion : summary_spv) {
2579 QString ref = registerRef(section->title().toLower());
2580 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section->title()) <<
"</h2>\n";
2581 generateQmlSummary(section->obsoleteMembers(), aggregate, marker);
2584 for (
const auto §ion : details_spv) {
2585 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2586 const NodeVector &members = section->obsoleteMembers();
2587 for (
const auto &member : members) {
2588 generateDetailedQmlMember(member, aggregate, marker);
2600 if (classMap.isEmpty())
2604 for (
const auto &it : classMap) {
2605 auto *classe =
static_cast<ClassNode *>(it);
2606 if (classe->baseClasses().isEmpty())
2607 topLevel.insert(classe->name(), classe);
2610 QStack<NodeMap> stack;
2611 stack.push(topLevel);
2614 while (!stack.isEmpty()) {
2615 if (stack.top().isEmpty()) {
2621 generateFullName(child, relative);
2623 stack.top().erase(stack.top().begin());
2626 const auto derivedClasses = child->derivedClasses();
2627 for (
const RelatedClass &d : derivedClasses) {
2628 if (d.m_node && d.m_node->isInAPI())
2629 newTop.insert(d.m_node->name(), d.m_node);
2631 if (!newTop.isEmpty()) {
2640
2641
2642
2644 const NodeList &unsortedNodes, Qt::SortOrder sortOrder)
2646 if (unsortedNodes.isEmpty() || relative ==
nullptr)
2650 bool allInternal =
true;
2651 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2652 for (
auto *node : unsortedNodes) {
2653 const NodeContext context = node->createContext();
2654 if (InclusionFilter::isIncluded(policy, context) && !node->isDeprecated()) {
2655 allInternal =
false;
2656 nmm.insert(node->fullName(relative), node);
2661 out() <<
"<div class=\"table\"><table class=\"annotated\">\n";
2665 if (sortOrder == Qt::DescendingOrder)
2670 for (
const auto *node : std::as_const(nodes)) {
2672 out() <<
"<tr class=\"odd topAlign\">";
2674 out() <<
"<tr class=\"even topAlign\">";
2675 out() <<
"<td class=\"tblName\" translate=\"no\"><p>";
2676 generateFullName(node, relative);
2677 out() <<
"</p></td>";
2679 if (!node->isTextPageNode()) {
2680 Text brief = node->doc().trimmedBriefText(node->name());
2681 if (!brief.isEmpty()) {
2682 out() <<
"<td class=\"tblDescr\"><p>";
2683 generateText(brief, node, marker);
2684 out() <<
"</p></td>";
2685 }
else if (!node->reconstitutedBrief().isEmpty()) {
2686 out() <<
"<td class=\"tblDescr\"><p>";
2687 out() << node->reconstitutedBrief();
2688 out() <<
"</p></td>";
2691 out() <<
"<td class=\"tblDescr\"><p>";
2692 if (!node->reconstitutedBrief().isEmpty()) {
2693 out() << node->reconstitutedBrief();
2695 out() << protectEnc(node->doc().briefText().toString());
2696 out() <<
"</p></td>";
2700 out() <<
"</table></div>\n";
2704
2705
2706
2710 const auto &uniqueKeys = nmm.uniqueKeys();
2711 for (
const QString &name : uniqueKeys) {
2712 if (!name.isEmpty()) {
2713 out() <<
"<h2 id=\"" << registerRef(name.toLower()) <<
"\">" << protectEnc(name)
2716 generateAnnotatedList(relative, marker, nmm.values(name));
2721
2722
2723
2724
2725
2726
2727
2728
2729
2732 const QString &commonPrefix)
2737 const int NumParagraphs = 37;
2738 qsizetype commonPrefixLen = commonPrefix.size();
2741
2742
2743
2744
2745
2747 QString paragraphName[NumParagraphs + 1];
2748 QSet<
char> usedParagraphNames;
2750 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
2751 QStringList pieces = c.key().split(
"::");
2752 int idx = commonPrefixLen;
2753 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
2755 QString last = pieces.last().toLower();
2756 QString key = last.mid(idx);
2758 int paragraphNr = NumParagraphs - 1;
2760 if (key[0].digitValue() != -1) {
2761 paragraphNr = key[0].digitValue();
2762 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
2763 paragraphNr = 10 + key[0].unicode() -
'a';
2766 paragraphName[paragraphNr] = key[0].toUpper();
2767 usedParagraphNames.insert(key[0].toLower().cell());
2768 paragraph[paragraphNr].insert(last, c.value());
2772
2773
2774
2775
2776
2777
2778
2779 qsizetype paragraphOffset[NumParagraphs + 1];
2780 paragraphOffset[0] = 0;
2781 for (
int i = 0; i < NumParagraphs; i++)
2782 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
2785
2786
2787 if (includeAlphabet) {
2788 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2789 for (
int i = 0; i < 26; i++) {
2791 if (usedParagraphNames.contains(
char(
'a' + i)))
2792 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2794 out() <<
"</b></p>\n";
2798
2799
2800 out() <<
"<div class=\"flowListDiv\" translate=\"no\">\n";
2804 QHash<QString,
int> nameOccurrences;
2805 for (
const auto &[key, node] : nmm.asKeyValueRange()) {
2806 QStringList pieces{node->fullName(relative).split(
"::"_L1)};
2807 const QString &name{pieces.last()};
2808 nameOccurrences[name]++;
2812 int curParOffset = 0;
2814 for (
int i = 0; i < nmm.size(); i++) {
2815 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
2821
2822
2823 if (curParOffset == 0) {
2826 if (++m_numTableRows % 2 == 1)
2827 out() <<
"<dl class=\"flowList odd\">";
2829 out() <<
"<dl class=\"flowList even\">";
2830 out() <<
"<dt class=\"alphaChar\"";
2831 if (includeAlphabet)
2832 out() << QString(
" id=\"%1\"").arg(paragraphName[curParNr][0].toLower());
2833 out() <<
"><b>" << paragraphName[curParNr] <<
"</b></dt>\n";
2837
2838
2840 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
2841 NodeMultiMap::Iterator it;
2842 NodeMultiMap::Iterator next;
2843 it = paragraph[curParNr].begin();
2844 for (
int j = 0; j < curParOffset; j++)
2849
2850
2851
2852 out() <<
"<a href=\"" << linkForNode(it.value(), relative) <<
"\">";
2854 QString fileName = fileBase(it.value()) +
"-obsolete." + fileExtension();
2856 if (useOutputSubdirs())
2857 link =
"../%1/"_L1.arg(it.value()->tree()->physicalModuleName());
2859 out() <<
"<a href=\"" << link <<
"\">";
2862 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
2863 const auto &name{pieces.last()};
2866 if (nameOccurrences[name] > 1) {
2867 const QString moduleName = it.value()->isQmlNode() ? it.value()->logicalModuleName()
2868 : it.value()->tree()->camelCaseModuleName();
2869 pieces.last().append(
": %1"_L1.arg(moduleName));
2872 out() << protectEnc(pieces.last());
2874 if (pieces.size() > 1) {
2876 generateFullName(it.value()->parent(), relative);
2886 out() <<
"</div>\n";
2891 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2892 for (
int i = 0; i < 26; i++) {
2894 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2896 out() <<
"</b></p>\n";
2898 char nextLetter =
'a';
2900 out() <<
"<ul translate=\"no\">\n";
2901 NodeMapMap &funcIndex = m_qdb->getFunctionIndex();
2902 for (
auto fnMap = funcIndex.constBegin(); fnMap != funcIndex.constEnd(); ++fnMap) {
2903 const QString &key = fnMap.key();
2904 const QChar firstLetter = key.isEmpty() ? QChar(
'A') : key.front();
2905 Q_ASSERT_X(firstLetter.unicode() < 256,
"generateFunctionIndex",
2906 "Only valid C++ identifiers were expected");
2907 const char currentLetter = firstLetter.isLower() ? firstLetter.unicode() : nextLetter - 1;
2909 if (currentLetter < nextLetter) {
2913 while (nextLetter < currentLetter)
2914 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2915 Q_ASSERT(nextLetter == currentLetter);
2916 out() << QStringLiteral(
"<li id=\"%1\">").arg(nextLetter++);
2918 out() << protectEnc(key) <<
':';
2920 for (
auto it = (*fnMap).constBegin(); it != (*fnMap).constEnd(); ++it) {
2922 generateFullName((*it)->parent(), relative, *it);
2926 while (nextLetter <=
'z')
2927 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2934 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
2935 Text text = it.key();
2936 generateText(text, relative, marker);
2940 generateFullName(it.value(), relative);
2943 }
while (it != legaleseTexts.constEnd() && it.key() == text);
2951 QString marked = marker->markedUpQmlItem(node, summary);
2952 marked.replace(
"@param>",
"i>");
2954 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
2955 .arg(summary ?
"summary"_L1 :
"details"_L1));
2956 marked.replace(
"</@extra>",
"</code>");
2960 marked.remove(
"<@name>");
2961 marked.remove(
"</@name>");
2962 marked.remove(
"<@type>");
2963 marked.remove(
"</@type>");
2965 out() << highlightedCode(marked, relative,
false, Genus::QML);
2969
2970
2971
2972
2973
2974
2975
2978 m_qdb->mergeCollections(cn);
2983 if (sortOrder == Qt::DescendingOrder)
2988 for (
const auto *node : std::as_const(members)) {
2989 out() <<
"<li translate=\"no\">";
2990 generateFullName(node,
nullptr);
2998 const QString &selector, Qt::SortOrder sortOrder)
3002 if (selector == QLatin1String(
"overviews"))
3004 else if (selector == QLatin1String(
"cpp-modules"))
3006 else if (selector == QLatin1String(
"qml-modules"))
3010 m_qdb->mergeCollections(type, cnm, relative);
3011 const auto collectionList = cnm.values();
3012 nodeList.reserve(collectionList.size());
3013 for (
auto *collectionNode : collectionList)
3014 nodeList.append(collectionNode);
3015 generateAnnotatedList(relative, marker, nodeList, sortOrder);
3018
3019
3020
3021
3024 QStringLiteral(
"\\generatelist {%1} is only allowed in \\group, "
3025 "\\module and \\qmlmodule comments.")
3029 auto *node =
const_cast<
Node *>(relative);
3030 auto *collectionNode =
static_cast<CollectionNode *>(node);
3031 if (!collectionNode)
3033 m_qdb->mergeCollections(collectionNode);
3034 generateAnnotatedList(collectionNode, marker, collectionNode->members(), sortOrder);
3040 bool alignNames =
true;
3041 if (!nv.isEmpty()) {
3042 bool twoColumn =
false;
3043 if (nv.first()->isProperty()) {
3044 twoColumn = (nv.size() >= 5);
3048 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3051 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3052 <<
"<tr><td class=\"topAlign\">";
3057 for (
const auto &member : nv) {
3060 out() <<
"<tr><td class=\"memItemLeft rightAlign topAlign\"> ";
3062 if (twoColumn && i == (nv.size() + 1) / 2)
3063 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3064 out() <<
"<li class=\"fn\" translate=\"no\">";
3067 generateSynopsis(member, relative, marker, Section::Summary, alignNames);
3069 out() <<
"</td></tr>\n";
3075 out() <<
"</table></div>\n";
3079 out() <<
"</td></tr>\n</table></div>\n";
3087 bool alignNames =
true;
3090 if (!members.isEmpty()) {
3091 bool hasPrivateSignals =
false;
3092 bool isInvokable =
false;
3093 bool twoColumn =
false;
3096 twoColumn = (members.size() >= 16);
3097 }
else if (members.first()->isProperty()) {
3098 twoColumn = (members.size() >= 5);
3102 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3105 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3106 <<
"<tr><td class=\"topAlign\">";
3111 for (
const auto &member : members) {
3114 if (member->name().isEmpty())
3118 out() <<
"<tr><td class=\"memItemLeft topAlign rightAlign\"> ";
3120 if (twoColumn && i == (members.size() + 1) / 2)
3121 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3122 out() <<
"<li class=\"fn\" translate=\"no\">";
3125 generateSynopsis(member, relative, marker, section.style(), alignNames);
3126 if (member->isFunction()) {
3127 const auto *fn =
static_cast<
const FunctionNode *>(member);
3128 if (fn->isPrivateSignal()) {
3129 hasPrivateSignals =
true;
3131 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3132 }
else if (fn->isInvokable()) {
3135 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3139 out() <<
"</td></tr>\n";
3145 out() <<
"</table></div>\n";
3149 out() <<
"</td></tr>\n</table></div>\n";
3152 if (hasPrivateSignals)
3160 && !section.inheritedMembers().isEmpty()) {
3162 generateSectionInheritedList(section, relative);
3169 const QList<std::pair<Aggregate *,
int>> &inheritedMembers = section.inheritedMembers();
3170 for (
const auto &member : inheritedMembers) {
3171 out() <<
"<li class=\"fn\" translate=\"no\">";
3172 out() << member.second <<
' ';
3173 if (member.second == 1) {
3174 out() << section.singular();
3176 out() << section.plural();
3178 out() <<
" inherited from <a href=\"" << fileName(member.first) <<
'#'
3179 << Generator::cleanRef(section.title().toLower()) <<
"\">"
3180 << protectEnc(member.first->plainFullName(relative)) <<
"</a></li>\n";
3187 QString marked = marker->markedUpSynopsis(node, relative, style);
3188 marked.replace(
"@param>",
"i>");
3191 marked.remove(
"<@name>");
3192 marked.remove(
"</@name>");
3196 static const QRegularExpression extraRegExp(
"<@extra>.*</@extra>",
3197 QRegularExpression::InvertedGreedinessOption);
3198 marked.remove(extraRegExp);
3200 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
3201 .arg(style == Section::Summary ?
"summary"_L1 :
"details"_L1));
3202 marked.replace(
"</@extra>",
"</code>");
3206 marked.remove(
"<@type>");
3207 marked.remove(
"</@type>");
3210 out() << highlightedCode(marked, relative, alignNames);
3213QString
HtmlGenerator::highlightedCode(
const QString &markedCode,
const Node *relative,
3214 bool alignNames, Genus genus)
3216 QString src = markedCode;
3218 html.reserve(src.size());
3222 const QChar charLangle =
'<';
3223 const QChar charAt =
'@';
3225 static const QString typeTag(
"type");
3226 static const QString headerTag(
"headerfile");
3227 static const QString funcTag(
"func");
3228 static const QString linkTag(
"link");
3229 static const QString extrefTag(
"extref");
3232 static const QHash<QString, QString> extrefUrls = {
3233 {
"cpp-explicitly-defaulted"_L1,
3234 "https://en.cppreference.com/w/cpp/language/function#Defaulted_functions"_L1},
3235 {
"cpp-deleted-functions"_L1,
3236 "https://en.cppreference.com/w/cpp/language/function#Deleted_functions"_L1},
3243 for (
int i = 0, srcSize = src.size(); i < srcSize;) {
3244 if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
3245 if (alignNames && !done) {
3246 html += QLatin1String(
"</td><td class=\"memItemRight bottomAlign\">");
3250 if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) {
3251 html += QLatin1String(
"<b>");
3252 const Node *n =
static_cast<
const Node*>(Utilities::nodeForString(par1.toString()));
3253 QString link = linkForNode(n, relative);
3254 addLink(link, arg, &html);
3255 html += QLatin1String(
"</b>");
3256 }
else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
3257 const FunctionNode *fn = m_qdb->findFunctionNode(par1.toString(), relative, genus);
3258 QString link = linkForNode(fn, relative);
3259 addLink(link, arg, &html);
3260 par1 = QStringView();
3261 }
else if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
3262 par1 = QStringView();
3263 const Node *n = m_qdb->findTypeNode(arg.toString(), relative, genus);
3264 html += QLatin1String(
"<span class=\"type\">");
3267 addLink(linkForNode(n, relative), arg, &html);
3271 addLink(linkForNode(n, relative), arg, &html);
3272 html += QLatin1String(
"</span>");
3273 }
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
3274 par1 = QStringView();
3275 if (arg.startsWith(QLatin1Char(
'&')))
3278 const Node *n = m_qdb->findNodeForInclude(QStringList(arg.toString()));
3279 if (n && n != relative)
3280 addLink(linkForNode(n, relative), arg, &html);
3284 }
else if (parseArg(src, extrefTag, &i, srcSize, &arg, &par1)) {
3285 QString url = extrefUrls.value(par1.toString());
3287 addLink(url, arg, &html);
3295 html += src.at(i++);
3304 html.reserve(src.size());
3307 QLatin1StringView tag;
3308 QLatin1StringView span;
3310 static constexpr SpanTag spanTags[] = {
3311 {
"comment>"_L1,
"<span class=\"comment\">"_L1},
3312 {
"preprocessor>"_L1,
"<span class=\"preprocessor\">"_L1},
3313 {
"string>"_L1,
"<span class=\"string\">"_L1},
3314 {
"char>"_L1,
"<span class=\"char\">"_L1},
3315 {
"number>"_L1,
"<span class=\"number\">"_L1},
3316 {
"op>"_L1,
"<span class=\"operator\">"_L1},
3317 {
"type>"_L1,
"<span class=\"type\">"_L1},
3318 {
"name>"_L1,
"<span class=\"name\">"_L1},
3319 {
"keyword>"_L1,
"<span class=\"keyword\">"_L1},
3320 {
"template-block>"_L1,
"<span class=\"template-block\">"_L1},
3324 const qsizetype n = src.size();
3325 const QStringView sv(src);
3327 if (sv.at(i) ==
'<'_L1) {
3328 if (i + 1 < n && sv.at(i + 1) ==
'@'_L1) {
3330 bool handled =
false;
3331 for (
const auto &st : spanTags) {
3332 if (i + st.tag.size() <= n
3333 && st.tag == sv.sliced(i, st.tag.size())) {
3342 while (i < n && sv.at(i) !=
'>'_L1)
3348 }
else if (i + 2 < n && sv.at(i + 1) ==
'/'_L1 && sv.at(i + 2) ==
'@'_L1) {
3350 bool handled =
false;
3351 for (
const auto &st : spanTags) {
3352 if (i + st.tag.size() <= n
3353 && st.tag == sv.sliced(i, st.tag.size())) {
3354 html +=
"</span>"_L1;
3362 while (i < n && sv.at(i) !=
'>'_L1)
3380 if (m_linkNode && m_linkNode->isFunction()) {
3382 if (match.hasMatch()) {
3384 qsizetype leftParenLoc = match.capturedStart(1);
3385 out() << protectEnc(atom->string().left(leftParenLoc));
3387 out() << protectEnc(atom->string().mid(leftParenLoc));
3391 out() << protectEnc(atom->string());
3396 return protect(string);
3401 if (string.isEmpty())
3405 if (html.isEmpty()) {
3412 qsizetype n = string.size();
3414 for (
int i = 0; i < n; ++i) {
3415 QChar ch = string.at(i);
3417 if (ch == QLatin1Char(
'&')) {
3419 }
else if (ch == QLatin1Char(
'<')) {
3421 }
else if (ch == QLatin1Char(
'>')) {
3423 }
else if (ch == QChar(8211)) {
3425 }
else if (ch == QChar(8212)) {
3427 }
else if (ch == QLatin1Char(
'"')) {
3430 if (!html.isEmpty())
3435 if (!html.isEmpty())
3444 QString result = Generator::fileBase(node);
3446 result += QLatin1String(
"-obsolete");
3453 return node->name();
3454 return Generator::fileName(node);
3458 const Node *actualNode)
3460 if (actualNode ==
nullptr)
3461 actualNode = apparentNode;
3462 bool link = !linkForNode(actualNode, relative).isEmpty();
3464 out() <<
"<a href=\"" << linkForNode(actualNode, relative);
3466 out() <<
"\" class=\"obsolete";
3469 out() << protectEnc(apparentNode->fullName(relative));
3475
3476
3477
3484 const auto srcLink = Config::instance().getSourceLink();
3485 if (!srcLink.enabled)
3490 if (loc
.isEmpty() || srcLink.baseUrl.isEmpty() || srcLink.rootPath.isEmpty())
3493 QString srcUrl{srcLink.baseUrl};
3494 if (!srcUrl.contains(
'\1'_L1)) {
3495 if (!srcUrl.endsWith(
'/'_L1))
3500 QDir rootDir{srcLink.rootPath};
3501 srcUrl.replace(
'\1'_L1, rootDir.relativeFilePath(loc.filePath()));
3502 srcUrl.replace(
'\2'_L1, QString::number(loc.lineNo()));
3503 const auto &description{
"View declaration of this %1"_L1.arg(node->nodeTypeString())};
3504 out() <<
"<a class=\"srclink\" href=\"%1\" title=\"%2\">%3</a>"_L1
3505 .arg(srcUrl, description, srcLink.linkText);
3512 generateExtractionMark(node, MemberMark);
3513 QString nodeRef =
nullptr;
3516 const QList<Node *> &collective = scn->collective();
3517 if (collective.size() > 1)
3518 out() <<
"<div class=\"fngroup\">\n";
3519 for (
const auto *sharedNode : collective) {
3520 out() << headingStart.arg(getClassAttr(sharedNode,
"fn fngroupitem"_L1),
3521 refForNode(sharedNode));
3522 generateSynopsis(sharedNode, relative, marker, Section::Details);
3523 generateSourceLink(sharedNode);
3524 out() << headingEnd;
3526 if (collective.size() > 1)
3530 if (node->isEnumType(Genus::CPP) && (etn =
static_cast<
const EnumNode *>(node))->flagsType()) {
3531 out() << headingStart.arg(getClassAttr(node,
"flags"_L1), refForNode(node));
3535 generateSourceLink(node);
3536 out() << headingEnd;
3538 out() << headingStart.arg(getClassAttr(node,
"fn"_L1), refForNode(node));
3540 generateSourceLink(node);
3541 out() << headingEnd;
3548 const auto *func =
static_cast<
const FunctionNode *>(node);
3549 if (func->hasOverloads() && (func->isSignal() || func->isSlot()))
3558 const auto property =
static_cast<
const PropertyNode *>(node);
3568 out() <<
"<p><b>Access functions:</b></p>\n";
3569 generateSectionList(section, node, marker);
3576 out() <<
"<p><b>Notifier signal:</b></p>\n";
3577 generateSectionList(notifiers, node, marker);
3581 const auto *enumTypeNode =
static_cast<
const EnumNode *>(node);
3582 if (enumTypeNode->flagsType()) {
3583 out() <<
"<p>The " << protectEnc(enumTypeNode->flagsType()->name())
3584 <<
" type is a typedef for "
3585 <<
"<a href=\"" << m_qflagsHref <<
"\">QFlags</a><"
3586 << protectEnc(enumTypeNode->name()) <<
">. It stores an OR combination of "
3587 << protectEnc(enumTypeNode->name()) <<
" values.</p>\n";
3590 generateAlsoList(node, marker);
3591 generateExtractionMark(node, EndMark);
3595
3596
3597
3598
3603 m_linkNode =
nullptr;
3605 if (!m_link.isEmpty())
3606 out() <<
"<a href=\"" << m_link <<
"\" translate=\"no\">";
3614 if (m_link.isEmpty())
3617 const QString &translate_attr =
3618 (node && isApiGenus(node->genus())) ?
" translate=\"no\""_L1 :
""_L1;
3620 if (node ==
nullptr || (relative !=
nullptr && node->status() == relative->status()))
3621 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3622 else if (node->isDeprecated())
3623 out() <<
"<a href=\"" << m_link <<
"\" class=\"obsolete\"%1>"_L1.arg(translate_attr);
3625 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3634 m_linkNode =
nullptr;
3636 if (!m_link.isEmpty())
3641
3642
3643
3647 if (!members.isEmpty()) {
3649 for (
const auto &member : members) {
3650 out() <<
"<li class=\"fn\" translate=\"no\">";
3651 generateQmlItem(member, relative, marker,
true);
3652 if (member->isPropertyGroup()) {
3653 const auto *scn =
static_cast<
const SharedCommentNode *>(member);
3654 if (scn->count() > 0) {
3656 const QList<Node *> &sharedNodes = scn->collective();
3657 for (
const auto &node : sharedNodes) {
3658 if (node->isQmlProperty()) {
3659 out() <<
"<li class=\"fn\" translate=\"no\">";
3660 generateQmlItem(node, relative, marker,
true);
3674
3675
3678 out() << headingStart.arg(getClassAttr(scn,
"fn qml-member qml-property-group"_L1),
3680 <<
"<b>" << scn->name() <<
" group</b>"
3685
3686
3687
3691 generateExtractionMark(node, MemberMark);
3693 auto generateQmlProperty = [&](
Node *n,
bool isGroupItem =
false) {
3694 const auto cssClasses = isGroupItem ?
"fn qml-member qml-property fngroupitem"_L1 :
"fn qml-member qml-property"_L1;
3695 out() << headingStart.arg(getClassAttr(n, cssClasses), refForNode(n));
3696 generateQmlItem(n, relative, marker,
false);
3697 generateSourceLink(n);
3698 out() << headingEnd;
3701 auto generateQmlMethod = [&](
Node *n,
bool isGroupItem =
false) {
3702 const auto cssClasses = isGroupItem ?
"fn qml-member qml-method fngroupitem"_L1 :
"fn qml-member qml-method"_L1;
3703 out() << headingStart.arg(getClassAttr(n, cssClasses), refForNode(n));
3705 generateSourceLink(n);
3706 out() << headingEnd;
3710 auto *scn =
static_cast<
const SharedCommentNode *>(node);
3711 const auto shared = scn->collective();
3713 if (scn->isPropertyGroup() && !scn->name().isEmpty())
3714 emitGroupHeader(scn);
3716 const bool isGroup = shared.size() > 1;
3719 out() <<
"<div class=\"fngroup\">\n"_L1;
3721 for (
auto *child : std::as_const(shared)) {
3722 if (child->isQmlProperty())
3723 generateQmlProperty(child, isGroup);
3725 generateQmlMethod(child, isGroup);
3729 out() <<
"</div>"_L1;
3732 generateQmlProperty(node);
3734 generateQmlMethod(node);
3741 generateAlsoList(node, marker);
3742 generateExtractionMark(node, EndMark);
3745void HtmlGenerator::generateExtractionMark(
const Node *node, ExtractionMarkType markType)
3747 if (markType != EndMark) {
3748 out() <<
"<!-- $$$" + node->name();
3749 if (markType == MemberMark) {
3751 const auto *func =
static_cast<
const FunctionNode *>(node);
3752 if (!func->hasAssociatedProperties()) {
3753 if (func->overloadNumber() == 0)
3754 out() <<
"[overload1]";
3755 out() <<
"$$$" + func->name() + func->parameters().rawSignature().remove(
' ');
3759 const auto *prop =
static_cast<
const PropertyNode *>(node);
3760 const NodeList &list = prop->functions();
3761 for (
const auto *propFuncNode : list) {
3762 if (propFuncNode->isFunction()) {
3763 const auto *func =
static_cast<
const FunctionNode *>(propFuncNode);
3764 out() <<
"$$$" + func->name()
3765 + func->parameters().rawSignature().remove(
' ');
3769 const auto *enumNode =
static_cast<
const EnumNode *>(node);
3770 const auto &items = enumNode->items();
3771 for (
const auto &item : items)
3772 out() <<
"$$$" + item.name();
3774 }
else if (markType == BriefMark) {
3776 }
else if (markType == DetailedDescriptionMark) {
3777 out() <<
"-description";
3781 out() <<
"<!-- @@@" + node->name() +
" -->\n";
#define ATOM_FORMATTING_TELETYPE
#define ATOM_LIST_LOWERALPHA
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_LIST_UPPERALPHA
#define ATOM_FORMATTING_NOTRANSLATE
#define ATOM_LIST_LOWERROMAN
#define ATOM_FORMATTING_SPAN
#define ATOM_FORMATTING_SUBSCRIPT
#define ATOM_FORMATTING_BOLD
#define ATOM_FORMATTING_TRADEMARK
#define ATOM_FORMATTING_ITALIC
#define ATOM_LIST_UPPERROMAN
#define ATOM_FORMATTING_LINK
#define ATOM_FORMATTING_SUPERSCRIPT
#define ATOM_FORMATTING_INDEX
#define ATOM_FORMATTING_UICONTROL
#define ATOM_FORMATTING_PARAMETER
The Atom class is the fundamental unit for representing documents internally.
AtomType type() const
Return the type of this atom.
AtomType
\value AnnotatedList \value AutoLink \value BaseName \value BriefLeft \value BriefRight \value C \val...
const Atom * next() const
Return the next atom in the atom list.
The ClassNode represents a C++ class.
virtual Atom::AtomType atomType() const
A class for holding the members of a collection of doc pages.
const NodeList & members() const
bool wasSeen() const override
Returns the seen flag data member of this node if it is a NamespaceNode or a CollectionNode.
NodeMap getMembers(NodeType type) const
const Location & location() const
Returns the starting location of a qdoc comment.
const Text & title() const
bool hasTableOfContents() const
static void quoteFromFile(const Location &location, Quoter "er, ResolvedFile resolved_file, CodeMarker *marker=nullptr)
Text briefText(bool inclusive=false) const
QStringMultiMap * metaTagMap() const
const TypedefNode * flagsType() const
Encapsulate the logic that QDoc uses to find files whose path is provided by the user and that are re...
This node is used to represent any kind of function being documented.
bool generateComparisonCategory(const Node *node, CodeMarker *marker=nullptr)
static void setQmlTypeContext(QmlTypeNode *t)
void generateStatus(const Node *node, CodeMarker *marker)
void generateThreadSafeness(const Node *node, CodeMarker *marker)
Generates text that explains how threadsafe and/or reentrant node is.
static bool noLinkErrors()
void generateNoexceptNote(const Node *node, CodeMarker *marker)
void unknownAtom(const Atom *atom)
virtual void terminateGenerator()
static bool matchAhead(const Atom *atom, Atom::AtomType expectedAtomType)
virtual void generateDocs()
Traverses the database recursively to generate all the documentation.
static bool appendTrademark(const Atom *atom)
Returns true if a trademark symbol should be appended to the output as determined by atom.
static bool s_redirectDocumentationToDevNull
virtual void generateBody(const Node *node, CodeMarker *marker)
Generate the body of the documentation from the qdoc comment found with the entity represented by the...
void generateSince(const Node *node, CodeMarker *marker)
void endSubPage()
Flush the text stream associated with the subpage, and then pop it off the text stream stack and dele...
static bool autolinkErrors()
bool generateComparisonTable(const Node *node)
Generates a table of comparison categories for node, combining both self-comparison (from \compares) ...
virtual void initializeGenerator()
No-op base implementation.
QString fileExtension() const override
Returns "html" for this subclass of Generator.
void generateProxyPage(Aggregate *aggregate, CodeMarker *marker) override
void generatePageNode(PageNode *pn, CodeMarker *marker) override
Generate the HTML page for an entity that doesn't map to any underlying parsable C++ or QML element.
void generateCppReferencePage(Aggregate *aggregate, CodeMarker *marker) override
Generate a reference page for the C++ class, namespace, or header file documented in node using the c...
void generateDocs() override
If qdoc is in the {-prepare} phase, traverse the primary tree to generate the index file for the curr...
void generateCollectionNode(CollectionNode *cn, CodeMarker *marker) override
Generate the HTML page for a group, module, or QML module.
~HtmlGenerator() override
Destroys the HTML output generator.
HtmlGenerator(FileResolver &file_resolver)
void generateExampleFilePage(const Node *en, ResolvedFile resolved_file, CodeMarker *marker) override
Generate an html file with the contents of a C++ or QML source file.
QString fileBase(const Node *node) const override
void generateGenericCollectionPage(CollectionNode *cn, CodeMarker *marker) override
Generate the HTML page for a generic collection.
void generateQmlTypePage(QmlTypeNode *qcn, CodeMarker *marker) override
Generate the HTML page for a QML type.
void initializeGenerator() override
Initializes the HTML output generator's data structures from the configuration (Config) singleton.
QString format() const override
Returns the format identifier for this producer (e.g., "HTML", "DocBook", "template").
void terminateGenerator() override
Gracefully terminates the HTML output generator.
qsizetype generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker) override
Generate html from an instance of Atom.
static bool isIncluded(const InclusionPolicy &policy, const NodeContext &context)
The Location class provides a way to mark a location in a file.
bool isEmpty() const
Returns true if there is no file name set yet; returns false otherwise.
The ManifestWriter is responsible for writing manifest files.
void generateManifestFiles()
This function outputs one or more manifest files in XML.
This class represents a C++ namespace.
NamespaceNode * docNode() const
Returns a pointer to the NamespaceNode that represents where the namespace documentation is actually ...
Tree * tree() const override
Returns a pointer to the Tree that contains this NamespaceNode.
bool isDocumentedHere() const
Returns true if this namespace is to be documented in the current module.
A PageNode is a Node that generates a documentation page.
bool noAutoList() const
Returns the value of the no auto-list flag.
This class describes one instance of using the Q_PROPERTY macro.
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
static QDocDatabase * qdocDB()
Creates the singleton.
Status
Specifies the status of the QQmlIncubator.
ClassNode * classNode() const override
If this is a QmlTypeNode, this function returns the pointer to the C++ ClassNode that this QML type r...
static void subclasses(const Node *base, NodeList &subs, bool recurse=false)
Loads the list subs with the nodes of all the subclasses of base.
QString logicalModuleVersion() const override
If the QML type's QML module pointer is set, return the QML module version from the QML module node.
QString logicalModuleName() const override
If the QML type's QML module pointer is set, return the QML module name from the QML module node.
QmlTypeNode * qmlBaseNode() const override
If this Aggregate is a QmlTypeNode, this function returns a pointer to the QmlTypeNode that is its ba...
CollectionNode * logicalModule() const override
If this is a QmlTypeNode, a pointer to its QML module is returned, which is a pointer to a Collection...
A class for containing the elements of one documentation section.
const NodeVector & obsoleteMembers() const
void appendMembers(const NodeVector &nv)
const Aggregate * aggregate() const
const ClassNodesList & classNodesList() const
const NodeVector & members() const
A class for creating vectors of collections for documentation.
Aggregate * aggregate() const
Sections(Aggregate *aggregate)
This constructor builds the section vectors based on the type of the aggregate node.
SectionVector & summarySections()
SectionVector & sinceSections()
Sections(const NodeMultiMap &nsmap)
This constructor builds the since sections from the since node map, nsmap.
bool hasObsoleteMembers(SectionPtrVector *summary_spv, SectionPtrVector *details_spv) const
Returns true if any sections in this object contain obsolete members.
SectionVector & detailsSections()
const Section & allMembersSection() const
Table of contents writer.
void generateTOC(const QString &fileName, const QString &indexTitle)
Writes the TOC entries for project to fileName, starting from a page with a title matching indexTitle...
This class handles the generation of the QDoc tag files.
void generateTagFile(const QString &fileName, Generator *generator)
Writes a tag file named fileName.
const QString & camelCaseModuleName() const
static void rewritePropertyBrief(const Atom *atom, const Node *relative)
Rewrites the brief of this node depending on its first word.
static int hOffset(const Node *node)
Header offset depending on the type of the node.
static bool hasBrief(const Node *node)
Do not display.
XmlGenerator(FileResolver &file_resolver)
static const QRegularExpression m_funcLeftParen
static NodeType typeFromString(const Atom *atom)
Returns the type of this atom as an enumeration.
#define COMMAND_INQMLMODULE
#define CONFIG_USEALTTEXTASTITLE
#define CONFIG_CPPCLASSESTITLE
#define CONFIG_CODEPREFIX
#define CONFIG_QMLTYPESPAGE
#define CONFIG_HEADERSCRIPTS
#define CONFIG_DESCRIPTION
#define CONFIG_CODEINDENT
#define CONFIG_TRADEMARKSPAGE
#define CONFIG_CPPCLASSESPAGE
#define CONFIG_NATURALLANGUAGE
#define CONFIG_PRODUCTNAME
#define CONFIG_NAVIGATION
#define CONFIG_BUILDVERSION
#define CONFIG_LANDINGPAGE
#define CONFIG_CODESUFFIX
#define CONFIG_LANDINGTITLE
#define CONFIG_HEADERSTYLES
#define CONFIG_QMLTYPESTITLE
static QString getClassAttr(const Node *node, const QString &classSet)
Extends the class HTML attribute generated for node.
static const Atom closeCodeTag
static void addLink(const QString &linkTarget, QStringView nestedStuff, QString *res)
static const auto headingStart
static const auto headingEnd
static const Atom openCodeTag
#define HTMLGENERATOR_PROLOGUE
#define HTMLGENERATOR_NONAVIGATIONBAR
#define HTMLGENERATOR_TOCDEPTH
#define HTMLGENERATOR_NAVIGATIONSEPARATOR
#define HTMLGENERATOR_POSTPOSTHEADER
#define HTMLGENERATOR_ADDRESS
#define HTMLGENERATOR_FOOTER
#define HTMLGENERATOR_POSTHEADER
QList< Node * > NodeVector
QMap< QString, Node * > NodeMap
QMap< QString, NodeMap > NodeMapMap
QMap< QString, CollectionNode * > CNMap
QT_BEGIN_NAMESPACE typedef QMultiMap< Text, const Node * > TextToNodeMap
QList< const Section * > SectionPtrVector
QList< Section > SectionVector
QList< ClassNodes > ClassNodesList
The Node class is the base class for all the nodes in QDoc's parse tree.
bool isExternalPage() const
Returns true if the node type is ExternalPage.
const Doc & doc() const
Returns a reference to the node's Doc data member.
virtual bool hasClasses() const
Returns true if this is a CollectionNode and its members list contains class nodes.
virtual bool hasNamespaces() const
Returns true if this is a CollectionNode and its members list contains namespace nodes.
bool isEnumType(Genus g) const
SharedCommentNode * sharedCommentNode()
bool isNamespace() const
Returns true if the node type is Namespace.
bool isQmlBasicType() const
Returns true if the node type is QmlBasicType.
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
bool isSharedCommentNode() const
Returns true if the node type is SharedComment.
bool isHeader() const
Returns true if the node type is HeaderFile.
Genus genus() const override
Returns this node's Genus.
virtual bool isPageNode() const
Returns true if this node represents something that generates a documentation page.
bool isEnumType() const
Returns true if the node type is Enum.
virtual Status status() const
Returns the node's status value.
Aggregate * parent() const
Returns the node's parent pointer.
virtual bool isDeprecated() const
Returns true if this node's status is Deprecated.
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
static bool nodeNameLessThan(const Node *first, const Node *second)
Returns true if the node n1 is less than node n2.
const Location & location() const
If this node's definition location is empty, this function returns this node's declaration location.
bool isProxyNode() const
Returns true if the node type is Proxy.
const std::optional< RelaxedTemplateDeclaration > & templateDecl() const
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool isProperty() const
Returns true if the node type is Property.
const Location & declLocation() const
Returns the Location where this node's declaration was seen.
NodeContext createContext() const
bool isModule() const
Returns true if the node type is Module.
bool isSharingComment() const
This function returns true if the node is sharing a comment with other nodes.
bool hasDoc() const
Returns true if this node is documented, or it represents a documented node read from the index ('had...
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
virtual bool isCollectionNode() const
Returns true if this is an instance of CollectionNode.
static bool nodeSortKeyOrNameLessThan(const Node *n1, const Node *n2)
Returns true if node n1 is less than node n2 when comparing the sort keys, defined with.
bool isExample() const
Returns true if the node type is Example.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.
Represents a file that is reachable by QDoc based on its current configuration.