28#include <QtCore/qlist.h>
29#include <QtCore/qmap.h>
30#include <QtCore/quuid.h>
31#include <QtCore/qversionnumber.h>
32#include <QtCore/qregularexpression.h>
40using namespace Qt::StringLiterals;
49static void addLink(
const QString &linkTarget, QStringView nestedStuff, QString *res)
51 if (!linkTarget.isEmpty()) {
52 *res += QLatin1String(
"<a href=\"");
54 *res += QLatin1String(
"\" translate=\"no\">");
56 *res += QLatin1String(
"</a>");
63
64
65
68 if (!s_inUnorderedList) {
70 s_inUnorderedList =
true;
75
76
77
80 if (s_inUnorderedList) {
82 s_inUnorderedList =
false;
87
88
89
92 if (m_helpProjectWriter) {
93 delete m_helpProjectWriter;
94 m_helpProjectWriter =
nullptr;
97 if (m_manifestWriter) {
98 delete m_manifestWriter;
99 m_manifestWriter =
nullptr;
104
105
106
126 {
nullptr,
nullptr,
nullptr } };
129 config = &Config::instance();
132
133
134
135 for (
int i = 0; defaults[i].key; ++i) {
136 formattingLeftMap().insert(QLatin1String(defaults[i].key), QLatin1String(defaults[i].left));
137 formattingRightMap().insert(QLatin1String(defaults[i].key),
138 QLatin1String(defaults[i].right));
141 QString formatDot{HtmlGenerator::format() + Config::dot};
142 m_endHeader = config->get(formatDot +
CONFIG_ENDHEADER).asString(
"</head>\n<body>\n"_L1);
156 .asString(m_project +
" Reference Documentation"_L1);
158 m_projectUrl = config->get(
CONFIG_URL).asString();
167
168
169
170 if (m_helpProjectWriter)
171 m_helpProjectWriter->reset(m_project.toLower() +
".qhp",
this);
173 m_helpProjectWriter =
new HelpProjectWriter(m_project.toLower() +
".qhp",
this);
175 if (!m_manifestWriter)
188 .asString(m_homepage);
195 .asString(m_landingpage);
202 .asString(
"C++ Classes"_L1);
209 .asString(
"QML Types"_L1);
218
219
231
232
233
234
235
236
237
243 Node *qflags = m_qdb->findClassNode(QStringList(
"QFlags"_L1));
245 m_qflagsHref = linkForNode(qflags,
nullptr);
249 const QString fileBase =
"%1/%2"_L1.arg(
251 m_project.toLower().simplified().replace(
' '_L1,
'-'_L1)
253 if (!config->generating())
254 m_qdb->generateIndex(
"%1.index"_L1.arg(fileBase), m_projectUrl, m_projectDescription);
260 const QString &rootTitle = m_landingpage.isEmpty() ? m_homepage : m_landingpage;
261 tocWriter.generateTOC(
"%1_toc.xml"_L1.arg(fileBase), rootTitle);
263
264
265 if (!tagFile_.isEmpty()) {
267 tagFileWriter.generateTagFile(tagFile_,
this);
273
274
277 SubTitleSize subTitleSize = LargeSubTitle;
278 QString fullTitle = en->fullTitle();
280 beginSubPage(en, linkForExampleFile(resolved_file.get_query()));
281 generateHeader(fullTitle, en, marker);
282 generateTitle(fullTitle, Text() << en->subtitle(), subTitleSize, en, marker);
287 QString code = quoter.quoteTo(en->location(), QString(), QString());
288 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
292 generateText(text, en, codeMarker);
297
298
301 qsizetype idx, skipAhead = 0;
302 static bool in_para =
false;
303 Genus genus = Genus::DontCare;
307 QString name = atom->string();
308 if (relative && relative->name() == name.replace(QLatin1String(
"()"), QLatin1String())) {
309 out() << protectEnc(atom->string());
318 const Node *node =
nullptr;
319 QString link = getAutoLink(atom, relative, &node, genus);
320 if (link.isEmpty()) {
325 QStringLiteral(
"Can't autolink to '%1'").arg(atom->string()));
330 if (link.isEmpty()) {
331 out() << protectEnc(atom->string());
333 beginLink(link, node, relative);
338 out() << protectEnc(atom->string());
345 skipAhead = skipAtoms(atom, Atom::BriefRight);
360 out() << protectEnc(plainCode(atom->string()));
364 out() <<
"<p class=\"figCaption\">";
375 out() <<
"<pre class=\"qml\" translate=\"no\">"
376 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative,
378 m_codePrefix, m_codeSuffix)
382 out() <<
"<pre class=\"cpp\" translate=\"no\">"
383 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative),
384 m_codePrefix, m_codeSuffix)
388 out() <<
"<pre class=\"cpp plain\" translate=\"no\">"
389 << trimmedTrailing(protectEnc(plainCode(indent(m_codeIndent, atom->string()))),
390 m_codePrefix, m_codeSuffix)
394 out() <<
"<details>\n";
395 if (!atom->string().isEmpty())
396 out() <<
"<summary>" << protectEnc(atom->string()) <<
"</summary>\n";
398 out() <<
"<summary>...</summary>\n";
401 out() <<
"</details>\n";
405 if (!atom->string().isEmpty())
406 out() <<
' ' << atom->string();
429 if (atom->string().startsWith(
"span "))
430 out() <<
'<' + atom->string() <<
'>';
432 out() << formattingLeftMap()[atom->string()];
440 const Node *node{
nullptr};
441 const Atom tm_link(Atom::NavLink, m_trademarkspage);
442 if (
const auto &link = getLink(&tm_link, relative, &node);
443 !link.isEmpty() && node != relative)
444 out() <<
"<a href=\"%1\">%2</a>"_L1.arg(link, formattingRightMap()[atom->string()]);
446 out() << formattingRightMap()[atom->string()];
449 }
else if (atom->string().startsWith(
"span ")) {
452 out() << formattingRightMap()[atom->string()];
456 if (
const auto *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group); cn)
457 generateList(cn, marker, atom->string(), Generator::sortOrder(atom->strings().last()));
460 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
461 if (atom->string() == QLatin1String(
"annotatedclasses")) {
462 generateAnnotatedList(relative, marker, m_qdb->getCppClasses().values(), sortOrder);
463 }
else if (atom->string() == QLatin1String(
"annotatedexamples")) {
465 }
else if (atom->string() == QLatin1String(
"annotatedattributions")) {
467 }
else if (atom->string() == QLatin1String(
"classes")) {
468 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true,
470 }
else if (atom->string().contains(
"classes ")) {
471 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
472 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true, rootName);
473 }
else if (atom->string() == QLatin1String(
"qmlvaluetypes")
474 || atom->string() == QLatin1String(
"qmlbasictypes")) {
475 generateCompactList(Generic, relative, m_qdb->getQmlValueTypes(),
true,
477 }
else if (atom->string() == QLatin1String(
"qmltypes")) {
478 generateCompactList(Generic, relative, m_qdb->getQmlTypes(),
true, QStringLiteral(
""));
479 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
481 QString moduleName = atom->string().mid(idx + 8).trimmed();
483 if (
const auto *cn = qdb->getCollectionNode(moduleName, moduleType)) {
485 switch (moduleType) {
489 generateAnnotatedList(relative, marker, map.values(), sortOrder);
492 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
496 generateAnnotatedList(relative, marker, map.values(), sortOrder);
499 generateAnnotatedList(relative, marker, cn->members(), sortOrder);
503 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
505 }
else if (atom->string() == QLatin1String(
"obsoleteclasses")) {
506 generateCompactList(Generic, relative, m_qdb->getObsoleteClasses(),
false,
507 QStringLiteral(
"Q"));
508 }
else if (atom->string() == QLatin1String(
"obsoleteqmltypes")) {
509 generateCompactList(Generic, relative, m_qdb->getObsoleteQmlTypes(),
false,
511 }
else if (atom->string() == QLatin1String(
"obsoletecppmembers")) {
512 generateCompactList(Obsolete, relative, m_qdb->getClassesWithObsoleteMembers(),
false,
513 QStringLiteral(
"Q"));
514 }
else if (atom->string() == QLatin1String(
"obsoleteqmlmembers")) {
515 generateCompactList(Obsolete, relative, m_qdb->getQmlTypesWithObsoleteMembers(),
false,
517 }
else if (atom->string() == QLatin1String(
"functionindex")) {
518 generateFunctionIndex(relative);
519 }
else if (atom->string() == QLatin1String(
"attributions")) {
520 generateAnnotatedList(relative, marker, m_qdb->getAttributions().values(), sortOrder);
521 }
else if (atom->string() == QLatin1String(
"legalese")) {
522 generateLegaleseList(relative, marker);
523 }
else if (atom->string() == QLatin1String(
"overviews")) {
524 generateList(relative, marker,
"overviews", sortOrder);
525 }
else if (atom->string() == QLatin1String(
"cpp-modules")) {
526 generateList(relative, marker,
"cpp-modules", sortOrder);
527 }
else if (atom->string() == QLatin1String(
"qml-modules")) {
528 generateList(relative, marker,
"qml-modules", sortOrder);
529 }
else if (atom->string() == QLatin1String(
"namespaces")) {
530 generateAnnotatedList(relative, marker, m_qdb->getNamespaces().values(), sortOrder);
531 }
else if (atom->string() == QLatin1String(
"related")) {
532 generateList(relative, marker,
"related", sortOrder);
536 if (!generateGroupList(
const_cast<CollectionNode *>(cn), sortOrder))
538 QString(
"'\\generatelist %1' group is empty").arg(atom->string()));
541 QString(
"'\\generatelist %1' no such group").arg(atom->string()));
556 for (
const auto §ion : sinceSections) {
557 if (!section.members().isEmpty()) {
559 <<
"<a href=\"#" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
560 << section.title() <<
"</a></li>\n";
566 for (
const auto §ion : sinceSections) {
567 if (!section.members().isEmpty()) {
568 out() <<
"<h3 id=\"" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
569 << protectEnc(section.title()) <<
"</h3>\n";
570 if (index == Sections::SinceClasses)
571 generateCompactList(Generic, relative, ncmap,
false, QStringLiteral(
"Q"));
572 else if (index == Sections::SinceQmlTypes)
573 generateCompactList(Generic, relative, nqcmap,
false, QStringLiteral(
""));
574 else if (index == Sections::SinceMemberFunctions
575 || index == Sections::SinceQmlMethods
576 || index == Sections::SinceQmlProperties) {
578 QMap<QString, NodeMultiMap> parentmaps;
580 const QList<Node *> &members = section.members();
581 for (
const auto &member : members) {
582 QString parent_full_name = (*member).parent()->fullName();
584 auto parent_entry = parentmaps.find(parent_full_name);
585 if (parent_entry == parentmaps.end())
586 parent_entry = parentmaps.insert(parent_full_name, NodeMultiMap());
587 parent_entry->insert(member->name(), member);
590 for (
auto map = parentmaps.begin(); map != parentmaps.end(); ++map) {
591 NodeVector nv = map->values().toVector();
592 auto parent = nv.front()->parent();
594 out() << ((index == Sections::SinceMemberFunctions) ?
"<p>Class " :
"<p>QML Type ");
596 out() <<
"<a href=\"" << linkForNode(parent, relative) <<
"\" translate=\"no\">";
597 QStringList pieces = parent->fullName().split(
"::");
598 out() << protectEnc(pieces.last());
602 generateSection(nv, relative, marker);
605 }
else if (index == Sections::SinceEnumValues) {
606 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
607 const auto map_it = m_qdb->newEnumValueMaps().constFind(atom->string());
608 for (
auto it = map_it->cbegin(); it != map_it->cend(); ++it) {
609 out() <<
"<tr><td class=\"memItemLeft\"> enum value </td><td class=\"memItemRight\">"
610 <<
"<b><a href=\"" << linkForNode(it.value(),
nullptr) <<
"\">"
611 << it.key() <<
"</a></b></td></tr>\n";
613 out() <<
"</table></div>\n";
615 generateSection(section.members(), relative, marker);
633 out() <<
"<p class=\"centerAlign\">";
635 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
636 if (!maybe_resolved_file) {
638 relative->location().warning(
639 QStringLiteral(
"Missing image: %1").arg(protectEnc(atom->string())));
640 out() <<
"<font color=\"red\">[Missing image " << protectEnc(atom->string())
644 QString file_name{QFileInfo{file.get_path()}.fileName()};
663 Config::copyFile(relative->doc().location(), file.get_path(), file_name,
664 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
666 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
668 out() <<
"<img src=\"%1\""_L1.arg(protectEnc(imgPath));
670 const QString altAndTitleText = protectEnc(text);
671 out() <<
" alt=\"" << altAndTitleText;
673 out() <<
"\" title=\"" << altAndTitleText;
677 m_helpProjectWriter->addExtraFile(imgPath);
678 setImageFileName(relative, imgPath);
690 QString admonType = atom->typeString();
693 out() <<
"<div class=\"admonition " << admonType.toLower() <<
"\">\n"
696 out() << admonType <<
": ";
706 out() <<
"<div class=\"LegaleseLeft\">";
720 const Node *node =
nullptr;
721 QString link = getLink(atom, relative, &node);
726 QStringLiteral(
"Can't link to '%1'").arg(atom->string()));
728 beginLink(link, node, relative);
732 QString link = linkForExampleFile(atom->string());
737 QString link = atom->string();
738 link =
"images/used-in-examples/" + link;
743 const Node *node =
static_cast<
const Node*>(Utilities::nodeForString(atom->string()));
744 beginLink(linkForNode(node, relative), node, relative);
757 out() << R"(<div class="table"><table class="valuelist">)";
761 out() << R"(<tr valign="top" class="odd">)";
763 out() << R"(<tr valign="top" class="even">)";
765 out() <<
"<th class=\"tblConst\">Constant</th>";
769 out() <<
"<th class=\"tblval\">Value</th>";
771 out() <<
"<th class=\"tbldscr\">Description</th></tr>\n";
773 out() <<
"<tr><th class=\"tblConst\">Constant</th><th "
774 "class=\"tblVal\">Value</th></tr>\n";
791 out() << QString(R"(<ol class="%1" type="%1" start="%2">)")
792 .arg(olType, atom
->next()->string());
794 out() << QString(R"(<ol class="%1" type="%1">)").arg(olType);
803 std::pair<QString,
int> pair = getAtomListValue(atom);
804 skipAhead = pair.second;
805 QString t = protectEnc(plainCode(marker->markedUpEnumValue(pair.first, relative)));
806 out() <<
"<tr><td class=\"topAlign\"><code translate=\"no\">" << t <<
"</code>";
809 out() <<
"</td><td class=\"topAlign tblval\">";
810 const auto *enume =
static_cast<
const EnumNode *>(relative);
811 QString itemValue = enume->itemValue(atom->next()->string());
812 if (itemValue.isEmpty())
815 out() <<
"<code translate=\"no\">" << protectEnc(itemValue) <<
"</code>";
829 out() <<
"</td><td class=\"topAlign\">";
836 if (matchAhead(atom, Atom::ParaLeft))
843 out() <<
"</td></tr>\n";
854 out() <<
"</table></div>\n";
875 out() <<
"<blockquote>";
878 out() <<
"</blockquote>\n";
881 out() << atom->string();
887 int unit = atom->string().toInt() +
hOffset(relative
);
888 out() <<
"<h" + QString::number(unit) + QLatin1Char(
' ') <<
"id=\""
889 << Tree::refForAtom(atom) <<
"\">";
893 case Atom::SectionHeadingRight:
894 out() <<
"</h" + QString::number(atom->string().toInt() + hOffset(relative)) +
">\n";
905 out() << protectEnc(atom->string());
909 std::pair<QString, QString> pair = getTableWidthAttr(atom);
910 QString attr = pair.second;
911 QString width = pair.first;
918 out() << R"(<div class="table"><table class=")" << attr <<
'"';
919 if (!width.isEmpty())
920 out() <<
" width=\"" << width <<
'"';
925 out() <<
"</table></div>\n";
928 out() <<
"<thead><tr class=\"qt-style\">";
935 out() <<
"\n<tr class=\"qt-style\">";
937 out() <<
"</thead>\n";
942 if (!atom->string().isEmpty())
943 out() <<
"<tr " << atom->string() <<
'>';
945 out() << R"(<tr valign="top" class="odd">)";
947 out() << R"(<tr valign="top" class="even">)";
958 for (
int i = 0; i < atom->count(); ++i) {
961 const QString &p = atom->string(i);
962 if (p.contains(
'=')) {
965 QStringList spans = p.split(QLatin1Char(
','));
966 if (spans.size() == 2) {
967 if (spans.at(0) !=
"1")
968 out() <<
" colspan=\"" << spans.at(0) <<
'"';
969 if (spans.at(1) !=
"1")
970 out() <<
" rowspan=\"" << spans.at(1) <<
'"';
975 if (matchAhead(atom, Atom::ParaLeft))
984 if (matchAhead(atom, Atom::ParaLeft))
987 case Atom::TableOfContentsLeft:
989 std::ignore = atom->find(Atom::TableOfContentsRight, &skipAhead);
994 out() <<
"<span id=\"" << Utilities::asAsciiPrintable(atom->string()) <<
"\"></span>";
997 out() <<
"<b class=\"redFont\"><Missing HTML></b>";
999 case Atom::UnknownCommand:
1000 out() << R"(<b class="redFont"><code translate=\"no\">\)" << protectEnc(atom->string()) <<
"</code></b>";
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1048 auto link_for_group = [
this](
const CollectionNode *group) -> QString {
1049 QString target{linkForNode(group,
nullptr)};
1050 return (target.isEmpty()) ? protectEnc(group->name()) :
"<a href=\"" + target +
"\">" + protectEnc(group->fullTitle()) +
"</a>";
1055 const QStringList &groups_names{node->groupNames()};
1056 if (groups_names.isEmpty())
1059 std::vector<CollectionNode *> groups_nodes(groups_names.size(),
nullptr);
1060 std::transform(groups_names.cbegin(), groups_names.cend(), groups_nodes.begin(),
1064 return (group && group
->wasSeen()) ? group :
nullptr;
1066 groups_nodes.erase(
std::remove(groups_nodes.begin(), groups_nodes.end(),
nullptr), groups_nodes.end());
1068 if (!groups_nodes.empty()) {
1069 text += node->name() +
" is part of ";
1071 for (std::vector<CollectionNode *>::size_type index{0}; index < groups_nodes.size(); ++index) {
1072 text += link_for_group(groups_nodes[index]) + Utilities::separator(index, groups_nodes.size());
1079
1080
1081
1082
1092 QString typeWord = aggregate->typeWord(
true);
1095 fullTitle = aggregate->plainFullName();
1096 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1101 fullTitle = aggregate->plainFullName();
1102 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1106 title = fullTitle = aggregate->fullTitle();
1113 if (aggregate
->parent()->isInAPI() || templateDecl) {
1115 subtitleText <<
"%1 "_L1.arg((*templateDecl).to_qstring());
1116 subtitleText << aggregate->typeWord(
false) <<
" "_L1;
1117 auto ancestors = fullTitle.split(
"::"_L1);
1118 ancestors.pop_back();
1119 for (
const auto &a : ancestors)
1120 subtitleText << Atom(Atom::AutoLink, a) <<
"::"_L1;
1121 subtitleText << aggregate->plainName();
1124 generateHeader(title, aggregate, marker);
1125 generateTableOfContents(aggregate, marker, summarySections);
1126 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1130 brief <<
"The " << ns->name() <<
" namespace includes the following elements from module "
1133 addNodeLink(brief, fullNamespace,
" here.");
1135 generateText(brief, ns, marker);
1138 generateBrief(aggregate, marker);
1140 const auto parentIsClass = aggregate
->parent()->isClassNode();
1143 generateRequisites(aggregate, marker);
1148 QString membersLink = generateAllMembersFile(Sections::allMembersSection(), marker);
1149 if (!membersLink.isEmpty()) {
1150 openUnorderedList();
1151 out() <<
"<li><a href=\"" << membersLink <<
"\">"
1152 <<
"List of all members, including inherited members</a></li>\n";
1154 QString obsoleteLink = generateObsoleteMembersFile(sections, marker);
1155 if (!obsoleteLink.isEmpty()) {
1156 openUnorderedList();
1157 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1158 <<
"Deprecated members</a></li>\n";
1161 if (QString groups_text{groupReferenceText(aggregate)}; !groups_text.isEmpty()) {
1162 openUnorderedList();
1164 out() <<
"<li>" << groups_text <<
"</li>\n";
1167 closeUnorderedList();
1173 bool needOtherSection =
false;
1175 for (
const auto §ion : std::as_const(*summarySections)) {
1176 if (section.members().isEmpty() && section.reimplementedMembers().isEmpty()) {
1177 if (!section.inheritedMembers().isEmpty())
1178 needOtherSection =
true;
1180 if (!section.members().isEmpty()) {
1181 QString ref = registerRef(section.title().toLower());
1182 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1183 generateSection(section.members(), aggregate, marker);
1185 if (!section.reimplementedMembers().isEmpty()) {
1186 QString name = QString(
"Reimplemented ") + section.title();
1187 QString ref = registerRef(name.toLower());
1188 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(name) <<
"</h2>\n";
1189 generateSection(section.reimplementedMembers(), aggregate, marker);
1192 if (!section.inheritedMembers().isEmpty()) {
1194 generateSectionInheritedList(section, aggregate);
1200 if (needOtherSection) {
1201 out() <<
"<h3>Additional Inherited Members</h3>\n"
1204 for (
const auto §ion : std::as_const(*summarySections)) {
1205 if (section.members().isEmpty() && !section.inheritedMembers().isEmpty())
1206 generateSectionInheritedList(section, aggregate);
1211 if (aggregate
->doc().isEmpty()) {
1212 QString command =
"documentation";
1214 command = R"('\class' comment)";
1217 QStringLiteral(
"No %1 for '%2'").arg(command, aggregate->plainSignature()));
1220 generateExtractionMark(aggregate, DetailedDescriptionMark);
1221 out() <<
"<div class=\"descr\">\n"
1222 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1223 <<
"Detailed Description"
1226 out() <<
"</div>\n";
1227 generateAlsoList(aggregate, marker);
1228 generateExtractionMark(aggregate, EndMark);
1231 for (
const auto §ion : std::as_const(*detailsSections)) {
1232 bool headerGenerated =
false;
1233 if (section.isEmpty())
1236 const QList<Node *> &members = section.members();
1237 for (
const auto &member : members) {
1238 if (!headerGenerated) {
1239 if (!section.divClass().isEmpty())
1240 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1241 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1242 headerGenerated =
true;
1244 if (!member->isClassNode())
1245 generateDetailedMember(member, aggregate, marker);
1247 out() <<
"<h3> class ";
1248 generateFullName(member, aggregate);
1250 generateBrief(member, marker, aggregate);
1253 if (headerGenerated && !section.divClass().isEmpty())
1254 out() <<
"</div>\n";
1256 generateFooter(aggregate);
1271 rawTitle = aggregate->plainName();
1272 fullTitle = aggregate->plainFullName();
1273 title = rawTitle +
" Proxy Page";
1276 generateHeader(title, aggregate, marker);
1277 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1278 generateBrief(aggregate, marker);
1279 for (
auto it = summarySections->constBegin(); it != summarySections->constEnd(); ++it) {
1280 if (!it->members().isEmpty()) {
1281 QString ref = registerRef(it->title().toLower());
1282 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(it->title()) <<
"</h2>\n";
1283 generateSection(it->members(), aggregate, marker);
1287 if (!aggregate
->doc().isEmpty()) {
1288 generateExtractionMark(aggregate, DetailedDescriptionMark);
1289 out() <<
"<div class=\"descr\">\n"
1290 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1291 <<
"Detailed Description"
1294 out() <<
"</div>\n";
1295 generateAlsoList(aggregate, marker);
1296 generateExtractionMark(aggregate, EndMark);
1299 for (
const auto §ion : std::as_const(*detailsSections)) {
1300 if (section.isEmpty())
1303 if (!section.divClass().isEmpty())
1304 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1305 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1307 const QList<Node *> &members = section.members();
1308 for (
const auto &member : members) {
1309 if (!member->isClassNode()) {
1310 generateDetailedMember(member, aggregate, marker);
1312 out() <<
"<h3> class ";
1313 generateFullName(member, aggregate);
1315 generateBrief(member, marker, aggregate);
1318 if (!section.divClass().isEmpty())
1319 out() <<
"</div>\n";
1321 generateFooter(aggregate);
1325
1326
1327
1331 SubTitleSize subTitleSize = LargeSubTitle;
1332 QString htmlTitle = qcn->name();
1334 htmlTitle.append(
" QML Value Type");
1336 htmlTitle.append(
" QML Type");
1338 if (qcn->isSingleton())
1339 htmlTitle.append(
" (Singleton)"_L1);
1341 generateHeader(htmlTitle, qcn, marker);
1343 generateTableOfContents(qcn, marker, §ions.stdQmlTypeSummarySections());
1344 marker = CodeMarker::markerForLanguage(QLatin1String(
"QML"));
1345 generateTitle(htmlTitle, Text() << qcn->subtitle(), subTitleSize, qcn, marker);
1346 generateBrief(qcn, marker);
1347 generateQmlRequisites(qcn, marker);
1351 out() <<
"<p><strong>Note:</strong> This type is a QML singleton. "_L1
1352 <<
"There is only one instance of this type in the QML engine.</p>\n"_L1;
1355 QString allQmlMembersLink;
1358 if (!qcn->isQmlBasicType())
1359 allQmlMembersLink = generateAllQmlMembersFile(sections, marker);
1360 QString obsoleteLink = generateObsoleteQmlMembersFile(sections, marker);
1361 if (!allQmlMembersLink.isEmpty() || !obsoleteLink.isEmpty()) {
1362 openUnorderedList();
1364 if (!allQmlMembersLink.isEmpty()) {
1365 out() <<
"<li><a href=\"" << allQmlMembersLink <<
"\">"
1366 <<
"List of all members, including inherited members</a></li>\n";
1368 if (!obsoleteLink.isEmpty()) {
1369 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1370 <<
"Deprecated members</a></li>\n";
1374 if (QString groups_text{groupReferenceText(qcn)}; !groups_text.isEmpty()) {
1375 openUnorderedList();
1377 out() <<
"<li>" << groups_text <<
"</li>\n";
1380 closeUnorderedList();
1383 for (
const auto §ion : stdQmlTypeSummarySections) {
1384 if (!section.isEmpty()) {
1385 QString ref = registerRef(section.title().toLower());
1386 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1387 generateQmlSummary(section.members(), qcn, marker);
1391 generateExtractionMark(qcn, DetailedDescriptionMark);
1392 out() <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1393 <<
"Detailed Description"
1396 generateAlsoList(qcn, marker);
1397 generateExtractionMark(qcn, EndMark);
1400 for (
const auto §ion : stdQmlTypeDetailsSections) {
1401 if (section.isEmpty())
1403 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1404 const QList<Node *> &members = section.members();
1405 for (
const auto member : members)
1406 generateDetailedQmlMember(member, qcn, marker);
1408 generateFooter(qcn);
1413
1414
1415
1418 SubTitleSize subTitleSize = LargeSubTitle;
1419 QString fullTitle = pn->fullTitle();
1421 generateHeader(fullTitle, pn, marker);
1423
1424
1425
1426 if ((pn->name() != QLatin1String(
"index.html")))
1427 generateTableOfContents(pn, marker,
nullptr);
1429 generateTitle(fullTitle, Text() << pn->subtitle(), subTitleSize, pn, marker);
1431 generateBrief(pn, marker,
nullptr,
false);
1434 generateExtractionMark(pn, DetailedDescriptionMark);
1435 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1439 out() <<
"</div>\n";
1440 generateAlsoList(pn, marker);
1441 generateExtractionMark(pn, EndMark);
1447
1448
1451 SubTitleSize subTitleSize = LargeSubTitle;
1452 QString fullTitle = cn->fullTitle();
1455 generateHeader(fullTitle, cn, marker);
1456 generateTableOfContents(cn, marker,
nullptr);
1457 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1460 if (cn
->genus() != Genus::DOC && cn
->genus() != Genus::DontCare) {
1462 generateBrief(cn, marker);
1470 if (!nmm.isEmpty()) {
1471 ref = registerRef(
"namespaces");
1472 out() <<
"<h2 id=\"" << ref <<
"\">Namespaces</h2>\n";
1473 generateAnnotatedList(cn, marker, nmm.values());
1476 if (!nmm.isEmpty()) {
1477 ref = registerRef(
"classes");
1478 out() <<
"<h2 id=\"" << ref <<
"\">Classes</h2>\n";
1479 generateAnnotatedList(cn, marker, nmm.values());
1485 generateExtractionMark(cn, DetailedDescriptionMark);
1486 ref = registerRef(
"details");
1487 out() <<
"<div class=\"descr\">\n";
1488 out() <<
"<h2 id=\"" << ref <<
"\">"
1489 <<
"Detailed Description"
1492 generateExtractionMark(cn, DetailedDescriptionMark);
1493 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1498 out() <<
"</div>\n";
1499 generateAlsoList(cn, marker);
1500 generateExtractionMark(cn, EndMark);
1503 if (cn->isGroup() || cn->isQmlModule())
1504 generateAnnotatedList(cn, marker, cn->members());
1510
1511
1512
1513
1516 SubTitleSize subTitleSize = LargeSubTitle;
1517 QString fullTitle = cn->name();
1519 generateHeader(fullTitle, cn, marker);
1520 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1523 brief <<
"Each function or type documented here is related to a class or "
1524 <<
"namespace that is documented in a different module. The reference "
1525 <<
"page for that class or namespace will link to the function or type "
1528 generateText(brief, cn, marker);
1532 for (
const auto &member : members)
1533 generateDetailedMember(member, cn, marker);
1539
1540
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568void HtmlGenerator::generateNavigationBar(
const QString &title,
const Node *node,
1569 CodeMarker *marker,
const QString &buildversion,
1572 if (m_noNavigationBar || node ==
nullptr)
1583 auto addNavItem = [&](
const QString &link,
const QString &title) {
1584 navigationbar << Atom(itemLeft) << Atom(
Atom::NavLink, link)
1591 auto addNavItemNode = [&](
const Node *node,
const QString &title) {
1592 navigationbar << Atom(itemLeft);
1593 addNodeLink(navigationbar, node, title);
1594 navigationbar << Atom(itemRight);
1599 QString moduleState;
1600 if (moduleNode && !moduleNode->state().isEmpty())
1601 moduleState = QStringLiteral(
" (%1)").arg(moduleNode->state());
1603 if (m_hometitle == title)
1605 if (!m_homepage.isEmpty())
1606 addNavItem(m_homepage, m_hometitle);
1607 if (!m_landingpage.isEmpty() && m_landingtitle != title)
1608 addNavItem(m_landingpage, m_landingtitle);
1611 if (!m_cppclassespage.isEmpty() && !m_cppclassestitle.isEmpty())
1612 addNavItem(m_cppclassespage, m_cppclassestitle);
1613 if (!node->physicalModuleName().isEmpty()) {
1617 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_cppclassespage))
1618 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1620 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1622 if (!m_qmltypespage.isEmpty() && !m_qmltypestitle.isEmpty())
1623 addNavItem(m_qmltypespage, m_qmltypestitle);
1627 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_qmltypespage)) {
1628 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1630 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1633 auto currentNode{
static_cast<
const PageNode*>(node)};
1634 std::deque<
const Node *> navNodes;
1636 qsizetype navItems = 0;
1638 if (
std::find(navNodes.cbegin(), navNodes.cend(),
1645 if (navNodes.empty()) {
1646 const QStringList groups =
static_cast<
const PageNode *>(node)->groupNames();
1647 for (
const auto &groupName : groups) {
1648 const auto *groupNode = m_qdb->findNodeByNameAndType(QStringList{groupName}, &Node::isGroup);
1649 if (groupNode && !groupNode->title().isEmpty()) {
1650 navNodes.push_front(groupNode);
1655 while (!navNodes.empty()) {
1656 if (navNodes.front()->isPageNode())
1657 addNavItemNode(navNodes.front(), navNodes.front()->title());
1658 navNodes.pop_front();
1662 navigationbar << Atom(itemLeft) << Atom(
Atom::String, title) << Atom(itemRight);
1666 generateText(navigationbar, node, marker);
1668 if (buildversion.isEmpty())
1674 out() <<
"</tr></table><table class=\"buildversion\"><tr>\n"
1675 << R"(<td id="buildversion" width="100%" align="right">)";
1677 out() <<
"<li id=\"buildversion\">";
1681 if (!m_landingpage.isEmpty() && m_landingtitle != title) {
1682 navigationbar << Atom(Atom::NavLink, m_landingpage)
1684 << Atom(Atom::String, buildversion)
1686 generateText(navigationbar, node, marker);
1688 out() << buildversion;
1698 out() <<
"<!DOCTYPE html>\n";
1699 out() << QString(
"<html lang=\"%1\">\n").arg(naturalLanguage);
1700 out() <<
"<head>\n";
1701 out() <<
" <meta charset=\"utf-8\">\n";
1706 out() <<
" <meta name=\"description\" content=\""
1707 << protectEnc(node->doc().briefText().toString())
1712 QString titleSuffix;
1713 if (!m_landingtitle.isEmpty()) {
1715 titleSuffix = m_landingtitle;
1716 }
else if (!m_hometitle.isEmpty()) {
1719 if (title != m_hometitle)
1720 titleSuffix = m_hometitle;
1723 titleSuffix = m_productName.isEmpty() ? m_project : m_productName;
1725 if (title == titleSuffix)
1726 titleSuffix.clear();
1728 out() <<
" <title>";
1729 if (!titleSuffix.isEmpty() && !title.isEmpty()) {
1730 out() <<
"%1 | %2"_L1.arg(protectEnc(title), titleSuffix);
1732 out() << protectEnc(title);
1737 QVersionNumber projectVersion = QVersionNumber::fromString(m_qdb->version());
1738 if (!projectVersion.isNull()) {
1739 QVersionNumber titleVersion;
1740 static const QRegularExpression re(QLatin1String(R"(\d+\.\d+)"));
1741 const QString &versionedTitle = titleSuffix.isEmpty() ? title : titleSuffix;
1742 auto match = re.match(versionedTitle);
1743 if (match.hasMatch())
1744 titleVersion = QVersionNumber::fromString(match.captured());
1745 if (titleVersion.isNull() || !titleVersion.isPrefixOf(projectVersion)) {
1747 if (!m_productName.isEmpty() && titleSuffix != m_productName)
1748 out() <<
" | %1"_L1.arg(m_productName);
1749 out() <<
" %1"_L1.arg(projectVersion.toString());
1752 out() <<
"</title>\n";
1755 out() << m_headerStyles;
1756 out() << m_headerScripts;
1757 out() << m_endHeader;
1759 out() << QString(m_postHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1760 bool usingTable = m_postHeader.trimmed().endsWith(QLatin1String(
"<tr>"));
1761 generateNavigationBar(title, node, marker, m_buildversion, usingTable);
1762 out() << QString(m_postPostHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1764 m_navigationLinks.clear();
1767 if (node && !node->links().empty()) {
1768 std::pair<QString, QString> linkPair;
1769 std::pair<QString, QString> anchorPair;
1770 const Node *linkNode;
1771 bool useSeparator =
false;
1773 if (node->links().contains(Node::PreviousLink)) {
1774 linkPair = node->links()[Node::PreviousLink];
1775 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1778 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1779 if (linkNode ==
nullptr || linkNode == node)
1780 anchorPair = linkPair;
1782 anchorPair = anchorForNode(linkNode);
1784 out() << R"( <link rel="prev" href=")" << anchorPair.first <<
"\" />\n";
1786 m_navigationLinks += R"(<a class="prevPage" href=")" + anchorPair.first +
"\">";
1787 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1788 m_navigationLinks += protect(anchorPair.second);
1790 m_navigationLinks += protect(linkPair.second);
1791 m_navigationLinks +=
"</a>\n";
1792 useSeparator = !m_navigationSeparator.isEmpty();
1794 if (node->links().contains(Node::NextLink)) {
1795 linkPair = node->links()[Node::NextLink];
1796 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1799 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1800 if (linkNode ==
nullptr || linkNode == node)
1801 anchorPair = linkPair;
1803 anchorPair = anchorForNode(linkNode);
1805 out() << R"( <link rel="next" href=")" << anchorPair.first <<
"\" />\n";
1808 m_navigationLinks += m_navigationSeparator;
1810 m_navigationLinks += R"(<a class="nextPage" href=")" + anchorPair.first +
"\">";
1811 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1812 m_navigationLinks += protect(anchorPair.second);
1814 m_navigationLinks += protect(linkPair.second);
1815 m_navigationLinks +=
"</a>\n";
1817 if (node->links().contains(Node::StartLink)) {
1818 linkPair = node->links()[Node::StartLink];
1819 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1822 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1823 if (linkNode ==
nullptr || linkNode == node)
1824 anchorPair =
std::move(linkPair);
1826 anchorPair = anchorForNode(linkNode);
1827 out() << R"( <link rel="start" href=")" << anchorPair.first <<
"\" />\n";
1831 if (node && !node->links().empty())
1832 out() <<
"<p class=\"naviNextPrevious headerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1836 SubTitleSize subTitleSize,
const Node *relative,
1839 out() << QString(m_prologue).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1842 attribute = R"( translate="no")";
1844 if (!title.isEmpty())
1845 out() <<
"<h1 class=\"title\"" << attribute <<
">" << protectEnc(title) <<
"</h1>\n";
1848 if (subTitleSize == SmallSubTitle)
1849 out() <<
" class=\"small-subtitle\"" << attribute <<
">";
1851 out() <<
" class=\"subtitle\"" << attribute <<
">";
1852 generateText(subtitle, relative, marker);
1853 out() <<
"</span>\n";
1859 if (node && !node->links().empty())
1860 out() <<
"<p class=\"naviNextPrevious footerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1862 out() << QString(m_footer).replace(
"\\" +
COMMAND_VERSION, m_qdb->version())
1863 << QString(m_address).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1865 out() <<
"</body>\n";
1866 out() <<
"</html>\n";
1870
1871
1872
1875 QMap<QString, Text> requisites;
1878 const QString headerText =
"Header";
1879 const QString sinceText =
"Since";
1880 const QString inheritedByText =
"Inherited By";
1881 const QString inheritsText =
"Inherits";
1882 const QString nativeTypeText =
"In QML";
1883 const QString qtVariableText =
"qmake";
1884 const QString cmakeText =
"CMake";
1885 const QString statusText =
"Status";
1888 const QStringList requisiteorder { headerText, cmakeText, qtVariableText, sinceText,
1889 nativeTypeText, inheritsText, inheritedByText, statusText };
1891 addIncludeFileToMap(aggregate, requisites, text, headerText);
1892 addSinceToMap(aggregate, requisites, &text, sinceText);
1895 addCMakeInfoToMap(aggregate, requisites, &text, cmakeText);
1896 addQtVariableToMap(aggregate, requisites, &text, qtVariableText);
1900 auto *classe =
dynamic_cast<
ClassNode *>(aggregate);
1902 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1904 if (InclusionFilter::isIncluded(policy, context))
1905 addQmlNativeTypesToMap(requisites, &text, nativeTypeText, classe);
1908 addInheritsToMap(requisites, &text, inheritsText, classe);
1909 addInheritedByToMap(requisites, &text, inheritedByText, classe);
1913 addStatusToMap(aggregate, requisites, text, statusText);
1915 if (!requisites.isEmpty()) {
1917 generateTheTable(requisiteorder, requisites, aggregate, marker);
1922
1923
1924void HtmlGenerator::generateTheTable(
const QStringList &requisiteOrder,
1925 const QMap<QString, Text> &requisites,
1928 out() <<
"<div class=\"table\"><table class=\"alignedsummary requisites\" translate=\"no\">\n";
1930 for (
auto it = requisiteOrder.constBegin(); it != requisiteOrder.constEnd(); ++it) {
1932 if (requisites.contains(*it)) {
1934 <<
"<td class=\"memItemLeft rightAlign topAlign\"> " << *it
1936 "</td><td class=\"memItemRight bottomAlign\"> ";
1938 generateText(requisites.value(*it), aggregate, marker);
1939 out() <<
"</td></tr>\n";
1942 out() <<
"</table></div>\n";
1946
1947
1948
1949void HtmlGenerator::addInheritedByToMap(QMap<QString, Text> &requisites,
Text *text,
1950 const QString &inheritedByText,
ClassNode *classe)
1952 if (!classe->derivedClasses().isEmpty()) {
1955 int count = appendSortedNames(*text, classe, classe->derivedClasses());
1958 requisites.insert(inheritedByText, *text);
1963
1964
1965
1966void HtmlGenerator::addInheritsToMap(QMap<QString, Text> &requisites,
Text *text,
1967 const QString &inheritsText,
ClassNode *classe)
1969 if (!classe->baseClasses().isEmpty()) {
1972 const auto baseClasses = classe->baseClasses();
1973 for (
const auto &cls : baseClasses) {
1975 appendFullName(*text, cls.m_node, classe);
1977 if (cls.m_access == Access::Protected) {
1978 *text <<
" (protected)";
1979 }
else if (cls.m_access == Access::Private) {
1980 *text <<
" (private)";
1982 *text << Utilities::comma(index++, classe->baseClasses().size());
1987 requisites.insert(inheritsText, *text);
1992
1993
1994
1995void HtmlGenerator::addQmlNativeTypesToMap(QMap<QString, Text> &requisites,
Text *text,
1996 const QString &nativeTypeText,
ClassNode *classe)
const
2003 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2005 qsizetype index { 0 };
2007 for (
const auto &item : std::as_const(nativeTypes)) {
2008 addNodeLink(*text, item);
2009 *text << Utilities::comma(index++, nativeTypes.size());
2011 requisites.insert(nativeTypeText, *text);
2015
2016
2017
2019 Text *text,
const QString &CMakeInfo)
const
2021 if (!aggregate->physicalModuleName().isEmpty() && text !=
nullptr) {
2025 const auto result = cmakeRequisite(cn);
2038 requisites.insert(CMakeInfo, *text);
2043
2044
2045
2047 Text *text,
const QString &qtVariableText)
const
2049 if (!aggregate->physicalModuleName().isEmpty()) {
2053 if (cn && !cn->qtVariable().isEmpty()) {
2056 requisites.insert(qtVariableText, *text);
2062
2063
2064
2065
2067 Text *text,
const QString &sinceText)
const
2069 if (!aggregate->since().isEmpty() && text !=
nullptr) {
2072 requisites.insert(sinceText, *text);
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2088 Text &text,
const QString &statusText)
const
2090 auto status{formatStatus(aggregate, m_qdb)};
2096 spanClass = u"deprecated"_s;
2098 spanClass = Utilities::asAsciiPrintable(status.value());
2101 text << Atom(Atom::String, status.value())
2103 "class=\"status %1\""_L1.arg(spanClass))
2105 requisites.insert(statusText, text);
2109
2110
2111
2112
2114 QMap<QString, Text> &requisites,
Text& text,
2115 const QString &headerText)
2117 if (aggregate->includeFile()) {
2119 text << openCodeTag <<
"#include <%1>"_L1.arg(*aggregate->includeFile()) << closeCodeTag;
2120 requisites.insert(headerText, text);
2125
2126
2127
2133 QMap<QString, Text> requisites;
2136 const QString importText =
"Import Statement";
2137 const QString sinceText =
"Since";
2138 const QString inheritedByText =
"Inherited By";
2139 const QString inheritsText =
"Inherits";
2140 const QString nativeTypeText =
"In C++";
2141 const QString statusText =
"Status";
2144 QString logicalModuleVersion;
2149 bool generate_import =
true;
2151 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2155 if (generate_import) {
2159 requisites.insert(importText, text);
2162 qcn
->doc().location().warning(QStringLiteral(
"Could not resolve QML import statement for type '%1'").arg(qcn->name()),
2167 if (!qcn->since().isEmpty()) {
2170 requisites.insert(sinceText, text);
2175 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2179 addNodeLink(text, cn);
2180 requisites.insert(nativeTypeText, text);
2188 QStringList knownTypeNames{qcn->name()};
2190 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2198 knownTypeNames << base->name();
2201 addNodeLink(text, base);
2204 for (
const auto sub : std::as_const(subs)) {
2205 if (knownTypeNames.contains(sub->name())) {
2206 text << Atom(Atom::String,
" (%1)"_L1.arg(base->logicalModuleName()));
2211 requisites.insert(inheritsText, text);
2215 if (!subs.isEmpty()) {
2218 int count = appendSortedQmlNames(text, qcn, knownTypeNames, subs);
2221 requisites.insert(inheritedByText, text);
2225 addStatusToMap(qcn, requisites, text, statusText);
2228 const QStringList requisiteorder {
std::move(importText),
std::move(sinceText),
2229 std::move(nativeTypeText),
std::move(inheritsText),
2230 std::move(inheritedByText),
std::move(statusText)};
2232 if (!requisites.isEmpty())
2233 generateTheTable(requisiteorder, requisites, qcn, marker);
2245 QStringLiteral(
"'\\brief' statement does not end with a full stop."));
2247 generateExtractionMark(node, BriefMark);
2249 generateText(brief, node, marker);
2252 if (!relative || node == relative)
2253 out() <<
" <a href=\"#";
2255 out() <<
" <a href=\"" << linkForNode(node, relative) <<
'#';
2256 out() << registerRef(
"details") <<
"\">More...</a>";
2260 generateExtractionMark(node, EndMark);
2265
2266
2267
2269 QList<Section> *sections)
2273 toc = node
->doc().tableOfContents();
2274 if (tocDepth == 0 || (toc.isEmpty() && !sections && !node
->isModule())) {
2279 int sectionNumber = 1;
2280 int detailsBase = 0;
2285 out() <<
"<div class=\"sidebar\">\n";
2286 out() <<
"<div class=\"toc\">\n";
2287 out() <<
"<h3 id=\"toc\">Contents</h3>\n";
2290 openUnorderedList();
2293 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2294 << registerRef(
"namespaces") <<
"\">Namespaces</a></li>\n";
2297 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2298 << registerRef(
"classes") <<
"\">Classes</a></li>\n";
2301 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#" << registerRef(
"details")
2302 <<
"\">Detailed Description</a></li>\n";
2303 for (
const auto &entry : std::as_const(toc)) {
2304 if (entry->string().toInt() == 1) {
2310 for (
const auto §ion : std::as_const(*sections)) {
2311 if (!section.members().isEmpty()) {
2312 openUnorderedList();
2313 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2314 << registerRef(section.plural()) <<
"\">" << section.title() <<
"</a></li>\n";
2316 if (!section.reimplementedMembers().isEmpty()) {
2317 openUnorderedList();
2318 QString ref = QString(
"Reimplemented ") + section.plural();
2319 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2320 << registerRef(ref.toLower()) <<
"\">"
2321 << QString(
"Reimplemented ") + section.title() <<
"</a></li>\n";
2325 openUnorderedList();
2326 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2327 << registerRef(
"details") <<
"\">Detailed Description</a></li>\n";
2329 for (
const auto &entry : toc) {
2330 if (entry->string().toInt() == 1) {
2337 for (
const auto &atom : toc) {
2338 sectionNumber = atom->string().toInt() + detailsBase;
2341 if (sectionNumber <= tocDepth || tocDepth < 0) {
2342 openUnorderedList();
2344 Text headingText = Text::sectionHeading(atom);
2345 out() <<
"<li class=\"level" << sectionNumber <<
"\">";
2346 out() <<
"<a href=\"" <<
'#' << Tree::refForAtom(atom) <<
"\">";
2347 generateAtomList(headingText.firstAtom(), node, marker,
true, numAtoms);
2348 out() <<
"</a></li>\n";
2351 closeUnorderedList();
2352 out() <<
"</div>\n";
2353 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2354 out() <<
"</div>\n";
2360
2361
2364 out() <<
"<div class=\"sidebar\">";
2365 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2366 out() <<
"</div>\n";
2375 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2376 beginSubPage(aggregate, fileName);
2377 QString title =
"List of All Members for " + aggregate->plainFullName();
2378 generateHeader(title, aggregate, marker);
2380 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2381 out() <<
"<p>This is the complete list of members for ";
2382 generateFullName(aggregate,
nullptr);
2383 out() <<
", including inherited members.</p>\n";
2385 generateSectionList(section, aggregate, marker);
2393
2394
2395
2396
2397
2405 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2406 beginSubPage(aggregate, fileName);
2407 QString title =
"List of All Members for " + aggregate->name();
2408 generateHeader(title, aggregate, marker);
2410 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2411 out() <<
"<p>This is the complete list of members for ";
2412 generateFullName(aggregate,
nullptr);
2413 out() <<
", including inherited members.</p>\n";
2416 for (
int i = 0; i < cknl.size(); i++) {
2420 if (nodes.isEmpty())
2423 out() <<
"<p>The following members are inherited from ";
2424 generateFullName(qcn,
nullptr);
2427 openUnorderedList();
2428 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2429 for (
int j = 0; j < nodes.size(); j++) {
2430 Node *node = nodes[j];
2437 std::function<
void(
Node *)> generate = [&](Node *n) {
2438 out() <<
"<li class=\"fn\" translate=\"no\">";
2439 generateQmlItem(n, aggregate, marker,
true);
2441 out() <<
" [default]";
2442 else if (n->isAttached())
2443 out() <<
" [attached]";
2445 if (n->isPropertyGroup()) {
2447 const QList<Node *> &collective =
2448 static_cast<SharedCommentNode *>(n)->collective();
2449 std::for_each(collective.begin(), collective.end(), generate);
2456 closeUnorderedList();
2473 QString title =
"Obsolete Members for " + aggregate->plainFullName();
2474 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2476 beginSubPage(aggregate, fileName);
2477 generateHeader(title, aggregate, marker);
2479 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2481 out() <<
"<p><b>The following members of class "
2482 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\" translate=\"no\">"
2483 << protectEnc(aggregate->name()) <<
"</a>"
2484 <<
" are deprecated.</b> "
2485 <<
"They are provided to keep old source code working. "
2486 <<
"We strongly advise against using them in new code.</p>\n";
2488 for (
const auto §ion : summary_spv) {
2489 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2490 generateSectionList(*section, aggregate, marker,
true);
2493 for (
const auto §ion : details_spv) {
2494 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2496 const NodeVector &members = section->obsoleteMembers();
2497 for (
const auto &member : members)
2498 generateDetailedMember(member, aggregate, marker);
2507
2508
2509
2510
2519 QString title =
"Obsolete Members for " + aggregate->name();
2520 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2522 beginSubPage(aggregate, fileName);
2523 generateHeader(title, aggregate, marker);
2525 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2527 out() <<
"<p><b>The following members of QML type "
2528 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\">"
2529 << protectEnc(aggregate->name()) <<
"</a>"
2530 <<
" are deprecated.</b> "
2531 <<
"They are provided to keep old source code working. "
2532 <<
"We strongly advise against using them in new code.</p>\n";
2534 for (
const auto §ion : summary_spv) {
2535 QString ref = registerRef(section->title().toLower());
2536 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section->title()) <<
"</h2>\n";
2537 generateQmlSummary(section->obsoleteMembers(), aggregate, marker);
2540 for (
const auto §ion : details_spv) {
2541 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2542 const NodeVector &members = section->obsoleteMembers();
2543 for (
const auto &member : members) {
2544 generateDetailedQmlMember(member, aggregate, marker);
2556 if (classMap.isEmpty())
2560 for (
const auto &it : classMap) {
2561 auto *classe =
static_cast<ClassNode *>(it);
2562 if (classe->baseClasses().isEmpty())
2563 topLevel.insert(classe->name(), classe);
2566 QStack<NodeMap> stack;
2567 stack.push(topLevel);
2570 while (!stack.isEmpty()) {
2571 if (stack.top().isEmpty()) {
2577 generateFullName(child, relative);
2579 stack.top().erase(stack.top().begin());
2582 const auto derivedClasses = child->derivedClasses();
2583 for (
const RelatedClass &d : derivedClasses) {
2584 if (d.m_node && d.m_node->isInAPI())
2585 newTop.insert(d.m_node->name(), d.m_node);
2587 if (!newTop.isEmpty()) {
2596
2597
2598
2600 const NodeList &unsortedNodes, Qt::SortOrder sortOrder)
2602 if (unsortedNodes.isEmpty() || relative ==
nullptr)
2606 bool allInternal =
true;
2607 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2608 for (
auto *node : unsortedNodes) {
2609 const NodeContext context = node->createContext();
2610 if (InclusionFilter::isIncluded(policy, context) && !node->isDeprecated()) {
2611 allInternal =
false;
2612 nmm.insert(node->fullName(relative), node);
2617 out() <<
"<div class=\"table\"><table class=\"annotated\">\n";
2621 if (sortOrder == Qt::DescendingOrder)
2626 for (
const auto *node : std::as_const(nodes)) {
2628 out() <<
"<tr class=\"odd topAlign\">";
2630 out() <<
"<tr class=\"even topAlign\">";
2631 out() <<
"<td class=\"tblName\" translate=\"no\"><p>";
2632 generateFullName(node, relative);
2633 out() <<
"</p></td>";
2635 if (!node->isTextPageNode()) {
2636 Text brief = node->doc().trimmedBriefText(node->name());
2637 if (!brief.isEmpty()) {
2638 out() <<
"<td class=\"tblDescr\"><p>";
2639 generateText(brief, node, marker);
2640 out() <<
"</p></td>";
2641 }
else if (!node->reconstitutedBrief().isEmpty()) {
2642 out() <<
"<td class=\"tblDescr\"><p>";
2643 out() << node->reconstitutedBrief();
2644 out() <<
"</p></td>";
2647 out() <<
"<td class=\"tblDescr\"><p>";
2648 if (!node->reconstitutedBrief().isEmpty()) {
2649 out() << node->reconstitutedBrief();
2651 out() << protectEnc(node->doc().briefText().toString());
2652 out() <<
"</p></td>";
2656 out() <<
"</table></div>\n";
2660
2661
2662
2666 const auto &uniqueKeys = nmm.uniqueKeys();
2667 for (
const QString &name : uniqueKeys) {
2668 if (!name.isEmpty()) {
2669 out() <<
"<h2 id=\"" << registerRef(name.toLower()) <<
"\">" << protectEnc(name)
2672 generateAnnotatedList(relative, marker, nmm.values(name));
2677
2678
2679
2680
2681
2682
2683
2684
2685
2688 const QString &commonPrefix)
2693 const int NumParagraphs = 37;
2694 qsizetype commonPrefixLen = commonPrefix.size();
2697
2698
2699
2700
2701
2703 QString paragraphName[NumParagraphs + 1];
2704 QSet<
char> usedParagraphNames;
2706 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
2707 QStringList pieces = c.key().split(
"::");
2708 int idx = commonPrefixLen;
2709 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
2711 QString last = pieces.last().toLower();
2712 QString key = last.mid(idx);
2714 int paragraphNr = NumParagraphs - 1;
2716 if (key[0].digitValue() != -1) {
2717 paragraphNr = key[0].digitValue();
2718 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
2719 paragraphNr = 10 + key[0].unicode() -
'a';
2722 paragraphName[paragraphNr] = key[0].toUpper();
2723 usedParagraphNames.insert(key[0].toLower().cell());
2724 paragraph[paragraphNr].insert(last, c.value());
2728
2729
2730
2731
2732
2733
2734
2735 qsizetype paragraphOffset[NumParagraphs + 1];
2736 paragraphOffset[0] = 0;
2737 for (
int i = 0; i < NumParagraphs; i++)
2738 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
2741
2742
2743 if (includeAlphabet) {
2744 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2745 for (
int i = 0; i < 26; i++) {
2747 if (usedParagraphNames.contains(
char(
'a' + i)))
2748 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2750 out() <<
"</b></p>\n";
2754
2755
2756 out() <<
"<div class=\"flowListDiv\" translate=\"no\">\n";
2760 QHash<QString,
int> nameOccurrences;
2761 for (
const auto &[key, node] : nmm.asKeyValueRange()) {
2762 QStringList pieces{node->fullName(relative).split(
"::"_L1)};
2763 const QString &name{pieces.last()};
2764 nameOccurrences[name]++;
2768 int curParOffset = 0;
2770 for (
int i = 0; i < nmm.size(); i++) {
2771 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
2777
2778
2779 if (curParOffset == 0) {
2783 out() <<
"<dl class=\"flowList odd\">";
2785 out() <<
"<dl class=\"flowList even\">";
2786 out() <<
"<dt class=\"alphaChar\"";
2787 if (includeAlphabet)
2788 out() << QString(
" id=\"%1\"").arg(paragraphName[curParNr][0].toLower());
2789 out() <<
"><b>" << paragraphName[curParNr] <<
"</b></dt>\n";
2793
2794
2796 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
2797 NodeMultiMap::Iterator it;
2798 NodeMultiMap::Iterator next;
2799 it = paragraph[curParNr].begin();
2800 for (
int j = 0; j < curParOffset; j++)
2805
2806
2807
2808 out() <<
"<a href=\"" << linkForNode(it.value(), relative) <<
"\">";
2810 QString fileName = fileBase(it.value()) +
"-obsolete." + fileExtension();
2812 if (useOutputSubdirs())
2813 link =
"../%1/"_L1.arg(it.value()->tree()->physicalModuleName());
2815 out() <<
"<a href=\"" << link <<
"\">";
2818 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
2819 const auto &name{pieces.last()};
2822 if (nameOccurrences[name] > 1) {
2823 const QString moduleName = it.value()->isQmlNode() ? it.value()->logicalModuleName()
2824 : it.value()->tree()->camelCaseModuleName();
2825 pieces.last().append(
": %1"_L1.arg(moduleName));
2828 out() << protectEnc(pieces.last());
2830 if (pieces.size() > 1) {
2832 generateFullName(it.value()->parent(), relative);
2842 out() <<
"</div>\n";
2847 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2848 for (
int i = 0; i < 26; i++) {
2850 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2852 out() <<
"</b></p>\n";
2854 char nextLetter =
'a';
2856 out() <<
"<ul translate=\"no\">\n";
2858 for (
auto fnMap = funcIndex.constBegin(); fnMap != funcIndex.constEnd(); ++fnMap) {
2859 const QString &key = fnMap.key();
2860 const QChar firstLetter = key.isEmpty() ? QChar(
'A') : key.front();
2861 Q_ASSERT_X(firstLetter.unicode() < 256,
"generateFunctionIndex",
2862 "Only valid C++ identifiers were expected");
2863 const char currentLetter = firstLetter.isLower() ? firstLetter.unicode() : nextLetter - 1;
2865 if (currentLetter < nextLetter) {
2869 while (nextLetter < currentLetter)
2870 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2871 Q_ASSERT(nextLetter == currentLetter);
2872 out() << QStringLiteral(
"<li id=\"%1\">").arg(nextLetter++);
2874 out() << protectEnc(key) <<
':';
2876 for (
auto it = (*fnMap).constBegin(); it != (*fnMap).constEnd(); ++it) {
2878 generateFullName((*it)->parent(), relative, *it);
2882 while (nextLetter <=
'z')
2883 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2890 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
2891 Text text = it.key();
2892 generateText(text, relative, marker);
2896 generateFullName(it.value(), relative);
2899 }
while (it != legaleseTexts.constEnd() && it.key() == text);
2907 QString marked = marker->markedUpQmlItem(node, summary);
2908 marked.replace(
"@param>",
"i>");
2910 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
2911 .arg(summary ?
"summary"_L1 :
"details"_L1));
2912 marked.replace(
"</@extra>",
"</code>");
2916 marked.remove(
"<@name>");
2917 marked.remove(
"</@name>");
2918 marked.remove(
"<@type>");
2919 marked.remove(
"</@type>");
2921 out() << highlightedCode(marked, relative,
false, Genus::QML);
2925
2926
2927
2928
2929
2930
2931
2939 if (sortOrder == Qt::DescendingOrder)
2944 for (
const auto *node : std::as_const(members)) {
2945 out() <<
"<li translate=\"no\">";
2946 generateFullName(node,
nullptr);
2954 const QString &selector, Qt::SortOrder sortOrder)
2958 if (selector == QLatin1String(
"overviews"))
2960 else if (selector == QLatin1String(
"cpp-modules"))
2962 else if (selector == QLatin1String(
"qml-modules"))
2967 const auto collectionList = cnm.values();
2968 nodeList.reserve(collectionList.size());
2969 for (
auto *collectionNode : collectionList)
2970 nodeList.append(collectionNode);
2971 generateAnnotatedList(relative, marker, nodeList, sortOrder);
2974
2975
2976
2977
2980 QStringLiteral(
"\\generatelist {%1} is only allowed in \\group, "
2981 "\\module and \\qmlmodule comments.")
2985 auto *node =
const_cast<
Node *>(relative);
2987 if (!collectionNode)
2990 generateAnnotatedList(collectionNode, marker, collectionNode->members(), sortOrder);
2996 bool alignNames =
true;
2997 if (!nv.isEmpty()) {
2998 bool twoColumn =
false;
2999 if (nv.first()->isProperty()) {
3000 twoColumn = (nv.size() >= 5);
3004 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3007 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3008 <<
"<tr><td class=\"topAlign\">";
3013 for (
const auto &member : nv) {
3016 out() <<
"<tr><td class=\"memItemLeft rightAlign topAlign\"> ";
3018 if (twoColumn && i == (nv.size() + 1) / 2)
3019 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3020 out() <<
"<li class=\"fn\" translate=\"no\">";
3023 generateSynopsis(member, relative, marker, Section::Summary, alignNames);
3025 out() <<
"</td></tr>\n";
3031 out() <<
"</table></div>\n";
3035 out() <<
"</td></tr>\n</table></div>\n";
3043 bool alignNames =
true;
3046 if (!members.isEmpty()) {
3047 bool hasPrivateSignals =
false;
3048 bool isInvokable =
false;
3049 bool twoColumn =
false;
3052 twoColumn = (members.size() >= 16);
3053 }
else if (members.first()->isProperty()) {
3054 twoColumn = (members.size() >= 5);
3058 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3061 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3062 <<
"<tr><td class=\"topAlign\">";
3067 for (
const auto &member : members) {
3070 if (member->name().isEmpty())
3074 out() <<
"<tr><td class=\"memItemLeft topAlign rightAlign\"> ";
3076 if (twoColumn && i == (members.size() + 1) / 2)
3077 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3078 out() <<
"<li class=\"fn\" translate=\"no\">";
3081 generateSynopsis(member, relative, marker, section.style(), alignNames);
3082 if (member->isFunction()) {
3083 const auto *fn =
static_cast<
const FunctionNode *>(member);
3084 if (fn->isPrivateSignal()) {
3085 hasPrivateSignals =
true;
3087 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3088 }
else if (fn->isInvokable()) {
3091 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3095 out() <<
"</td></tr>\n";
3101 out() <<
"</table></div>\n";
3105 out() <<
"</td></tr>\n</table></div>\n";
3108 if (hasPrivateSignals)
3116 && !section.inheritedMembers().isEmpty()) {
3118 generateSectionInheritedList(section, relative);
3125 const QList<std::pair<Aggregate *,
int>> &inheritedMembers = section.inheritedMembers();
3126 for (
const auto &member : inheritedMembers) {
3127 out() <<
"<li class=\"fn\" translate=\"no\">";
3128 out() << member.second <<
' ';
3129 if (member.second == 1) {
3130 out() << section.singular();
3132 out() << section.plural();
3134 out() <<
" inherited from <a href=\"" << fileName(member.first) <<
'#'
3135 << Generator::cleanRef(section.title().toLower()) <<
"\">"
3136 << protectEnc(member.first->plainFullName(relative)) <<
"</a></li>\n";
3143 QString marked = marker->markedUpSynopsis(node, relative, style);
3144 marked.replace(
"@param>",
"i>");
3147 marked.remove(
"<@name>");
3148 marked.remove(
"</@name>");
3152 static const QRegularExpression extraRegExp(
"<@extra>.*</@extra>",
3153 QRegularExpression::InvertedGreedinessOption);
3154 marked.remove(extraRegExp);
3156 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
3157 .arg(style == Section::Summary ?
"summary"_L1 :
"details"_L1));
3158 marked.replace(
"</@extra>",
"</code>");
3162 marked.remove(
"<@type>");
3163 marked.remove(
"</@type>");
3166 out() << highlightedCode(marked, relative, alignNames);
3169QString
HtmlGenerator::highlightedCode(
const QString &markedCode,
const Node *relative,
3170 bool alignNames, Genus genus)
3172 QString src = markedCode;
3174 html.reserve(src.size());
3178 const QChar charLangle =
'<';
3179 const QChar charAt =
'@';
3181 static const QString typeTag(
"type");
3182 static const QString headerTag(
"headerfile");
3183 static const QString funcTag(
"func");
3184 static const QString linkTag(
"link");
3190 for (
int i = 0, srcSize = src.size(); i < srcSize;) {
3191 if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
3192 if (alignNames && !done) {
3193 html += QLatin1String(
"</td><td class=\"memItemRight bottomAlign\">");
3197 if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) {
3198 html += QLatin1String(
"<b>");
3199 const Node *n =
static_cast<
const Node*>(Utilities::nodeForString(par1.toString()));
3200 QString link = linkForNode(n, relative);
3201 addLink(link, arg, &html);
3202 html += QLatin1String(
"</b>");
3203 }
else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
3204 const FunctionNode *fn =
m_qdb->findFunctionNode(par1.toString(), relative, genus);
3205 QString link = linkForNode(fn, relative);
3206 addLink(link, arg, &html);
3207 par1 = QStringView();
3208 }
else if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
3209 par1 = QStringView();
3210 const Node *n =
m_qdb->findTypeNode(arg.toString(), relative, genus);
3211 html += QLatin1String(
"<span class=\"type\">");
3214 addLink(linkForNode(n, relative), arg, &html);
3218 addLink(linkForNode(n, relative), arg, &html);
3219 html += QLatin1String(
"</span>");
3220 }
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
3221 par1 = QStringView();
3222 if (arg.startsWith(QLatin1Char(
'&')))
3225 const Node *n =
m_qdb->findNodeForInclude(QStringList(arg.toString()));
3226 if (n && n != relative)
3227 addLink(linkForNode(n, relative), arg, &html);
3236 html += src.at(i++);
3253 html.reserve(src.size());
3254 static const QLatin1String spanTags[] = {
3255 QLatin1String(
"comment>"), QLatin1String(
"<span class=\"comment\">"),
3256 QLatin1String(
"preprocessor>"), QLatin1String(
"<span class=\"preprocessor\">"),
3257 QLatin1String(
"string>"), QLatin1String(
"<span class=\"string\">"),
3258 QLatin1String(
"char>"), QLatin1String(
"<span class=\"char\">"),
3259 QLatin1String(
"number>"), QLatin1String(
"<span class=\"number\">"),
3260 QLatin1String(
"op>"), QLatin1String(
"<span class=\"operator\">"),
3261 QLatin1String(
"type>"), QLatin1String(
"<span class=\"type\">"),
3262 QLatin1String(
"name>"), QLatin1String(
"<span class=\"name\">"),
3263 QLatin1String(
"keyword>"), QLatin1String(
"<span class=\"keyword\">")
3268 for (
int i = 0, n = src.size(); i < n;) {
3269 if (src.at(i) == QLatin1Char(
'<')) {
3270 if (src.at(i + 1) == QLatin1Char(
'@')) {
3272 bool handled =
false;
3273 for (
int k = 0; k != nTags; ++k) {
3274 const QLatin1String &tag = spanTags[2 * k];
3275 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3276 html += spanTags[2 * k + 1];
3284 while (i < n && src.at(i) != QLatin1Char(
'>'))
3289 }
else if (src.at(i + 1) == QLatin1Char(
'/') && src.at(i + 2) == QLatin1Char(
'@')) {
3291 bool handled =
false;
3292 for (
int k = 0; k != nTags; ++k) {
3293 const QLatin1String &tag = spanTags[2 * k];
3294 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3295 html += QLatin1String(
"</span>");
3303 while (i < n && src.at(i) != QLatin1Char(
'>'))
3322 if (match.hasMatch()) {
3324 qsizetype leftParenLoc = match.capturedStart(1);
3325 out() << protectEnc(atom->string().left(leftParenLoc));
3327 out() << protectEnc(atom->string().mid(leftParenLoc));
3331 out() << protectEnc(atom->string());
3336 return protect(string);
3341 if (string.isEmpty())
3345 if (html.isEmpty()) {
3352 qsizetype n = string.size();
3354 for (
int i = 0; i < n; ++i) {
3355 QChar ch = string.at(i);
3357 if (ch == QLatin1Char(
'&')) {
3359 }
else if (ch == QLatin1Char(
'<')) {
3361 }
else if (ch == QLatin1Char(
'>')) {
3363 }
else if (ch == QChar(8211)) {
3365 }
else if (ch == QChar(8212)) {
3367 }
else if (ch == QLatin1Char(
'"')) {
3370 if (!html.isEmpty())
3375 if (!html.isEmpty())
3384 QString result = Generator::fileBase(node);
3386 result += QLatin1String(
"-obsolete");
3393 return node->name();
3394 return Generator::fileName(node);
3398 const Node *actualNode)
3400 if (actualNode ==
nullptr)
3401 actualNode = apparentNode;
3402 bool link = !linkForNode(actualNode, relative).isEmpty();
3404 out() <<
"<a href=\"" << linkForNode(actualNode, relative);
3406 out() <<
"\" class=\"obsolete";
3409 out() << protectEnc(apparentNode->fullName(relative));
3415
3416
3417
3424 const auto srcLink = Config::instance().getSourceLink();
3425 if (!srcLink.enabled)
3430 if (loc
.isEmpty() || srcLink.baseUrl.isEmpty() || srcLink.rootPath.isEmpty())
3433 QString srcUrl{srcLink.baseUrl};
3434 if (!srcUrl.contains(
'\1'_L1)) {
3435 if (!srcUrl.endsWith(
'/'_L1))
3440 QDir rootDir{srcLink.rootPath};
3441 srcUrl.replace(
'\1'_L1, rootDir.relativeFilePath(loc.filePath()));
3442 srcUrl.replace(
'\2'_L1, QString::number(loc.lineNo()));
3443 const auto &description{
"View declaration of this %1"_L1.arg(node->nodeTypeString())};
3444 out() <<
"<a class=\"srclink\" href=\"%1\" title=\"%2\">%3</a>"_L1
3445 .arg(srcUrl, description, srcLink.linkText);
3452 generateExtractionMark(node, MemberMark);
3453 QString nodeRef =
nullptr;
3456 const QList<Node *> &collective = scn->collective();
3457 if (collective.size() > 1)
3458 out() <<
"<div class=\"fngroup\">\n";
3459 for (
const auto *sharedNode : collective) {
3460 nodeRef = refForNode(sharedNode);
3461 out() << R"(<h3 class="fn fngroupitem" translate="no" id=")" << nodeRef <<
"\">";
3462 generateSynopsis(sharedNode, relative, marker, Section::Details);
3463 generateSourceLink(sharedNode);
3466 if (collective.size() > 1)
3470 nodeRef = refForNode(node);
3472 out() << R"(<h3 class="flags" id=")" << nodeRef <<
"\">";
3476 generateSourceLink(node);
3479 out() << R"(<h3 class="fn" translate="no" id=")" << nodeRef <<
"\">";
3481 generateSourceLink(node);
3482 out() <<
"</h3>" <<
'\n';
3489 const auto *func =
static_cast<
const FunctionNode *>(node);
3499 const auto property =
static_cast<
const PropertyNode *>(node);
3509 out() <<
"<p><b>Access functions:</b></p>\n";
3510 generateSectionList(section, node, marker);
3517 out() <<
"<p><b>Notifier signal:</b></p>\n";
3518 generateSectionList(notifiers, node, marker);
3522 const auto *enumTypeNode =
static_cast<
const EnumNode *>(node);
3524 out() <<
"<p>The " << protectEnc(enumTypeNode->flagsType()->name())
3525 <<
" type is a typedef for "
3526 <<
"<a href=\"" << m_qflagsHref <<
"\">QFlags</a><"
3527 << protectEnc(enumTypeNode->name()) <<
">. It stores an OR combination of "
3528 << protectEnc(enumTypeNode->name()) <<
" values.</p>\n";
3531 generateAlsoList(node, marker);
3532 generateExtractionMark(node, EndMark);
3536
3537
3538
3539
3546 if (!m_link.isEmpty())
3547 out() <<
"<a href=\"" << m_link <<
"\" translate=\"no\">";
3555 if (m_link.isEmpty())
3558 const QString &translate_attr =
3559 (node && isApiGenus(node->genus())) ?
" translate=\"no\""_L1 :
""_L1;
3561 if (node ==
nullptr || (relative !=
nullptr && node->status() == relative->status()))
3562 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3563 else if (node->isDeprecated())
3564 out() <<
"<a href=\"" << m_link <<
"\" class=\"obsolete\"%1>"_L1.arg(translate_attr);
3566 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3577 if (!m_link.isEmpty())
3582
3583
3584
3588 if (!members.isEmpty()) {
3590 for (
const auto &member : members) {
3591 out() <<
"<li class=\"fn\" translate=\"no\">";
3592 generateQmlItem(member, relative, marker,
true);
3593 if (member->isPropertyGroup()) {
3594 const auto *scn =
static_cast<
const SharedCommentNode *>(member);
3595 if (scn->count() > 0) {
3597 const QList<Node *> &sharedNodes = scn->collective();
3598 for (
const auto &node : sharedNodes) {
3599 if (node->isQmlProperty()) {
3600 out() <<
"<li class=\"fn\" translate=\"no\">";
3601 generateQmlItem(node, relative, marker,
true);
3615
3616
3619 const QString id = refForNode(scn);
3620 out() << R"(<h3 class="fn qml-member qml-property-group" translate="no" id=")"
3622 <<
"<b>" << scn->name() <<
" group</b>"
3627
3628
3629
3633 generateExtractionMark(node, MemberMark);
3635 auto generateQmlProperty = [&](
Node *n,
bool isGroupItem =
false) {
3636 const QString nodeRef = refForNode(n);
3637 const auto cssClasses = isGroupItem ?
"fn qml-member qml-property fngroupitem"_L1 :
"fn qml-member qml-property"_L1;
3638 out() << R"(<h3 class=")"_L1 << cssClasses << R"(" translate="no" id=")"_L1 << nodeRef <<
"\">"_L1;
3639 generateQmlItem(n, relative, marker,
false);
3640 generateSourceLink(n);
3641 out() <<
"</h3>\n"_L1;
3644 auto generateQmlMethod = [&](
Node *n,
bool isGroupItem =
false) {
3645 const QString nodeRef = refForNode(n);
3646 const auto cssClasses = isGroupItem ?
"fn qml-member qml-method fngroupitem"_L1 :
"fn qml-member qml-method"_L1;
3647 out() << R"(<h3 class=")"_L1 << cssClasses << R"(" translate="no" id=")"_L1 << nodeRef <<
"\">"_L1;
3649 generateSourceLink(n);
3650 out() <<
"</h3>\n"_L1;
3655 const auto shared = scn->collective();
3658 emitGroupHeader(scn);
3660 const bool isGroup = shared.size() > 1;
3663 out() <<
"<div class=\"fngroup\">\n"_L1;
3665 for (
auto *child : std::as_const(shared)) {
3666 if (child->isQmlProperty())
3667 generateQmlProperty(child, isGroup);
3669 generateQmlMethod(child, isGroup);
3673 out() <<
"</div>"_L1;
3676 generateQmlProperty(node);
3678 generateQmlMethod(node);
3685 generateAlsoList(node, marker);
3686 generateExtractionMark(node, EndMark);
3689void HtmlGenerator::generateExtractionMark(
const Node *node, ExtractionMarkType markType)
3691 if (markType != EndMark) {
3692 out() <<
"<!-- $$$" + node->name();
3693 if (markType == MemberMark) {
3695 const auto *func =
static_cast<
const FunctionNode *>(node);
3698 out() <<
"[overload1]";
3703 const auto *prop =
static_cast<
const PropertyNode *>(node);
3705 for (
const auto *propFuncNode : list) {
3706 if (propFuncNode->isFunction()) {
3707 const auto *func =
static_cast<
const FunctionNode *>(propFuncNode);
3708 out() <<
"$$$" + func->name()
3709 + func->parameters().rawSignature().remove(
' ');
3713 const auto *enumNode =
static_cast<
const EnumNode *>(node);
3714 const auto &items = enumNode->items();
3715 for (
const auto &item : items)
3716 out() <<
"$$$" + item.name();
3718 }
else if (markType == BriefMark) {
3720 }
else if (markType == DetailedDescriptionMark) {
3721 out() <<
"-description";
3725 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...
virtual bool isLinkAtom() const
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.
static void quoteFromFile(const Location &location, Quoter "er, ResolvedFile resolved_file)
bool hasTableOfContents() const
Text briefText(bool inclusive=false) 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.
signed short overloadNumber() const
Returns the overload number for this function.
const Parameters & parameters() const
bool hasOverloads() const
Returns true if this function has overloads.
bool hasAssociatedProperties() const
bool generateComparisonCategory(const Node *node, CodeMarker *marker=nullptr)
FileResolver & file_resolver
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.
bool generateComparisonList(const Node *node)
Generates a list of types that compare to node with the comparison category that applies for the rela...
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.
bool m_threeColumnEnumValueTable
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()
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...
QString format() override
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.
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.
const PageNode * navigationParent() const
bool noAutoList() const
Returns the value of the no auto-list flag.
This class describes one instance of using the Q_PROPERTY macro.
const NodeList & getters() const
const NodeList & resetters() const
const NodeList & setters() const
PropertyType propertyType() const
const NodeList & notifiers() const
NodeList functions() const
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
NodeMapMap & getFunctionIndex()
Returns the function index.
TextToNodeMap & getLegaleseTexts()
Returns a reference to the collection of legalese texts.
NodeMultiMap & getAttributions()
Returns a reference to the multimap of attribution nodes.
static QDocDatabase * qdocDB()
Creates the singleton.
NodeMultiMap & getCppClasses()
Returns a reference to the map of all C++ classes.
void mergeCollections(NodeType type, CNMap &cnm, const Node *relative)
Finds all the collection nodes of the specified type and merges them into the collection node map cnm...
NodeMultiMap & getExamples()
Returns a reference to the multimap of example nodes.
const CollectionNode * getModuleNode(const Node *relative)
Returns the collection node representing the module that relative node belongs to,...
void mergeCollections(CollectionNode *c)
Finds all the collection nodes with the same name and type as c and merges their members into the mem...
ClassNode * classNode() 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)
ClassNodesList & classNodesList()
const Aggregate * aggregate() const
const NodeVector & members() const
A class for creating vectors of collections for documentation.
Aggregate * aggregate() const
Sections(Aggregate *aggregate)
This constructor builds the vectors of sections based on the type of the aggregate node.
SectionVector & stdCppClassSummarySections()
SectionVector & stdQmlTypeSummarySections()
SectionVector & stdDetailsSections()
SectionVector & stdCppClassDetailsSections()
SectionVector & stdQmlTypeDetailsSections()
SectionVector & sinceSections()
Sections(const NodeMultiMap &nsmap)
This constructor builds a vector of 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 & stdSummarySections()
static Section & allMembersSection()
Table of contents writer.
This class handles the generation of the QDoc tag files.
const QString & camelCaseModuleName() const
static bool isThreeColumnEnumValueTable(const Atom *atom)
Determines whether the list atom should be shown with three columns (constant-value-description).
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 const Atom closeCodeTag
static void addLink(const QString &linkTarget, QStringView nestedStuff, QString *res)
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
std::pair< const QmlTypeNode *, NodeVector > ClassNodes
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.