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
240 Node *qflags = m_qdb->findClassNode(QStringList(
"QFlags"_L1));
242 m_qflagsHref = linkForNode(qflags,
nullptr);
246 const QString fileBase =
"%1/%2"_L1.arg(
248 m_project.toLower().simplified().replace(
' '_L1,
'-'_L1)
250 if (!config->generating())
251 m_qdb->generateIndex(
"%1.index"_L1.arg(fileBase), m_projectUrl, m_projectDescription);
257 const QString &rootTitle = m_landingpage.isEmpty() ? m_homepage : m_landingpage;
258 tocWriter.generateTOC(
"%1_toc.xml"_L1.arg(fileBase), rootTitle);
260
261
262 if (!tagFile_.isEmpty()) {
264 tagFileWriter.generateTagFile(tagFile_,
this);
270
271
274 SubTitleSize subTitleSize = LargeSubTitle;
275 QString fullTitle = en->fullTitle();
277 beginSubPage(en, linkForExampleFile(resolved_file.get_query()));
278 generateHeader(fullTitle, en, marker);
279 generateTitle(fullTitle, Text() << en->subtitle(), subTitleSize, en, marker);
284 QString code = quoter.quoteTo(en->location(), QString(), QString());
285 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
289 generateText(text, en, codeMarker);
294
295
298 qsizetype idx, skipAhead = 0;
299 static bool in_para =
false;
300 Genus genus = Genus::DontCare;
304 QString name = atom->string();
305 if (relative && relative->name() == name.replace(QLatin1String(
"()"), QLatin1String())) {
306 out() << protectEnc(atom->string());
315 const Node *node =
nullptr;
316 QString link = getAutoLink(atom, relative, &node, genus);
317 if (link.isEmpty()) {
322 QStringLiteral(
"Can't autolink to '%1'").arg(atom->string()));
327 if (link.isEmpty()) {
328 out() << protectEnc(atom->string());
330 beginLink(link, node, relative);
335 out() << protectEnc(atom->string());
342 skipAhead = skipAtoms(atom, Atom::BriefRight);
357 out() << protectEnc(plainCode(atom->string()));
361 out() <<
"<p class=\"figCaption\">";
372 out() <<
"<pre class=\"qml\" translate=\"no\">"
373 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative,
375 m_codePrefix, m_codeSuffix)
379 out() <<
"<pre class=\"cpp\" translate=\"no\">"
380 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative),
381 m_codePrefix, m_codeSuffix)
385 out() <<
"<pre class=\"cpp plain\" translate=\"no\">"
386 << trimmedTrailing(protectEnc(plainCode(indent(m_codeIndent, atom->string()))),
387 m_codePrefix, m_codeSuffix)
391 out() <<
"<details>\n";
392 if (!atom->string().isEmpty())
393 out() <<
"<summary>" << protectEnc(atom->string()) <<
"</summary>\n";
395 out() <<
"<summary>...</summary>\n";
398 out() <<
"</details>\n";
402 if (!atom->string().isEmpty())
403 out() <<
' ' << atom->string();
426 if (atom->string().startsWith(
"span "))
427 out() <<
'<' + atom->string() <<
'>';
429 out() << formattingLeftMap()[atom->string()];
437 const Node *node{
nullptr};
438 const Atom tm_link(Atom::NavLink, m_trademarkspage);
439 if (
const auto &link = getLink(&tm_link, relative, &node);
440 !link.isEmpty() && node != relative)
441 out() <<
"<a href=\"%1\">%2</a>"_L1.arg(link, formattingRightMap()[atom->string()]);
443 out() << formattingRightMap()[atom->string()];
446 }
else if (atom->string().startsWith(
"span ")) {
449 out() << formattingRightMap()[atom->string()];
453 if (
const auto *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group); cn)
454 generateList(cn, marker, atom->string(), Generator::sortOrder(atom->strings().last()));
457 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
458 if (atom->string() == QLatin1String(
"annotatedclasses")) {
459 generateAnnotatedList(relative, marker, m_qdb->getCppClasses().values(), sortOrder);
460 }
else if (atom->string() == QLatin1String(
"annotatedexamples")) {
462 }
else if (atom->string() == QLatin1String(
"annotatedattributions")) {
464 }
else if (atom->string() == QLatin1String(
"classes")) {
465 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true,
467 }
else if (atom->string().contains(
"classes ")) {
468 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
469 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true, rootName);
470 }
else if (atom->string() == QLatin1String(
"qmlvaluetypes")
471 || atom->string() == QLatin1String(
"qmlbasictypes")) {
472 generateCompactList(Generic, relative, m_qdb->getQmlValueTypes(),
true,
474 }
else if (atom->string() == QLatin1String(
"qmltypes")) {
475 generateCompactList(Generic, relative, m_qdb->getQmlTypes(),
true, QStringLiteral(
""));
476 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
478 QString moduleName = atom->string().mid(idx + 8).trimmed();
480 if (
const auto *cn = qdb->getCollectionNode(moduleName, moduleType)) {
482 switch (moduleType) {
486 generateAnnotatedList(relative, marker, map.values(), sortOrder);
489 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
493 generateAnnotatedList(relative, marker, map.values(), sortOrder);
496 generateAnnotatedList(relative, marker, cn->members(), sortOrder);
500 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
502 }
else if (atom->string() == QLatin1String(
"obsoleteclasses")) {
503 generateCompactList(Generic, relative, m_qdb->getObsoleteClasses(),
false,
504 QStringLiteral(
"Q"));
505 }
else if (atom->string() == QLatin1String(
"obsoleteqmltypes")) {
506 generateCompactList(Generic, relative, m_qdb->getObsoleteQmlTypes(),
false,
508 }
else if (atom->string() == QLatin1String(
"obsoletecppmembers")) {
509 generateCompactList(Obsolete, relative, m_qdb->getClassesWithObsoleteMembers(),
false,
510 QStringLiteral(
"Q"));
511 }
else if (atom->string() == QLatin1String(
"obsoleteqmlmembers")) {
512 generateCompactList(Obsolete, relative, m_qdb->getQmlTypesWithObsoleteMembers(),
false,
514 }
else if (atom->string() == QLatin1String(
"functionindex")) {
515 generateFunctionIndex(relative);
516 }
else if (atom->string() == QLatin1String(
"attributions")) {
517 generateAnnotatedList(relative, marker, m_qdb->getAttributions().values(), sortOrder);
518 }
else if (atom->string() == QLatin1String(
"legalese")) {
519 generateLegaleseList(relative, marker);
520 }
else if (atom->string() == QLatin1String(
"overviews")) {
521 generateList(relative, marker,
"overviews", sortOrder);
522 }
else if (atom->string() == QLatin1String(
"cpp-modules")) {
523 generateList(relative, marker,
"cpp-modules", sortOrder);
524 }
else if (atom->string() == QLatin1String(
"qml-modules")) {
525 generateList(relative, marker,
"qml-modules", sortOrder);
526 }
else if (atom->string() == QLatin1String(
"namespaces")) {
527 generateAnnotatedList(relative, marker, m_qdb->getNamespaces().values(), sortOrder);
528 }
else if (atom->string() == QLatin1String(
"related")) {
529 generateList(relative, marker,
"related", sortOrder);
533 if (!generateGroupList(
const_cast<CollectionNode *>(cn), sortOrder))
535 QString(
"'\\generatelist %1' group is empty").arg(atom->string()));
538 QString(
"'\\generatelist %1' no such group").arg(atom->string()));
553 for (
const auto §ion : sinceSections) {
554 if (!section.members().isEmpty()) {
556 <<
"<a href=\"#" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
557 << section.title() <<
"</a></li>\n";
563 for (
const auto §ion : sinceSections) {
564 if (!section.members().isEmpty()) {
565 out() <<
"<h3 id=\"" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
566 << protectEnc(section.title()) <<
"</h3>\n";
567 if (index == Sections::SinceClasses)
568 generateCompactList(Generic, relative, ncmap,
false, QStringLiteral(
"Q"));
569 else if (index == Sections::SinceQmlTypes)
570 generateCompactList(Generic, relative, nqcmap,
false, QStringLiteral(
""));
571 else if (index == Sections::SinceMemberFunctions
572 || index == Sections::SinceQmlMethods
573 || index == Sections::SinceQmlProperties) {
575 QMap<QString, NodeMultiMap> parentmaps;
577 const QList<Node *> &members = section.members();
578 for (
const auto &member : members) {
579 QString parent_full_name = (*member).parent()->fullName();
581 auto parent_entry = parentmaps.find(parent_full_name);
582 if (parent_entry == parentmaps.end())
583 parent_entry = parentmaps.insert(parent_full_name, NodeMultiMap());
584 parent_entry->insert(member->name(), member);
587 for (
auto map = parentmaps.begin(); map != parentmaps.end(); ++map) {
588 NodeVector nv = map->values().toVector();
589 auto parent = nv.front()->parent();
591 out() << ((index == Sections::SinceMemberFunctions) ?
"<p>Class " :
"<p>QML Type ");
593 out() <<
"<a href=\"" << linkForNode(parent, relative) <<
"\" translate=\"no\">";
594 QStringList pieces = parent->fullName().split(
"::");
595 out() << protectEnc(pieces.last());
599 generateSection(nv, relative, marker);
602 }
else if (index == Sections::SinceEnumValues) {
603 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
604 const auto map_it = m_qdb->newEnumValueMaps().constFind(atom->string());
605 for (
auto it = map_it->cbegin(); it != map_it->cend(); ++it) {
606 out() <<
"<tr><td class=\"memItemLeft\"> enum value </td><td class=\"memItemRight\">"
607 <<
"<b><a href=\"" << linkForNode(it.value(),
nullptr) <<
"\">"
608 << it.key() <<
"</a></b></td></tr>\n";
610 out() <<
"</table></div>\n";
612 generateSection(section.members(), relative, marker);
630 out() <<
"<p class=\"centerAlign\">";
632 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
633 if (!maybe_resolved_file) {
635 relative->location().warning(
636 QStringLiteral(
"Missing image: %1").arg(protectEnc(atom->string())));
637 out() <<
"<font color=\"red\">[Missing image " << protectEnc(atom->string())
641 QString file_name{QFileInfo{file.get_path()}.fileName()};
660 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
663 out() <<
"<img src=\"" <<
"images/" + protectEnc(file_name) <<
'"';
665 const QString altAndTitleText = protectEnc(text);
666 out() <<
" alt=\"" << altAndTitleText;
668 out() <<
"\" title=\"" << altAndTitleText;
672 m_helpProjectWriter->addExtraFile(
"images/" + file_name);
673 setImageFileName(relative,
"images/" + file_name);
685 QString admonType = atom->typeString();
688 out() <<
"<div class=\"admonition " << admonType.toLower() <<
"\">\n"
691 out() << admonType <<
": ";
701 out() <<
"<div class=\"LegaleseLeft\">";
715 const Node *node =
nullptr;
716 QString link = getLink(atom, relative, &node);
721 QStringLiteral(
"Can't link to '%1'").arg(atom->string()));
723 beginLink(link, node, relative);
727 QString link = linkForExampleFile(atom->string());
732 QString link = atom->string();
733 link =
"images/used-in-examples/" + link;
738 const Node *node =
static_cast<
const Node*>(Utilities::nodeForString(atom->string()));
739 beginLink(linkForNode(node, relative), node, relative);
752 out() << R"(<div class="table"><table class="valuelist">)";
756 out() << R"(<tr valign="top" class="odd">)";
758 out() << R"(<tr valign="top" class="even">)";
760 out() <<
"<th class=\"tblConst\">Constant</th>";
764 out() <<
"<th class=\"tblval\">Value</th>";
766 out() <<
"<th class=\"tbldscr\">Description</th></tr>\n";
768 out() <<
"<tr><th class=\"tblConst\">Constant</th><th "
769 "class=\"tblVal\">Value</th></tr>\n";
786 out() << QString(R"(<ol class="%1" type="%1" start="%2">)")
787 .arg(olType, atom
->next()->string());
789 out() << QString(R"(<ol class="%1" type="%1">)").arg(olType);
798 std::pair<QString,
int> pair = getAtomListValue(atom);
799 skipAhead = pair.second;
800 QString t = protectEnc(plainCode(marker->markedUpEnumValue(pair.first, relative)));
801 out() <<
"<tr><td class=\"topAlign\"><code translate=\"no\">" << t <<
"</code>";
804 out() <<
"</td><td class=\"topAlign tblval\">";
805 const auto *enume =
static_cast<
const EnumNode *>(relative);
806 QString itemValue = enume->itemValue(atom->next()->string());
807 if (itemValue.isEmpty())
810 out() <<
"<code translate=\"no\">" << protectEnc(itemValue) <<
"</code>";
824 out() <<
"</td><td class=\"topAlign\">";
831 if (matchAhead(atom, Atom::ParaLeft))
838 out() <<
"</td></tr>\n";
849 out() <<
"</table></div>\n";
870 out() <<
"<blockquote>";
873 out() <<
"</blockquote>\n";
876 out() << atom->string();
882 int unit = atom->string().toInt() +
hOffset(relative
);
883 out() <<
"<h" + QString::number(unit) + QLatin1Char(
' ') <<
"id=\""
884 << Tree::refForAtom(atom) <<
"\">";
888 case Atom::SectionHeadingRight:
889 out() <<
"</h" + QString::number(atom->string().toInt() + hOffset(relative)) +
">\n";
900 out() << protectEnc(atom->string());
904 std::pair<QString, QString> pair = getTableWidthAttr(atom);
905 QString attr = pair.second;
906 QString width = pair.first;
913 out() << R"(<div class="table"><table class=")" << attr <<
'"';
914 if (!width.isEmpty())
915 out() <<
" width=\"" << width <<
'"';
920 out() <<
"</table></div>\n";
923 out() <<
"<thead><tr class=\"qt-style\">";
930 out() <<
"\n<tr class=\"qt-style\">";
932 out() <<
"</thead>\n";
937 if (!atom->string().isEmpty())
938 out() <<
"<tr " << atom->string() <<
'>';
940 out() << R"(<tr valign="top" class="odd">)";
942 out() << R"(<tr valign="top" class="even">)";
953 for (
int i = 0; i < atom->count(); ++i) {
956 const QString &p = atom->string(i);
957 if (p.contains(
'=')) {
960 QStringList spans = p.split(QLatin1Char(
','));
961 if (spans.size() == 2) {
962 if (spans.at(0) !=
"1")
963 out() <<
" colspan=\"" << spans.at(0) <<
'"';
964 if (spans.at(1) !=
"1")
965 out() <<
" rowspan=\"" << spans.at(1) <<
'"';
970 if (matchAhead(atom, Atom::ParaLeft))
979 if (matchAhead(atom, Atom::ParaLeft))
982 case Atom::TableOfContentsLeft:
984 std::ignore = atom->find(Atom::TableOfContentsRight, &skipAhead);
989 out() <<
"<span id=\"" << Utilities::asAsciiPrintable(atom->string()) <<
"\"></span>";
992 out() <<
"<b class=\"redFont\"><Missing HTML></b>";
994 case Atom::UnknownCommand:
995 out() << R"(<b class="redFont"><code translate=\"no\">\)" << protectEnc(atom->string()) <<
"</code></b>";
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1043 auto link_for_group = [
this](
const CollectionNode *group) -> QString {
1044 QString target{linkForNode(group,
nullptr)};
1045 return (target.isEmpty()) ? protectEnc(group->name()) :
"<a href=\"" + target +
"\">" + protectEnc(group->fullTitle()) +
"</a>";
1050 const QStringList &groups_names{node->groupNames()};
1051 if (groups_names.isEmpty())
1054 std::vector<CollectionNode *> groups_nodes(groups_names.size(),
nullptr);
1055 std::transform(groups_names.cbegin(), groups_names.cend(), groups_nodes.begin(),
1059 return (group && group
->wasSeen()) ? group :
nullptr;
1061 groups_nodes.erase(
std::remove(groups_nodes.begin(), groups_nodes.end(),
nullptr), groups_nodes.end());
1063 if (!groups_nodes.empty()) {
1064 text += node->name() +
" is part of ";
1066 for (std::vector<CollectionNode *>::size_type index{0}; index < groups_nodes.size(); ++index) {
1067 text += link_for_group(groups_nodes[index]) + Utilities::separator(index, groups_nodes.size());
1074
1075
1076
1077
1087 QString typeWord = aggregate->typeWord(
true);
1090 fullTitle = aggregate->plainFullName();
1091 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1096 fullTitle = aggregate->plainFullName();
1097 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1101 title = fullTitle = aggregate->fullTitle();
1108 if (aggregate
->parent()->isInAPI() || templateDecl) {
1110 subtitleText <<
"%1 "_L1.arg((*templateDecl).to_qstring());
1111 subtitleText << aggregate->typeWord(
false) <<
" "_L1;
1112 auto ancestors = fullTitle.split(
"::"_L1);
1113 ancestors.pop_back();
1114 for (
const auto &a : ancestors)
1115 subtitleText << Atom(Atom::AutoLink, a) <<
"::"_L1;
1116 subtitleText << aggregate->plainName();
1119 generateHeader(title, aggregate, marker);
1120 generateTableOfContents(aggregate, marker, summarySections);
1121 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1125 brief <<
"The " << ns->name() <<
" namespace includes the following elements from module "
1128 addNodeLink(brief, fullNamespace,
" here.");
1130 generateText(brief, ns, marker);
1133 generateBrief(aggregate, marker);
1135 const auto parentIsClass = aggregate
->parent()->isClassNode();
1138 generateRequisites(aggregate, marker);
1143 QString membersLink = generateAllMembersFile(Sections::allMembersSection(), marker);
1144 if (!membersLink.isEmpty()) {
1145 openUnorderedList();
1146 out() <<
"<li><a href=\"" << membersLink <<
"\">"
1147 <<
"List of all members, including inherited members</a></li>\n";
1149 QString obsoleteLink = generateObsoleteMembersFile(sections, marker);
1150 if (!obsoleteLink.isEmpty()) {
1151 openUnorderedList();
1152 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1153 <<
"Deprecated members</a></li>\n";
1156 if (QString groups_text{groupReferenceText(aggregate)}; !groups_text.isEmpty()) {
1157 openUnorderedList();
1159 out() <<
"<li>" << groups_text <<
"</li>\n";
1162 closeUnorderedList();
1168 bool needOtherSection =
false;
1170 for (
const auto §ion : std::as_const(*summarySections)) {
1171 if (section.members().isEmpty() && section.reimplementedMembers().isEmpty()) {
1172 if (!section.inheritedMembers().isEmpty())
1173 needOtherSection =
true;
1175 if (!section.members().isEmpty()) {
1176 QString ref = registerRef(section.title().toLower());
1177 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1178 generateSection(section.members(), aggregate, marker);
1180 if (!section.reimplementedMembers().isEmpty()) {
1181 QString name = QString(
"Reimplemented ") + section.title();
1182 QString ref = registerRef(name.toLower());
1183 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(name) <<
"</h2>\n";
1184 generateSection(section.reimplementedMembers(), aggregate, marker);
1187 if (!section.inheritedMembers().isEmpty()) {
1189 generateSectionInheritedList(section, aggregate);
1195 if (needOtherSection) {
1196 out() <<
"<h3>Additional Inherited Members</h3>\n"
1199 for (
const auto §ion : std::as_const(*summarySections)) {
1200 if (section.members().isEmpty() && !section.inheritedMembers().isEmpty())
1201 generateSectionInheritedList(section, aggregate);
1206 if (aggregate
->doc().isEmpty()) {
1207 QString command =
"documentation";
1209 command = R"('\class' comment)";
1212 QStringLiteral(
"No %1 for '%2'").arg(command, aggregate->plainSignature()));
1215 generateExtractionMark(aggregate, DetailedDescriptionMark);
1216 out() <<
"<div class=\"descr\">\n"
1217 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1218 <<
"Detailed Description"
1221 out() <<
"</div>\n";
1222 generateAlsoList(aggregate, marker);
1223 generateExtractionMark(aggregate, EndMark);
1226 for (
const auto §ion : std::as_const(*detailsSections)) {
1227 bool headerGenerated =
false;
1228 if (section.isEmpty())
1231 const QList<Node *> &members = section.members();
1232 for (
const auto &member : members) {
1233 if (!headerGenerated) {
1234 if (!section.divClass().isEmpty())
1235 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1236 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1237 headerGenerated =
true;
1239 if (!member->isClassNode())
1240 generateDetailedMember(member, aggregate, marker);
1242 out() <<
"<h3> class ";
1243 generateFullName(member, aggregate);
1245 generateBrief(member, marker, aggregate);
1248 if (headerGenerated && !section.divClass().isEmpty())
1249 out() <<
"</div>\n";
1251 generateFooter(aggregate);
1266 rawTitle = aggregate->plainName();
1267 fullTitle = aggregate->plainFullName();
1268 title = rawTitle +
" Proxy Page";
1271 generateHeader(title, aggregate, marker);
1272 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1273 generateBrief(aggregate, marker);
1274 for (
auto it = summarySections->constBegin(); it != summarySections->constEnd(); ++it) {
1275 if (!it->members().isEmpty()) {
1276 QString ref = registerRef(it->title().toLower());
1277 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(it->title()) <<
"</h2>\n";
1278 generateSection(it->members(), aggregate, marker);
1282 if (!aggregate
->doc().isEmpty()) {
1283 generateExtractionMark(aggregate, DetailedDescriptionMark);
1284 out() <<
"<div class=\"descr\">\n"
1285 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1286 <<
"Detailed Description"
1289 out() <<
"</div>\n";
1290 generateAlsoList(aggregate, marker);
1291 generateExtractionMark(aggregate, EndMark);
1294 for (
const auto §ion : std::as_const(*detailsSections)) {
1295 if (section.isEmpty())
1298 if (!section.divClass().isEmpty())
1299 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1300 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1302 const QList<Node *> &members = section.members();
1303 for (
const auto &member : members) {
1304 if (!member->isClassNode()) {
1305 generateDetailedMember(member, aggregate, marker);
1307 out() <<
"<h3> class ";
1308 generateFullName(member, aggregate);
1310 generateBrief(member, marker, aggregate);
1313 if (!section.divClass().isEmpty())
1314 out() <<
"</div>\n";
1316 generateFooter(aggregate);
1320
1321
1322
1326 SubTitleSize subTitleSize = LargeSubTitle;
1327 QString htmlTitle = qcn->fullTitle();
1329 htmlTitle.append(
" QML Value Type");
1331 htmlTitle.append(
" QML Type");
1333 if (qcn->isSingleton())
1334 htmlTitle.append(
" (Singleton)"_L1);
1336 generateHeader(htmlTitle, qcn, marker);
1338 generateTableOfContents(qcn, marker, §ions.stdQmlTypeSummarySections());
1339 marker = CodeMarker::markerForLanguage(QLatin1String(
"QML"));
1340 generateTitle(htmlTitle, Text() << qcn->subtitle(), subTitleSize, qcn, marker);
1341 generateBrief(qcn, marker);
1342 generateQmlRequisites(qcn, marker);
1346 out() <<
"<p><strong>Note:</strong> This type is a QML singleton. "_L1
1347 <<
"There is only one instance of this type in the QML engine.</p>\n"_L1;
1350 QString allQmlMembersLink;
1353 if (!qcn->isQmlBasicType())
1354 allQmlMembersLink = generateAllQmlMembersFile(sections, marker);
1355 QString obsoleteLink = generateObsoleteQmlMembersFile(sections, marker);
1356 if (!allQmlMembersLink.isEmpty() || !obsoleteLink.isEmpty()) {
1357 openUnorderedList();
1359 if (!allQmlMembersLink.isEmpty()) {
1360 out() <<
"<li><a href=\"" << allQmlMembersLink <<
"\">"
1361 <<
"List of all members, including inherited members</a></li>\n";
1363 if (!obsoleteLink.isEmpty()) {
1364 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1365 <<
"Deprecated members</a></li>\n";
1369 if (QString groups_text{groupReferenceText(qcn)}; !groups_text.isEmpty()) {
1370 openUnorderedList();
1372 out() <<
"<li>" << groups_text <<
"</li>\n";
1375 closeUnorderedList();
1378 for (
const auto §ion : stdQmlTypeSummarySections) {
1379 if (!section.isEmpty()) {
1380 QString ref = registerRef(section.title().toLower());
1381 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1382 generateQmlSummary(section.members(), qcn, marker);
1386 generateExtractionMark(qcn, DetailedDescriptionMark);
1387 out() <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1388 <<
"Detailed Description"
1391 generateAlsoList(qcn, marker);
1392 generateExtractionMark(qcn, EndMark);
1395 for (
const auto §ion : stdQmlTypeDetailsSections) {
1396 if (section.isEmpty())
1398 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1399 const QList<Node *> &members = section.members();
1400 for (
const auto member : members)
1401 generateDetailedQmlMember(member, qcn, marker);
1403 generateFooter(qcn);
1408
1409
1410
1413 SubTitleSize subTitleSize = LargeSubTitle;
1414 QString fullTitle = pn->fullTitle();
1416 generateHeader(fullTitle, pn, marker);
1418
1419
1420
1421 if ((pn->name() != QLatin1String(
"index.html")))
1422 generateTableOfContents(pn, marker,
nullptr);
1424 generateTitle(fullTitle, Text() << pn->subtitle(), subTitleSize, pn, marker);
1426 generateBrief(pn, marker,
nullptr,
false);
1429 generateExtractionMark(pn, DetailedDescriptionMark);
1430 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1434 out() <<
"</div>\n";
1435 generateAlsoList(pn, marker);
1436 generateExtractionMark(pn, EndMark);
1442
1443
1446 SubTitleSize subTitleSize = LargeSubTitle;
1447 QString fullTitle = cn->fullTitle();
1450 generateHeader(fullTitle, cn, marker);
1451 generateTableOfContents(cn, marker,
nullptr);
1452 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1455 if (cn
->genus() != Genus::DOC && cn
->genus() != Genus::DontCare) {
1457 generateBrief(cn, marker);
1465 if (!nmm.isEmpty()) {
1466 ref = registerRef(
"namespaces");
1467 out() <<
"<h2 id=\"" << ref <<
"\">Namespaces</h2>\n";
1468 generateAnnotatedList(cn, marker, nmm.values());
1471 if (!nmm.isEmpty()) {
1472 ref = registerRef(
"classes");
1473 out() <<
"<h2 id=\"" << ref <<
"\">Classes</h2>\n";
1474 generateAnnotatedList(cn, marker, nmm.values());
1480 generateExtractionMark(cn, DetailedDescriptionMark);
1481 ref = registerRef(
"details");
1482 out() <<
"<div class=\"descr\">\n";
1483 out() <<
"<h2 id=\"" << ref <<
"\">"
1484 <<
"Detailed Description"
1487 generateExtractionMark(cn, DetailedDescriptionMark);
1488 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1493 out() <<
"</div>\n";
1494 generateAlsoList(cn, marker);
1495 generateExtractionMark(cn, EndMark);
1498 if (cn->isGroup() || cn->isQmlModule())
1499 generateAnnotatedList(cn, marker, cn->members());
1505
1506
1507
1508
1511 SubTitleSize subTitleSize = LargeSubTitle;
1512 QString fullTitle = cn->name();
1514 generateHeader(fullTitle, cn, marker);
1515 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1518 brief <<
"Each function or type documented here is related to a class or "
1519 <<
"namespace that is documented in a different module. The reference "
1520 <<
"page for that class or namespace will link to the function or type "
1523 generateText(brief, cn, marker);
1527 for (
const auto &member : members)
1528 generateDetailedMember(member, cn, marker);
1534
1535
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563void HtmlGenerator::generateNavigationBar(
const QString &title,
const Node *node,
1564 CodeMarker *marker,
const QString &buildversion,
1567 if (m_noNavigationBar || node ==
nullptr)
1578 auto addNavItem = [&](
const QString &link,
const QString &title) {
1579 navigationbar << Atom(itemLeft) << Atom(
Atom::NavLink, link)
1586 auto addNavItemNode = [&](
const Node *node,
const QString &title) {
1587 navigationbar << Atom(itemLeft);
1588 addNodeLink(navigationbar, node, title);
1589 navigationbar << Atom(itemRight);
1594 QString moduleState;
1595 if (moduleNode && !moduleNode->state().isEmpty())
1596 moduleState = QStringLiteral(
" (%1)").arg(moduleNode->state());
1598 if (m_hometitle == title)
1600 if (!m_homepage.isEmpty())
1601 addNavItem(m_homepage, m_hometitle);
1602 if (!m_landingpage.isEmpty() && m_landingtitle != title)
1603 addNavItem(m_landingpage, m_landingtitle);
1606 if (!m_cppclassespage.isEmpty() && !m_cppclassestitle.isEmpty())
1607 addNavItem(m_cppclassespage, m_cppclassestitle);
1608 if (!node->physicalModuleName().isEmpty()) {
1612 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_cppclassespage))
1613 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1615 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1617 if (!m_qmltypespage.isEmpty() && !m_qmltypestitle.isEmpty())
1618 addNavItem(m_qmltypespage, m_qmltypestitle);
1622 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_qmltypespage)) {
1623 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1625 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1628 auto currentNode{
static_cast<
const PageNode*>(node)};
1629 std::deque<
const Node *> navNodes;
1631 qsizetype navItems = 0;
1633 if (
std::find(navNodes.cbegin(), navNodes.cend(),
1640 if (navNodes.empty()) {
1641 const QStringList groups =
static_cast<
const PageNode *>(node)->groupNames();
1642 for (
const auto &groupName : groups) {
1643 const auto *groupNode = m_qdb->findNodeByNameAndType(QStringList{groupName}, &Node::isGroup);
1644 if (groupNode && !groupNode->title().isEmpty()) {
1645 navNodes.push_front(groupNode);
1650 while (!navNodes.empty()) {
1651 if (navNodes.front()->isPageNode())
1652 addNavItemNode(navNodes.front(), navNodes.front()->title());
1653 navNodes.pop_front();
1657 navigationbar << Atom(itemLeft) << Atom(
Atom::String, title) << Atom(itemRight);
1661 generateText(navigationbar, node, marker);
1663 if (buildversion.isEmpty())
1669 out() <<
"</tr></table><table class=\"buildversion\"><tr>\n"
1670 << R"(<td id="buildversion" width="100%" align="right">)";
1672 out() <<
"<li id=\"buildversion\">";
1676 if (!m_landingpage.isEmpty() && m_landingtitle != title) {
1677 navigationbar << Atom(Atom::NavLink, m_landingpage)
1679 << Atom(Atom::String, buildversion)
1681 generateText(navigationbar, node, marker);
1683 out() << buildversion;
1693 out() <<
"<!DOCTYPE html>\n";
1694 out() << QString(
"<html lang=\"%1\">\n").arg(naturalLanguage);
1695 out() <<
"<head>\n";
1696 out() <<
" <meta charset=\"utf-8\">\n";
1701 out() <<
" <meta name=\"description\" content=\""
1702 << protectEnc(node->doc().briefText().toString())
1707 QString titleSuffix;
1708 if (!m_landingtitle.isEmpty()) {
1710 titleSuffix = m_landingtitle;
1711 }
else if (!m_hometitle.isEmpty()) {
1714 if (title != m_hometitle)
1715 titleSuffix = m_hometitle;
1718 titleSuffix = m_productName.isEmpty() ? m_project : m_productName;
1720 if (title == titleSuffix)
1721 titleSuffix.clear();
1723 out() <<
" <title>";
1724 if (!titleSuffix.isEmpty() && !title.isEmpty()) {
1725 out() <<
"%1 | %2"_L1.arg(protectEnc(title), titleSuffix);
1727 out() << protectEnc(title);
1732 QVersionNumber projectVersion = QVersionNumber::fromString(m_qdb->version());
1733 if (!projectVersion.isNull()) {
1734 QVersionNumber titleVersion;
1735 static const QRegularExpression re(QLatin1String(R"(\d+\.\d+)"));
1736 const QString &versionedTitle = titleSuffix.isEmpty() ? title : titleSuffix;
1737 auto match = re.match(versionedTitle);
1738 if (match.hasMatch())
1739 titleVersion = QVersionNumber::fromString(match.captured());
1740 if (titleVersion.isNull() || !titleVersion.isPrefixOf(projectVersion)) {
1742 if (!m_productName.isEmpty() && titleSuffix != m_productName)
1743 out() <<
" | %1"_L1.arg(m_productName);
1744 out() <<
" %1"_L1.arg(projectVersion.toString());
1747 out() <<
"</title>\n";
1750 out() << m_headerStyles;
1751 out() << m_headerScripts;
1752 out() << m_endHeader;
1754 out() << QString(m_postHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1755 bool usingTable = m_postHeader.trimmed().endsWith(QLatin1String(
"<tr>"));
1756 generateNavigationBar(title, node, marker, m_buildversion, usingTable);
1757 out() << QString(m_postPostHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1759 m_navigationLinks.clear();
1762 if (node && !node->links().empty()) {
1763 std::pair<QString, QString> linkPair;
1764 std::pair<QString, QString> anchorPair;
1765 const Node *linkNode;
1766 bool useSeparator =
false;
1768 if (node->links().contains(Node::PreviousLink)) {
1769 linkPair = node->links()[Node::PreviousLink];
1770 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1773 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1774 if (linkNode ==
nullptr || linkNode == node)
1775 anchorPair = linkPair;
1777 anchorPair = anchorForNode(linkNode);
1779 out() << R"( <link rel="prev" href=")" << anchorPair.first <<
"\" />\n";
1781 m_navigationLinks += R"(<a class="prevPage" href=")" + anchorPair.first +
"\">";
1782 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1783 m_navigationLinks += protect(anchorPair.second);
1785 m_navigationLinks += protect(linkPair.second);
1786 m_navigationLinks +=
"</a>\n";
1787 useSeparator = !m_navigationSeparator.isEmpty();
1789 if (node->links().contains(Node::NextLink)) {
1790 linkPair = node->links()[Node::NextLink];
1791 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1794 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1795 if (linkNode ==
nullptr || linkNode == node)
1796 anchorPair = linkPair;
1798 anchorPair = anchorForNode(linkNode);
1800 out() << R"( <link rel="next" href=")" << anchorPair.first <<
"\" />\n";
1803 m_navigationLinks += m_navigationSeparator;
1805 m_navigationLinks += R"(<a class="nextPage" href=")" + anchorPair.first +
"\">";
1806 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1807 m_navigationLinks += protect(anchorPair.second);
1809 m_navigationLinks += protect(linkPair.second);
1810 m_navigationLinks +=
"</a>\n";
1812 if (node->links().contains(Node::StartLink)) {
1813 linkPair = node->links()[Node::StartLink];
1814 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1817 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1818 if (linkNode ==
nullptr || linkNode == node)
1819 anchorPair =
std::move(linkPair);
1821 anchorPair = anchorForNode(linkNode);
1822 out() << R"( <link rel="start" href=")" << anchorPair.first <<
"\" />\n";
1826 if (node && !node->links().empty())
1827 out() <<
"<p class=\"naviNextPrevious headerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1831 SubTitleSize subTitleSize,
const Node *relative,
1834 out() << QString(m_prologue).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1837 attribute = R"( translate="no")";
1839 if (!title.isEmpty())
1840 out() <<
"<h1 class=\"title\"" << attribute <<
">" << protectEnc(title) <<
"</h1>\n";
1843 if (subTitleSize == SmallSubTitle)
1844 out() <<
" class=\"small-subtitle\"" << attribute <<
">";
1846 out() <<
" class=\"subtitle\"" << attribute <<
">";
1847 generateText(subtitle, relative, marker);
1848 out() <<
"</span>\n";
1854 if (node && !node->links().empty())
1855 out() <<
"<p class=\"naviNextPrevious footerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1857 out() << QString(m_footer).replace(
"\\" +
COMMAND_VERSION, m_qdb->version())
1858 << QString(m_address).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1860 out() <<
"</body>\n";
1861 out() <<
"</html>\n";
1865
1866
1867
1870 QMap<QString, Text> requisites;
1873 const QString headerText =
"Header";
1874 const QString sinceText =
"Since";
1875 const QString inheritedByText =
"Inherited By";
1876 const QString inheritsText =
"Inherits";
1877 const QString nativeTypeText =
"In QML";
1878 const QString qtVariableText =
"qmake";
1879 const QString cmakeText =
"CMake";
1880 const QString statusText =
"Status";
1883 const QStringList requisiteorder { headerText, cmakeText, qtVariableText, sinceText,
1884 nativeTypeText, inheritsText, inheritedByText, statusText };
1886 addIncludeFileToMap(aggregate, requisites, text, headerText);
1887 addSinceToMap(aggregate, requisites, &text, sinceText);
1890 addCMakeInfoToMap(aggregate, requisites, &text, cmakeText);
1891 addQtVariableToMap(aggregate, requisites, &text, qtVariableText);
1895 auto *classe =
dynamic_cast<
ClassNode *>(aggregate);
1897 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1899 if (InclusionFilter::isIncluded(policy, context))
1900 addQmlNativeTypesToMap(requisites, &text, nativeTypeText, classe);
1903 addInheritsToMap(requisites, &text, inheritsText, classe);
1904 addInheritedByToMap(requisites, &text, inheritedByText, classe);
1908 addStatusToMap(aggregate, requisites, text, statusText);
1910 if (!requisites.isEmpty()) {
1912 generateTheTable(requisiteorder, requisites, aggregate, marker);
1917
1918
1919void HtmlGenerator::generateTheTable(
const QStringList &requisiteOrder,
1920 const QMap<QString, Text> &requisites,
1923 out() <<
"<div class=\"table\"><table class=\"alignedsummary requisites\" translate=\"no\">\n";
1925 for (
auto it = requisiteOrder.constBegin(); it != requisiteOrder.constEnd(); ++it) {
1927 if (requisites.contains(*it)) {
1929 <<
"<td class=\"memItemLeft rightAlign topAlign\"> " << *it
1931 "</td><td class=\"memItemRight bottomAlign\"> ";
1933 generateText(requisites.value(*it), aggregate, marker);
1934 out() <<
"</td></tr>\n";
1937 out() <<
"</table></div>\n";
1941
1942
1943
1944void HtmlGenerator::addInheritedByToMap(QMap<QString, Text> &requisites,
Text *text,
1945 const QString &inheritedByText,
ClassNode *classe)
1947 if (!classe->derivedClasses().isEmpty()) {
1950 int count = appendSortedNames(*text, classe, classe->derivedClasses());
1953 requisites.insert(inheritedByText, *text);
1958
1959
1960
1961void HtmlGenerator::addInheritsToMap(QMap<QString, Text> &requisites,
Text *text,
1962 const QString &inheritsText,
ClassNode *classe)
1964 if (!classe->baseClasses().isEmpty()) {
1967 const auto baseClasses = classe->baseClasses();
1968 for (
const auto &cls : baseClasses) {
1970 appendFullName(*text, cls.m_node, classe);
1972 if (cls.m_access == Access::Protected) {
1973 *text <<
" (protected)";
1974 }
else if (cls.m_access == Access::Private) {
1975 *text <<
" (private)";
1977 *text << Utilities::comma(index++, classe->baseClasses().size());
1982 requisites.insert(inheritsText, *text);
1987
1988
1989
1990void HtmlGenerator::addQmlNativeTypesToMap(QMap<QString, Text> &requisites,
Text *text,
1991 const QString &nativeTypeText,
ClassNode *classe)
const
1998 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2000 qsizetype index { 0 };
2002 for (
const auto &item : std::as_const(nativeTypes)) {
2003 addNodeLink(*text, item);
2004 *text << Utilities::comma(index++, nativeTypes.size());
2006 requisites.insert(nativeTypeText, *text);
2010
2011
2012
2014 Text *text,
const QString &CMakeInfo)
const
2016 if (!aggregate->physicalModuleName().isEmpty() && text !=
nullptr) {
2020 const auto result = cmakeRequisite(cn);
2033 requisites.insert(CMakeInfo, *text);
2038
2039
2040
2042 Text *text,
const QString &qtVariableText)
const
2044 if (!aggregate->physicalModuleName().isEmpty()) {
2048 if (cn && !cn->qtVariable().isEmpty()) {
2051 requisites.insert(qtVariableText, *text);
2057
2058
2059
2060
2062 Text *text,
const QString &sinceText)
const
2064 if (!aggregate->since().isEmpty() && text !=
nullptr) {
2067 requisites.insert(sinceText, *text);
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2083 Text &text,
const QString &statusText)
const
2085 auto status{formatStatus(aggregate, m_qdb)};
2091 spanClass = u"deprecated"_s;
2093 spanClass = Utilities::asAsciiPrintable(status.value());
2096 text << Atom(Atom::String, status.value())
2098 "class=\"status %1\""_L1.arg(spanClass))
2100 requisites.insert(statusText, text);
2104
2105
2106
2107
2109 QMap<QString, Text> &requisites,
Text& text,
2110 const QString &headerText)
2112 if (aggregate->includeFile()) {
2114 text << openCodeTag <<
"#include <%1>"_L1.arg(*aggregate->includeFile()) << closeCodeTag;
2115 requisites.insert(headerText, text);
2120
2121
2122
2128 QMap<QString, Text> requisites;
2131 const QString importText =
"Import Statement";
2132 const QString sinceText =
"Since";
2133 const QString inheritedByText =
"Inherited By";
2134 const QString inheritsText =
"Inherits";
2135 const QString nativeTypeText =
"In C++";
2136 const QString statusText =
"Status";
2139 QString logicalModuleVersion;
2144 bool generate_import =
true;
2146 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2150 if (generate_import) {
2154 requisites.insert(importText, text);
2157 qcn
->doc().location().warning(QStringLiteral(
"Could not resolve QML import statement for type '%1'").arg(qcn->name()),
2162 if (!qcn->since().isEmpty()) {
2165 requisites.insert(sinceText, text);
2170 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2174 addNodeLink(text, cn);
2175 requisites.insert(nativeTypeText, text);
2183 QStringList knownTypeNames{qcn->name()};
2185 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2193 knownTypeNames << base->name();
2196 addNodeLink(text, base);
2199 for (
const auto sub : std::as_const(subs)) {
2200 if (knownTypeNames.contains(sub->name())) {
2201 text << Atom(Atom::String,
" (%1)"_L1.arg(base->logicalModuleName()));
2206 requisites.insert(inheritsText, text);
2210 if (!subs.isEmpty()) {
2213 int count = appendSortedQmlNames(text, qcn, knownTypeNames, subs);
2216 requisites.insert(inheritedByText, text);
2220 addStatusToMap(qcn, requisites, text, statusText);
2223 const QStringList requisiteorder {
std::move(importText),
std::move(sinceText),
2224 std::move(nativeTypeText),
std::move(inheritsText),
2225 std::move(inheritedByText),
std::move(statusText)};
2227 if (!requisites.isEmpty())
2228 generateTheTable(requisiteorder, requisites, qcn, marker);
2240 QStringLiteral(
"'\\brief' statement does not end with a full stop."));
2242 generateExtractionMark(node, BriefMark);
2244 generateText(brief, node, marker);
2247 if (!relative || node == relative)
2248 out() <<
" <a href=\"#";
2250 out() <<
" <a href=\"" << linkForNode(node, relative) <<
'#';
2251 out() << registerRef(
"details") <<
"\">More...</a>";
2255 generateExtractionMark(node, EndMark);
2260
2261
2262
2264 QList<Section> *sections)
2268 toc = node
->doc().tableOfContents();
2269 if (tocDepth == 0 || (toc.isEmpty() && !sections && !node
->isModule())) {
2274 int sectionNumber = 1;
2275 int detailsBase = 0;
2280 out() <<
"<div class=\"sidebar\">\n";
2281 out() <<
"<div class=\"toc\">\n";
2282 out() <<
"<h3 id=\"toc\">Contents</h3>\n";
2285 openUnorderedList();
2288 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2289 << registerRef(
"namespaces") <<
"\">Namespaces</a></li>\n";
2292 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2293 << registerRef(
"classes") <<
"\">Classes</a></li>\n";
2296 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#" << registerRef(
"details")
2297 <<
"\">Detailed Description</a></li>\n";
2298 for (
const auto &entry : std::as_const(toc)) {
2299 if (entry->string().toInt() == 1) {
2305 for (
const auto §ion : std::as_const(*sections)) {
2306 if (!section.members().isEmpty()) {
2307 openUnorderedList();
2308 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2309 << registerRef(section.plural()) <<
"\">" << section.title() <<
"</a></li>\n";
2311 if (!section.reimplementedMembers().isEmpty()) {
2312 openUnorderedList();
2313 QString ref = QString(
"Reimplemented ") + section.plural();
2314 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2315 << registerRef(ref.toLower()) <<
"\">"
2316 << QString(
"Reimplemented ") + section.title() <<
"</a></li>\n";
2320 openUnorderedList();
2321 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2322 << registerRef(
"details") <<
"\">Detailed Description</a></li>\n";
2324 for (
const auto &entry : toc) {
2325 if (entry->string().toInt() == 1) {
2332 for (
const auto &atom : toc) {
2333 sectionNumber = atom->string().toInt() + detailsBase;
2336 if (sectionNumber <= tocDepth || tocDepth < 0) {
2337 openUnorderedList();
2339 Text headingText = Text::sectionHeading(atom);
2340 out() <<
"<li class=\"level" << sectionNumber <<
"\">";
2341 out() <<
"<a href=\"" <<
'#' << Tree::refForAtom(atom) <<
"\">";
2342 generateAtomList(headingText.firstAtom(), node, marker,
true, numAtoms);
2343 out() <<
"</a></li>\n";
2346 closeUnorderedList();
2347 out() <<
"</div>\n";
2348 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2349 out() <<
"</div>\n";
2355
2356
2359 out() <<
"<div class=\"sidebar\">";
2360 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2361 out() <<
"</div>\n";
2370 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2371 beginSubPage(aggregate, fileName);
2372 QString title =
"List of All Members for " + aggregate->plainFullName();
2373 generateHeader(title, aggregate, marker);
2375 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2376 out() <<
"<p>This is the complete list of members for ";
2377 generateFullName(aggregate,
nullptr);
2378 out() <<
", including inherited members.</p>\n";
2380 generateSectionList(section, aggregate, marker);
2388
2389
2390
2391
2392
2400 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2401 beginSubPage(aggregate, fileName);
2402 QString title =
"List of All Members for " + aggregate->name();
2403 generateHeader(title, aggregate, marker);
2405 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2406 out() <<
"<p>This is the complete list of members for ";
2407 generateFullName(aggregate,
nullptr);
2408 out() <<
", including inherited members.</p>\n";
2411 for (
int i = 0; i < cknl.size(); i++) {
2415 if (nodes.isEmpty())
2418 out() <<
"<p>The following members are inherited from ";
2419 generateFullName(qcn,
nullptr);
2422 openUnorderedList();
2423 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2424 for (
int j = 0; j < nodes.size(); j++) {
2425 Node *node = nodes[j];
2432 std::function<
void(
Node *)> generate = [&](Node *n) {
2433 out() <<
"<li class=\"fn\" translate=\"no\">";
2434 generateQmlItem(n, aggregate, marker,
true);
2436 out() <<
" [default]";
2437 else if (n->isAttached())
2438 out() <<
" [attached]";
2440 if (n->isPropertyGroup()) {
2442 const QList<Node *> &collective =
2443 static_cast<SharedCommentNode *>(n)->collective();
2444 std::for_each(collective.begin(), collective.end(), generate);
2451 closeUnorderedList();
2468 QString title =
"Obsolete Members for " + aggregate->plainFullName();
2469 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2471 beginSubPage(aggregate, fileName);
2472 generateHeader(title, aggregate, marker);
2474 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2476 out() <<
"<p><b>The following members of class "
2477 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\" translate=\"no\">"
2478 << protectEnc(aggregate->name()) <<
"</a>"
2479 <<
" are deprecated.</b> "
2480 <<
"They are provided to keep old source code working. "
2481 <<
"We strongly advise against using them in new code.</p>\n";
2483 for (
const auto §ion : summary_spv) {
2484 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2485 generateSectionList(*section, aggregate, marker,
true);
2488 for (
const auto §ion : details_spv) {
2489 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2491 const NodeVector &members = section->obsoleteMembers();
2492 for (
const auto &member : members)
2493 generateDetailedMember(member, aggregate, marker);
2502
2503
2504
2505
2514 QString title =
"Obsolete Members for " + aggregate->name();
2515 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2517 beginSubPage(aggregate, fileName);
2518 generateHeader(title, aggregate, marker);
2520 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2522 out() <<
"<p><b>The following members of QML type "
2523 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\">"
2524 << protectEnc(aggregate->name()) <<
"</a>"
2525 <<
" are deprecated.</b> "
2526 <<
"They are provided to keep old source code working. "
2527 <<
"We strongly advise against using them in new code.</p>\n";
2529 for (
const auto §ion : summary_spv) {
2530 QString ref = registerRef(section->title().toLower());
2531 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section->title()) <<
"</h2>\n";
2532 generateQmlSummary(section->obsoleteMembers(), aggregate, marker);
2535 for (
const auto §ion : details_spv) {
2536 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2537 const NodeVector &members = section->obsoleteMembers();
2538 for (
const auto &member : members) {
2539 generateDetailedQmlMember(member, aggregate, marker);
2551 if (classMap.isEmpty())
2555 for (
const auto &it : classMap) {
2556 auto *classe =
static_cast<ClassNode *>(it);
2557 if (classe->baseClasses().isEmpty())
2558 topLevel.insert(classe->name(), classe);
2561 QStack<NodeMap> stack;
2562 stack.push(topLevel);
2565 while (!stack.isEmpty()) {
2566 if (stack.top().isEmpty()) {
2572 generateFullName(child, relative);
2574 stack.top().erase(stack.top().begin());
2577 const auto derivedClasses = child->derivedClasses();
2578 for (
const RelatedClass &d : derivedClasses) {
2579 if (d.m_node && d.m_node->isInAPI())
2580 newTop.insert(d.m_node->name(), d.m_node);
2582 if (!newTop.isEmpty()) {
2591
2592
2593
2595 const NodeList &unsortedNodes, Qt::SortOrder sortOrder)
2597 if (unsortedNodes.isEmpty() || relative ==
nullptr)
2601 bool allInternal =
true;
2602 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2603 for (
auto *node : unsortedNodes) {
2604 const NodeContext context = node->createContext();
2605 if (InclusionFilter::isIncluded(policy, context) && !node->isDeprecated()) {
2606 allInternal =
false;
2607 nmm.insert(node->fullName(relative), node);
2612 out() <<
"<div class=\"table\"><table class=\"annotated\">\n";
2616 if (sortOrder == Qt::DescendingOrder)
2621 for (
const auto *node : std::as_const(nodes)) {
2623 out() <<
"<tr class=\"odd topAlign\">";
2625 out() <<
"<tr class=\"even topAlign\">";
2626 out() <<
"<td class=\"tblName\" translate=\"no\"><p>";
2627 generateFullName(node, relative);
2628 out() <<
"</p></td>";
2630 if (!node->isTextPageNode()) {
2631 Text brief = node->doc().trimmedBriefText(node->name());
2632 if (!brief.isEmpty()) {
2633 out() <<
"<td class=\"tblDescr\"><p>";
2634 generateText(brief, node, marker);
2635 out() <<
"</p></td>";
2636 }
else if (!node->reconstitutedBrief().isEmpty()) {
2637 out() <<
"<td class=\"tblDescr\"><p>";
2638 out() << node->reconstitutedBrief();
2639 out() <<
"</p></td>";
2642 out() <<
"<td class=\"tblDescr\"><p>";
2643 if (!node->reconstitutedBrief().isEmpty()) {
2644 out() << node->reconstitutedBrief();
2646 out() << protectEnc(node->doc().briefText().toString());
2647 out() <<
"</p></td>";
2651 out() <<
"</table></div>\n";
2655
2656
2657
2661 const auto &uniqueKeys = nmm.uniqueKeys();
2662 for (
const QString &name : uniqueKeys) {
2663 if (!name.isEmpty()) {
2664 out() <<
"<h2 id=\"" << registerRef(name.toLower()) <<
"\">" << protectEnc(name)
2667 generateAnnotatedList(relative, marker, nmm.values(name));
2672
2673
2674
2675
2676
2677
2678
2679
2680
2683 const QString &commonPrefix)
2688 const int NumParagraphs = 37;
2689 qsizetype commonPrefixLen = commonPrefix.size();
2692
2693
2694
2695
2696
2698 QString paragraphName[NumParagraphs + 1];
2699 QSet<
char> usedParagraphNames;
2701 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
2702 QStringList pieces = c.key().split(
"::");
2703 int idx = commonPrefixLen;
2704 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
2706 QString last = pieces.last().toLower();
2707 QString key = last.mid(idx);
2709 int paragraphNr = NumParagraphs - 1;
2711 if (key[0].digitValue() != -1) {
2712 paragraphNr = key[0].digitValue();
2713 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
2714 paragraphNr = 10 + key[0].unicode() -
'a';
2717 paragraphName[paragraphNr] = key[0].toUpper();
2718 usedParagraphNames.insert(key[0].toLower().cell());
2719 paragraph[paragraphNr].insert(last, c.value());
2723
2724
2725
2726
2727
2728
2729
2730 qsizetype paragraphOffset[NumParagraphs + 1];
2731 paragraphOffset[0] = 0;
2732 for (
int i = 0; i < NumParagraphs; i++)
2733 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
2736
2737
2738 if (includeAlphabet) {
2739 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2740 for (
int i = 0; i < 26; i++) {
2742 if (usedParagraphNames.contains(
char(
'a' + i)))
2743 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2745 out() <<
"</b></p>\n";
2749
2750
2751 out() <<
"<div class=\"flowListDiv\" translate=\"no\">\n";
2755 QHash<QString,
int> nameOccurrences;
2756 for (
const auto &[key, node] : nmm.asKeyValueRange()) {
2757 QStringList pieces{node->fullName(relative).split(
"::"_L1)};
2758 const QString &name{pieces.last()};
2759 nameOccurrences[name]++;
2763 int curParOffset = 0;
2765 for (
int i = 0; i < nmm.size(); i++) {
2766 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
2772
2773
2774 if (curParOffset == 0) {
2778 out() <<
"<dl class=\"flowList odd\">";
2780 out() <<
"<dl class=\"flowList even\">";
2781 out() <<
"<dt class=\"alphaChar\"";
2782 if (includeAlphabet)
2783 out() << QString(
" id=\"%1\"").arg(paragraphName[curParNr][0].toLower());
2784 out() <<
"><b>" << paragraphName[curParNr] <<
"</b></dt>\n";
2788
2789
2791 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
2792 NodeMultiMap::Iterator it;
2793 NodeMultiMap::Iterator next;
2794 it = paragraph[curParNr].begin();
2795 for (
int j = 0; j < curParOffset; j++)
2800
2801
2802
2803 out() <<
"<a href=\"" << linkForNode(it.value(), relative) <<
"\">";
2805 QString fileName = fileBase(it.value()) +
"-obsolete." + fileExtension();
2807 if (useOutputSubdirs())
2808 link =
"../%1/"_L1.arg(it.value()->tree()->physicalModuleName());
2810 out() <<
"<a href=\"" << link <<
"\">";
2813 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
2814 const auto &name{pieces.last()};
2817 if (nameOccurrences[name] > 1) {
2818 const QString moduleName = it.value()->isQmlNode() ? it.value()->logicalModuleName()
2819 : it.value()->tree()->camelCaseModuleName();
2820 pieces.last().append(
": %1"_L1.arg(moduleName));
2823 out() << protectEnc(pieces.last());
2825 if (pieces.size() > 1) {
2827 generateFullName(it.value()->parent(), relative);
2837 out() <<
"</div>\n";
2842 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2843 for (
int i = 0; i < 26; i++) {
2845 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2847 out() <<
"</b></p>\n";
2849 char nextLetter =
'a';
2851 out() <<
"<ul translate=\"no\">\n";
2853 for (
auto fnMap = funcIndex.constBegin(); fnMap != funcIndex.constEnd(); ++fnMap) {
2854 const QString &key = fnMap.key();
2855 const QChar firstLetter = key.isEmpty() ? QChar(
'A') : key.front();
2856 Q_ASSERT_X(firstLetter.unicode() < 256,
"generateFunctionIndex",
2857 "Only valid C++ identifiers were expected");
2858 const char currentLetter = firstLetter.isLower() ? firstLetter.unicode() : nextLetter - 1;
2860 if (currentLetter < nextLetter) {
2864 while (nextLetter < currentLetter)
2865 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2866 Q_ASSERT(nextLetter == currentLetter);
2867 out() << QStringLiteral(
"<li id=\"%1\">").arg(nextLetter++);
2869 out() << protectEnc(key) <<
':';
2871 for (
auto it = (*fnMap).constBegin(); it != (*fnMap).constEnd(); ++it) {
2873 generateFullName((*it)->parent(), relative, *it);
2877 while (nextLetter <=
'z')
2878 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2885 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
2886 Text text = it.key();
2887 generateText(text, relative, marker);
2891 generateFullName(it.value(), relative);
2894 }
while (it != legaleseTexts.constEnd() && it.key() == text);
2902 QString marked = marker->markedUpQmlItem(node, summary);
2903 marked.replace(
"@param>",
"i>");
2905 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
2906 .arg(summary ?
"summary"_L1 :
"details"_L1));
2907 marked.replace(
"</@extra>",
"</code>");
2911 marked.remove(
"<@name>");
2912 marked.remove(
"</@name>");
2913 marked.remove(
"<@type>");
2914 marked.remove(
"</@type>");
2916 out() << highlightedCode(marked, relative,
false, Genus::QML);
2920
2921
2922
2923
2924
2925
2926
2934 if (sortOrder == Qt::DescendingOrder)
2939 for (
const auto *node : std::as_const(members)) {
2940 out() <<
"<li translate=\"no\">";
2941 generateFullName(node,
nullptr);
2949 const QString &selector, Qt::SortOrder sortOrder)
2953 if (selector == QLatin1String(
"overviews"))
2955 else if (selector == QLatin1String(
"cpp-modules"))
2957 else if (selector == QLatin1String(
"qml-modules"))
2962 const auto collectionList = cnm.values();
2963 nodeList.reserve(collectionList.size());
2964 for (
auto *collectionNode : collectionList)
2965 nodeList.append(collectionNode);
2966 generateAnnotatedList(relative, marker, nodeList, sortOrder);
2969
2970
2971
2972
2975 QStringLiteral(
"\\generatelist {%1} is only allowed in \\group, "
2976 "\\module and \\qmlmodule comments.")
2980 auto *node =
const_cast<
Node *>(relative);
2982 if (!collectionNode)
2985 generateAnnotatedList(collectionNode, marker, collectionNode->members(), sortOrder);
2991 bool alignNames =
true;
2992 if (!nv.isEmpty()) {
2993 bool twoColumn =
false;
2994 if (nv.first()->isProperty()) {
2995 twoColumn = (nv.size() >= 5);
2999 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3002 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3003 <<
"<tr><td class=\"topAlign\">";
3008 for (
const auto &member : nv) {
3011 out() <<
"<tr><td class=\"memItemLeft rightAlign topAlign\"> ";
3013 if (twoColumn && i == (nv.size() + 1) / 2)
3014 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3015 out() <<
"<li class=\"fn\" translate=\"no\">";
3018 generateSynopsis(member, relative, marker, Section::Summary, alignNames);
3020 out() <<
"</td></tr>\n";
3026 out() <<
"</table></div>\n";
3030 out() <<
"</td></tr>\n</table></div>\n";
3038 bool alignNames =
true;
3041 if (!members.isEmpty()) {
3042 bool hasPrivateSignals =
false;
3043 bool isInvokable =
false;
3044 bool twoColumn =
false;
3047 twoColumn = (members.size() >= 16);
3048 }
else if (members.first()->isProperty()) {
3049 twoColumn = (members.size() >= 5);
3053 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3056 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3057 <<
"<tr><td class=\"topAlign\">";
3062 for (
const auto &member : members) {
3065 out() <<
"<tr><td class=\"memItemLeft topAlign rightAlign\"> ";
3067 if (twoColumn && i == (members.size() + 1) / 2)
3068 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3069 out() <<
"<li class=\"fn\" translate=\"no\">";
3072 generateSynopsis(member, relative, marker, section.style(), alignNames);
3073 if (member->isFunction()) {
3074 const auto *fn =
static_cast<
const FunctionNode *>(member);
3075 if (fn->isPrivateSignal()) {
3076 hasPrivateSignals =
true;
3078 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3079 }
else if (fn->isInvokable()) {
3082 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3086 out() <<
"</td></tr>\n";
3092 out() <<
"</table></div>\n";
3096 out() <<
"</td></tr>\n</table></div>\n";
3099 if (hasPrivateSignals)
3107 && !section.inheritedMembers().isEmpty()) {
3109 generateSectionInheritedList(section, relative);
3116 const QList<std::pair<Aggregate *,
int>> &inheritedMembers = section.inheritedMembers();
3117 for (
const auto &member : inheritedMembers) {
3118 out() <<
"<li class=\"fn\" translate=\"no\">";
3119 out() << member.second <<
' ';
3120 if (member.second == 1) {
3121 out() << section.singular();
3123 out() << section.plural();
3125 out() <<
" inherited from <a href=\"" << fileName(member.first) <<
'#'
3126 << Generator::cleanRef(section.title().toLower()) <<
"\">"
3127 << protectEnc(member.first->plainFullName(relative)) <<
"</a></li>\n";
3134 QString marked = marker->markedUpSynopsis(node, relative, style);
3135 marked.replace(
"@param>",
"i>");
3138 marked.remove(
"<@name>");
3139 marked.remove(
"</@name>");
3143 static const QRegularExpression extraRegExp(
"<@extra>.*</@extra>",
3144 QRegularExpression::InvertedGreedinessOption);
3145 marked.remove(extraRegExp);
3147 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
3148 .arg(style == Section::Summary ?
"summary"_L1 :
"details"_L1));
3149 marked.replace(
"</@extra>",
"</code>");
3153 marked.remove(
"<@type>");
3154 marked.remove(
"</@type>");
3157 out() << highlightedCode(marked, relative, alignNames);
3160QString
HtmlGenerator::highlightedCode(
const QString &markedCode,
const Node *relative,
3161 bool alignNames, Genus genus)
3163 QString src = markedCode;
3165 html.reserve(src.size());
3169 const QChar charLangle =
'<';
3170 const QChar charAt =
'@';
3172 static const QString typeTag(
"type");
3173 static const QString headerTag(
"headerfile");
3174 static const QString funcTag(
"func");
3175 static const QString linkTag(
"link");
3181 for (
int i = 0, srcSize = src.size(); i < srcSize;) {
3182 if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
3183 if (alignNames && !done) {
3184 html += QLatin1String(
"</td><td class=\"memItemRight bottomAlign\">");
3188 if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) {
3189 html += QLatin1String(
"<b>");
3190 const Node *n =
static_cast<
const Node*>(Utilities::nodeForString(par1.toString()));
3191 QString link = linkForNode(n, relative);
3192 addLink(link, arg, &html);
3193 html += QLatin1String(
"</b>");
3194 }
else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
3195 const FunctionNode *fn =
m_qdb->findFunctionNode(par1.toString(), relative, genus);
3196 QString link = linkForNode(fn, relative);
3197 addLink(link, arg, &html);
3198 par1 = QStringView();
3199 }
else if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
3200 par1 = QStringView();
3201 const Node *n =
m_qdb->findTypeNode(arg.toString(), relative, genus);
3202 html += QLatin1String(
"<span class=\"type\">");
3205 addLink(linkForNode(n, relative), arg, &html);
3209 addLink(linkForNode(n, relative), arg, &html);
3210 html += QLatin1String(
"</span>");
3211 }
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
3212 par1 = QStringView();
3213 if (arg.startsWith(QLatin1Char(
'&')))
3216 const Node *n =
m_qdb->findNodeForInclude(QStringList(arg.toString()));
3217 if (n && n != relative)
3218 addLink(linkForNode(n, relative), arg, &html);
3227 html += src.at(i++);
3244 html.reserve(src.size());
3245 static const QLatin1String spanTags[] = {
3246 QLatin1String(
"comment>"), QLatin1String(
"<span class=\"comment\">"),
3247 QLatin1String(
"preprocessor>"), QLatin1String(
"<span class=\"preprocessor\">"),
3248 QLatin1String(
"string>"), QLatin1String(
"<span class=\"string\">"),
3249 QLatin1String(
"char>"), QLatin1String(
"<span class=\"char\">"),
3250 QLatin1String(
"number>"), QLatin1String(
"<span class=\"number\">"),
3251 QLatin1String(
"op>"), QLatin1String(
"<span class=\"operator\">"),
3252 QLatin1String(
"type>"), QLatin1String(
"<span class=\"type\">"),
3253 QLatin1String(
"name>"), QLatin1String(
"<span class=\"name\">"),
3254 QLatin1String(
"keyword>"), QLatin1String(
"<span class=\"keyword\">")
3259 for (
int i = 0, n = src.size(); i < n;) {
3260 if (src.at(i) == QLatin1Char(
'<')) {
3261 if (src.at(i + 1) == QLatin1Char(
'@')) {
3263 bool handled =
false;
3264 for (
int k = 0; k != nTags; ++k) {
3265 const QLatin1String &tag = spanTags[2 * k];
3266 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3267 html += spanTags[2 * k + 1];
3275 while (i < n && src.at(i) != QLatin1Char(
'>'))
3280 }
else if (src.at(i + 1) == QLatin1Char(
'/') && src.at(i + 2) == QLatin1Char(
'@')) {
3282 bool handled =
false;
3283 for (
int k = 0; k != nTags; ++k) {
3284 const QLatin1String &tag = spanTags[2 * k];
3285 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3286 html += QLatin1String(
"</span>");
3294 while (i < n && src.at(i) != QLatin1Char(
'>'))
3313 if (match.hasMatch()) {
3315 qsizetype leftParenLoc = match.capturedStart(1);
3316 out() << protectEnc(atom->string().left(leftParenLoc));
3318 out() << protectEnc(atom->string().mid(leftParenLoc));
3322 out() << protectEnc(atom->string());
3327 return protect(string);
3332 if (string.isEmpty())
3336 if (html.isEmpty()) {
3343 qsizetype n = string.size();
3345 for (
int i = 0; i < n; ++i) {
3346 QChar ch = string.at(i);
3348 if (ch == QLatin1Char(
'&')) {
3350 }
else if (ch == QLatin1Char(
'<')) {
3352 }
else if (ch == QLatin1Char(
'>')) {
3354 }
else if (ch == QChar(8211)) {
3356 }
else if (ch == QChar(8212)) {
3358 }
else if (ch == QLatin1Char(
'"')) {
3361 if (!html.isEmpty())
3366 if (!html.isEmpty())
3375 QString result = Generator::fileBase(node);
3377 result += QLatin1String(
"-obsolete");
3384 return node->name();
3385 return Generator::fileName(node);
3389 const Node *actualNode)
3391 if (actualNode ==
nullptr)
3392 actualNode = apparentNode;
3393 bool link = !linkForNode(actualNode, relative).isEmpty();
3395 out() <<
"<a href=\"" << linkForNode(actualNode, relative);
3397 out() <<
"\" class=\"obsolete";
3400 out() << protectEnc(apparentNode->fullName(relative));
3406
3407
3408
3415 const auto srcLink = Config::instance().getSourceLink();
3416 if (!srcLink.enabled)
3421 if (loc
.isEmpty() || srcLink.baseUrl.isEmpty() || srcLink.rootPath.isEmpty())
3424 QString srcUrl{srcLink.baseUrl};
3425 if (!srcUrl.contains(
'\1'_L1)) {
3426 if (!srcUrl.endsWith(
'/'_L1))
3431 QDir rootDir{srcLink.rootPath};
3432 srcUrl.replace(
'\1'_L1, rootDir.relativeFilePath(loc.filePath()));
3433 srcUrl.replace(
'\2'_L1, QString::number(loc.lineNo()));
3434 const auto &description{
"View declaration of this %1"_L1.arg(node->nodeTypeString())};
3435 out() <<
"<a class=\"srclink\" href=\"%1\" title=\"%2\">%3</a>"_L1
3436 .arg(srcUrl, description, srcLink.linkText);
3443 generateExtractionMark(node, MemberMark);
3444 QString nodeRef =
nullptr;
3447 const QList<Node *> &collective = scn->collective();
3448 if (collective.size() > 1)
3449 out() <<
"<div class=\"fngroup\">\n";
3450 for (
const auto *sharedNode : collective) {
3451 nodeRef = refForNode(sharedNode);
3452 out() << R"(<h3 class="fn fngroupitem" translate="no" id=")" << nodeRef <<
"\">";
3453 generateSynopsis(sharedNode, relative, marker, Section::Details);
3454 generateSourceLink(sharedNode);
3457 if (collective.size() > 1)
3461 nodeRef = refForNode(node);
3463 out() << R"(<h3 class="flags" id=")" << nodeRef <<
"\">";
3467 generateSourceLink(node);
3470 out() << R"(<h3 class="fn" translate="no" id=")" << nodeRef <<
"\">";
3472 generateSourceLink(node);
3473 out() <<
"</h3>" <<
'\n';
3480 const auto *func =
static_cast<
const FunctionNode *>(node);
3490 const auto property =
static_cast<
const PropertyNode *>(node);
3500 out() <<
"<p><b>Access functions:</b></p>\n";
3501 generateSectionList(section, node, marker);
3508 out() <<
"<p><b>Notifier signal:</b></p>\n";
3509 generateSectionList(notifiers, node, marker);
3513 const auto *enumTypeNode =
static_cast<
const EnumNode *>(node);
3515 out() <<
"<p>The " << protectEnc(enumTypeNode->flagsType()->name())
3516 <<
" type is a typedef for "
3517 <<
"<a href=\"" << m_qflagsHref <<
"\">QFlags</a><"
3518 << protectEnc(enumTypeNode->name()) <<
">. It stores an OR combination of "
3519 << protectEnc(enumTypeNode->name()) <<
" values.</p>\n";
3522 generateAlsoList(node, marker);
3523 generateExtractionMark(node, EndMark);
3527
3528
3529
3530
3537 if (!m_link.isEmpty())
3538 out() <<
"<a href=\"" << m_link <<
"\" translate=\"no\">";
3546 if (m_link.isEmpty())
3549 const QString &translate_attr =
3550 (node && isApiGenus(node->genus())) ?
" translate=\"no\""_L1 :
""_L1;
3552 if (node ==
nullptr || (relative !=
nullptr && node->status() == relative->status()))
3553 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3554 else if (node->isDeprecated())
3555 out() <<
"<a href=\"" << m_link <<
"\" class=\"obsolete\"%1>"_L1.arg(translate_attr);
3557 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3568 if (!m_link.isEmpty())
3573
3574
3575
3579 if (!members.isEmpty()) {
3581 for (
const auto &member : members) {
3582 out() <<
"<li class=\"fn\" translate=\"no\">";
3583 generateQmlItem(member, relative, marker,
true);
3584 if (member->isPropertyGroup()) {
3585 const auto *scn =
static_cast<
const SharedCommentNode *>(member);
3586 if (scn->count() > 0) {
3588 const QList<Node *> &sharedNodes = scn->collective();
3589 for (
const auto &node : sharedNodes) {
3590 if (node->isQmlProperty()) {
3591 out() <<
"<li class=\"fn\" translate=\"no\">";
3592 generateQmlItem(node, relative, marker,
true);
3606
3607
3610 const QString id = refForNode(scn);
3611 out() << R"(<h3 class="fn qml-member qml-property-group" translate="no" id=")"
3613 <<
"<b>" << scn->name() <<
" group</b>"
3618
3619
3620
3624 generateExtractionMark(node, MemberMark);
3626 auto generateQmlProperty = [&](
Node *n,
bool isGroupItem =
false) {
3627 const QString nodeRef = refForNode(n);
3628 const auto cssClasses = isGroupItem ?
"fn qml-member qml-property fngroupitem"_L1 :
"fn qml-member qml-property"_L1;
3629 out() << R"(<h3 class=")"_L1 << cssClasses << R"(" translate="no" id=")"_L1 << nodeRef <<
"\">"_L1;
3630 generateQmlItem(n, relative, marker,
false);
3631 generateSourceLink(n);
3632 out() <<
"</h3>\n"_L1;
3635 auto generateQmlMethod = [&](
Node *n,
bool isGroupItem =
false) {
3636 const QString nodeRef = refForNode(n);
3637 const auto cssClasses = isGroupItem ?
"fn qml-member qml-method fngroupitem"_L1 :
"fn qml-member qml-method"_L1;
3638 out() << R"(<h3 class=")"_L1 << cssClasses << R"(" translate="no" id=")"_L1 << nodeRef <<
"\">"_L1;
3640 generateSourceLink(n);
3641 out() <<
"</h3>\n"_L1;
3646 const auto shared = scn->collective();
3649 emitGroupHeader(scn);
3651 const bool isGroup = shared.size() > 1;
3654 out() <<
"<div class=\"fngroup\">\n"_L1;
3656 for (
auto *child : std::as_const(shared)) {
3657 if (child->isQmlProperty())
3658 generateQmlProperty(child, isGroup);
3660 generateQmlMethod(child, isGroup);
3664 out() <<
"</div>"_L1;
3667 generateQmlProperty(node);
3669 generateQmlMethod(node);
3676 generateAlsoList(node, marker);
3677 generateExtractionMark(node, EndMark);
3680void HtmlGenerator::generateExtractionMark(
const Node *node, ExtractionMarkType markType)
3682 if (markType != EndMark) {
3683 out() <<
"<!-- $$$" + node->name();
3684 if (markType == MemberMark) {
3686 const auto *func =
static_cast<
const FunctionNode *>(node);
3689 out() <<
"[overload1]";
3694 const auto *prop =
static_cast<
const PropertyNode *>(node);
3696 for (
const auto *propFuncNode : list) {
3697 if (propFuncNode->isFunction()) {
3698 const auto *func =
static_cast<
const FunctionNode *>(propFuncNode);
3699 out() <<
"$$$" + func->name()
3700 + func->parameters().rawSignature().remove(
' ');
3704 const auto *enumNode =
static_cast<
const EnumNode *>(node);
3705 const auto &items = enumNode->items();
3706 for (
const auto &item : items)
3707 out() <<
"$$$" + item.name();
3709 }
else if (markType == BriefMark) {
3711 }
else if (markType == DetailedDescriptionMark) {
3712 out() <<
"-description";
3716 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
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...
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.
static void subclasses(const Node *base, NodeList &subs)
Loads the list subs with the nodes of all the subclasses of base.
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.