27#include <QtCore/qlist.h>
28#include <QtCore/qmap.h>
29#include <QtCore/quuid.h>
30#include <QtCore/qversionnumber.h>
31#include <QtCore/qregularexpression.h>
39using namespace Qt::StringLiterals;
48static void addLink(
const QString &linkTarget, QStringView nestedStuff, QString *res)
50 if (!linkTarget.isEmpty()) {
51 *res += QLatin1String(
"<a href=\"");
53 *res += QLatin1String(
"\" translate=\"no\">");
55 *res += QLatin1String(
"</a>");
62
63
64
67 if (!s_inUnorderedList) {
69 s_inUnorderedList =
true;
74
75
76
79 if (s_inUnorderedList) {
81 s_inUnorderedList =
false;
86
87
88
91 if (m_helpProjectWriter) {
92 delete m_helpProjectWriter;
93 m_helpProjectWriter =
nullptr;
96 if (m_manifestWriter) {
97 delete m_manifestWriter;
98 m_manifestWriter =
nullptr;
103
104
105
124 {
nullptr,
nullptr,
nullptr } };
127 config = &Config::instance();
130
131
132
133 for (
int i = 0; defaults[i].key; ++i) {
134 formattingLeftMap().insert(QLatin1String(defaults[i].key), QLatin1String(defaults[i].left));
135 formattingRightMap().insert(QLatin1String(defaults[i].key),
136 QLatin1String(defaults[i].right));
139 QString formatDot{HtmlGenerator::format() + Config::dot};
153 .asString(m_project + QLatin1String(
" Reference Documentation"));
155 m_projectUrl = config->get(
CONFIG_URL).asString();
164
165
166
167 if (m_helpProjectWriter)
168 m_helpProjectWriter->reset(m_project.toLower() +
".qhp",
this);
170 m_helpProjectWriter =
new HelpProjectWriter(m_project.toLower() +
".qhp",
this);
172 if (!m_manifestWriter)
185 .asString(m_homepage);
192 .asString(m_landingpage);
199 .asString(QLatin1String(
"C++ Classes"));
206 .asString(QLatin1String(
"QML Types"));
215
216
228
229
230
231
232
233
234
237 Node *qflags =
m_qdb->findClassNode(QStringList(
"QFlags"));
239 m_qflagsHref = linkForNode(qflags,
nullptr);
245 m_project.toLower().simplified().replace(QLatin1Char(
' '), QLatin1Char(
'-'));
246 m_qdb->generateIndex(outputDir() + QLatin1Char(
'/') + fileBase +
".index", m_projectUrl,
247 m_projectDescription,
this);
254
255
256 if (!tagFile_.isEmpty()) {
258 tagFileWriter.generateTagFile(tagFile_,
this);
264
265
268 SubTitleSize subTitleSize = LargeSubTitle;
269 QString fullTitle = en->fullTitle();
271 beginSubPage(en, linkForExampleFile(resolved_file.get_query()));
272 generateHeader(fullTitle, en, marker);
273 generateTitle(fullTitle, Text() << en->subtitle(), subTitleSize, en, marker);
278 QString code = quoter.quoteTo(en->location(), QString(), QString());
279 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
283 generateText(text, en, codeMarker);
288
289
292 qsizetype idx, skipAhead = 0;
293 static bool in_para =
false;
298 QString name = atom->string();
299 if (relative && relative->name() == name.replace(QLatin1String(
"()"), QLatin1String())) {
300 out() << protectEnc(atom->string());
309 const Node *node =
nullptr;
310 QString link = getAutoLink(atom, relative, &node, genus);
311 if (link.isEmpty()) {
314 QStringLiteral(
"Can't autolink to '%1'").arg(atom->string()));
319 if (link.isEmpty()) {
320 out() << protectEnc(atom->string());
322 beginLink(link, node, relative);
327 out() << protectEnc(atom->string());
334 skipAhead = skipAtoms(atom, Atom::BriefRight);
340 case Atom::BriefRight:
341 if (hasBrief(relative))
349 out() << protectEnc(plainCode(atom->string()));
352 case Atom::CaptionLeft:
353 out() <<
"<p class=\"figCaption\">";
364 out() <<
"<pre class=\"qml\" translate=\"no\">"
365 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative,
367 m_codePrefix, m_codeSuffix)
371 out() <<
"<pre class=\"cpp\" translate=\"no\">"
372 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative),
373 m_codePrefix, m_codeSuffix)
377 out() <<
"<pre class=\"cpp plain\" translate=\"no\">"
378 << trimmedTrailing(protectEnc(plainCode(indent(m_codeIndent, atom->string()))),
379 m_codePrefix, m_codeSuffix)
382 case Atom::DetailsLeft:
383 out() <<
"<details>\n";
384 if (!atom->string().isEmpty())
385 out() <<
"<summary>" << protectEnc(atom->string()) <<
"</summary>\n";
387 out() <<
"<summary>...</summary>\n";
389 case Atom::DetailsRight:
390 out() <<
"</details>\n";
394 if (!atom->string().isEmpty())
395 out() <<
' ' << atom->string();
409 case Atom::FootnoteRight:
417 case Atom::FormattingLeft:
418 if (atom->string().startsWith(
"span "))
419 out() <<
'<' + atom->string() <<
'>';
421 out() << formattingLeftMap()[atom->string()];
429 const Node *node{
nullptr};
430 const Atom tm_link(Atom::NavLink, m_trademarkspage);
431 if (
const auto &link = getLink(&tm_link, relative, &node);
432 !link.isEmpty() && node != relative)
433 out() <<
"<a href=\"%1\">%2</a>"_L1.arg(link, formattingRightMap()[atom->string()]);
435 out() << formattingRightMap()[atom->string()];
438 }
else if (atom->string().startsWith(
"span ")) {
441 out() << formattingRightMap()[atom->string()];
445 if (
const auto *cn = m_qdb->getCollectionNode(atom->string(), Node::Group); cn)
446 generateList(cn, marker, atom->string(), Generator::sortOrder(atom->strings().last()));
449 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
450 if (atom->string() == QLatin1String(
"annotatedclasses")) {
451 generateAnnotatedList(relative, marker, m_qdb->getCppClasses().values(), sortOrder);
452 }
else if (atom->string() == QLatin1String(
"annotatedexamples")) {
454 }
else if (atom->string() == QLatin1String(
"annotatedattributions")) {
456 }
else if (atom->string() == QLatin1String(
"classes")) {
457 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true,
459 }
else if (atom->string().contains(
"classes ")) {
460 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
461 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true, rootName);
462 }
else if (atom->string() == QLatin1String(
"qmlvaluetypes")
463 || atom->string() == QLatin1String(
"qmlbasictypes")) {
464 generateCompactList(Generic, relative, m_qdb->getQmlValueTypes(),
true,
466 }
else if (atom->string() == QLatin1String(
"qmltypes")) {
467 generateCompactList(Generic, relative, m_qdb->getQmlTypes(),
true, QStringLiteral(
""));
468 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
470 QString moduleName = atom->string().mid(idx + 8).trimmed();
472 if (
const auto *cn = qdb->getCollectionNode(moduleName, moduleType)) {
474 switch (moduleType) {
478 generateAnnotatedList(relative, marker, map.values(), sortOrder);
481 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
485 generateAnnotatedList(relative, marker, map.values(), sortOrder);
488 generateAnnotatedList(relative, marker, cn->members(), sortOrder);
492 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
494 }
else if (atom->string() == QLatin1String(
"obsoleteclasses")) {
495 generateCompactList(Generic, relative, m_qdb->getObsoleteClasses(),
false,
496 QStringLiteral(
"Q"));
497 }
else if (atom->string() == QLatin1String(
"obsoleteqmltypes")) {
498 generateCompactList(Generic, relative, m_qdb->getObsoleteQmlTypes(),
false,
500 }
else if (atom->string() == QLatin1String(
"obsoletecppmembers")) {
501 generateCompactList(Obsolete, relative, m_qdb->getClassesWithObsoleteMembers(),
false,
502 QStringLiteral(
"Q"));
503 }
else if (atom->string() == QLatin1String(
"obsoleteqmlmembers")) {
504 generateCompactList(Obsolete, relative, m_qdb->getQmlTypesWithObsoleteMembers(),
false,
506 }
else if (atom->string() == QLatin1String(
"functionindex")) {
507 generateFunctionIndex(relative);
508 }
else if (atom->string() == QLatin1String(
"attributions")) {
509 generateAnnotatedList(relative, marker, m_qdb->getAttributions().values(), sortOrder);
510 }
else if (atom->string() == QLatin1String(
"legalese")) {
511 generateLegaleseList(relative, marker);
512 }
else if (atom->string() == QLatin1String(
"overviews")) {
513 generateList(relative, marker,
"overviews", sortOrder);
514 }
else if (atom->string() == QLatin1String(
"cpp-modules")) {
515 generateList(relative, marker,
"cpp-modules", sortOrder);
516 }
else if (atom->string() == QLatin1String(
"qml-modules")) {
517 generateList(relative, marker,
"qml-modules", sortOrder);
518 }
else if (atom->string() == QLatin1String(
"namespaces")) {
519 generateAnnotatedList(relative, marker, m_qdb->getNamespaces().values(), sortOrder);
520 }
else if (atom->string() == QLatin1String(
"related")) {
521 generateList(relative, marker,
"related", sortOrder);
525 if (!generateGroupList(
const_cast<CollectionNode *>(cn), sortOrder))
527 QString(
"'\\generatelist %1' group is empty").arg(atom->string()));
530 QString(
"'\\generatelist %1' no such group").arg(atom->string()));
544 const QList<Section> sinceSections = sections.sinceSections();
545 for (
const auto §ion : sinceSections) {
546 if (!section.members().isEmpty()) {
548 <<
"<a href=\"#" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
549 << section.title() <<
"</a></li>\n";
555 for (
const auto §ion : sinceSections) {
556 if (!section.members().isEmpty()) {
557 out() <<
"<h3 id=\"" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
558 << protectEnc(section.title()) <<
"</h3>\n";
559 if (index == Sections::SinceClasses)
560 generateCompactList(Generic, relative, ncmap,
false, QStringLiteral(
"Q"));
561 else if (index == Sections::SinceQmlTypes)
562 generateCompactList(Generic, relative, nqcmap,
false, QStringLiteral(
""));
563 else if (index == Sections::SinceMemberFunctions
564 || index == Sections::SinceQmlMethods
565 || index == Sections::SinceQmlProperties) {
567 QMap<QString, NodeMultiMap> parentmaps;
569 const QList<Node *> &members = section.members();
570 for (
const auto &member : members) {
571 QString parent_full_name = (*member).parent()->fullName();
573 auto parent_entry = parentmaps.find(parent_full_name);
574 if (parent_entry == parentmaps.end())
575 parent_entry = parentmaps.insert(parent_full_name, NodeMultiMap());
576 parent_entry->insert(member->name(), member);
579 for (
auto map = parentmaps.begin(); map != parentmaps.end(); ++map) {
580 NodeVector nv = map->values().toVector();
581 auto parent = nv.front()->parent();
583 out() << ((index == Sections::SinceMemberFunctions) ?
"<p>Class " :
"<p>QML Type ");
585 out() <<
"<a href=\"" << linkForNode(parent, relative) <<
"\" translate=\"no\">";
586 QStringList pieces = parent->fullName().split(
"::");
587 out() << protectEnc(pieces.last());
591 generateSection(nv, relative, marker);
594 }
else if (index == Sections::SinceEnumValues) {
595 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
596 const auto map_it = m_qdb->newEnumValueMaps().constFind(atom->string());
597 for (
auto it = map_it->cbegin(); it != map_it->cend(); ++it) {
598 out() <<
"<tr><td class=\"memItemLeft\"> enum value </td><td class=\"memItemRight\">"
599 <<
"<b><a href=\"" << linkForNode(it.value(),
nullptr) <<
"\">"
600 << it.key() <<
"</a></b></td></tr>\n";
602 out() <<
"</table></div>\n";
604 generateSection(section.members(), relative, marker);
621 if (atom->type() == Atom::Image)
622 out() <<
"<p class=\"centerAlign\">";
624 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
625 if (!maybe_resolved_file) {
627 relative->location().warning(
628 QStringLiteral(
"Missing image: %1").arg(protectEnc(atom->string())));
629 out() <<
"<font color=\"red\">[Missing image " << protectEnc(atom->string())
633 QString file_name{QFileInfo{file.get_path()}.fileName()};
652 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
655 out() <<
"<img src=\"" <<
"images/" + protectEnc(file_name) <<
'"';
663 out() <<
" alt=\"" << protectEnc(text) <<
'"';
665 out() <<
" alt=\"\"";
670 m_helpProjectWriter->addExtraFile(
"images/" + file_name);
671 setImageFileName(relative,
"images/" + file_name);
674 if (atom->type() == Atom::Image)
683 QString admonType = atom->typeString();
686 out() <<
"<div class=\"admonition " << admonType.toLower() <<
"\">\n"
689 out() << admonType <<
": ";
692 case Atom::ImportantRight:
693 case Atom::NoteRight:
694 case Atom::WarningRight:
698 case Atom::LegaleseLeft:
699 out() <<
"<div class=\"LegaleseLeft\">";
701 case Atom::LegaleseRight:
704 case Atom::LineBreak:
713 const Node *node =
nullptr;
714 QString link = getLink(atom, relative, &node);
719 QStringLiteral(
"Can't link to '%1'").arg(atom->string()));
721 beginLink(link, node, relative);
725 QString link = linkForExampleFile(atom->string());
730 QString link = atom->string();
731 link =
"images/used-in-examples/" + link;
736 const Node *node = CodeMarker::nodeForString(atom->string());
737 beginLink(linkForNode(node, relative), node, relative);
750 out() << R"(<div class="table"><table class="valuelist">)";
753 if (++m_numTableRows % 2 == 1)
754 out() << R"(<tr valign="top" class="odd">)";
756 out() << R"(<tr valign="top" class="even">)";
758 out() <<
"<th class=\"tblConst\">Constant</th>";
761 if (relative->isEnumType())
762 out() <<
"<th class=\"tblval\">Value</th>";
764 out() <<
"<th class=\"tbldscr\">Description</th></tr>\n";
766 out() <<
"<tr><th class=\"tblConst\">Constant</th><th "
767 "class=\"tblVal\">Value</th></tr>\n";
784 out() << QString(R"(<ol class="%1" type="%1" start="%2">)")
785 .arg(olType, atom->next()->string());
787 out() << QString(R"(<ol class="%1" type="%1">)").arg(olType);
796 std::pair<QString,
int> pair = getAtomListValue(atom);
797 skipAhead = pair.second;
798 QString t = protectEnc(plainCode(marker->markedUpEnumValue(pair.first, relative)));
799 out() <<
"<tr><td class=\"topAlign\"><code translate=\"no\">" << t <<
"</code>";
802 out() <<
"</td><td class=\"topAlign tblval\">";
803 const auto *enume =
static_cast<
const EnumNode *>(relative);
804 QString itemValue = enume->itemValue(atom->next()->string());
805 if (itemValue.isEmpty())
808 out() <<
"<code translate=\"no\">" << protectEnc(itemValue) <<
"</code>";
812 case Atom::SinceTagRight:
813 case Atom::ListTagRight:
822 out() <<
"</td><td class=\"topAlign\">";
823 if (matchAhead(atom, Atom::ListItemRight))
829 if (matchAhead(atom, Atom::ParaLeft))
836 out() <<
"</td></tr>\n";
847 out() <<
"</table></div>\n";
867 case Atom::QuotationLeft:
868 out() <<
"<blockquote>";
870 case Atom::QuotationRight:
871 out() <<
"</blockquote>\n";
873 case Atom::RawString:
874 out() << atom->string();
880 int unit = atom->string().toInt() +
hOffset(relative
);
881 out() <<
"<h" + QString::number(unit) + QLatin1Char(
' ') <<
"id=\""
882 << Tree::refForAtom(atom) <<
"\">";
886 case Atom::SectionHeadingRight:
887 out() <<
"</h" + QString::number(atom->string().toInt() + hOffset(relative)) +
">\n";
898 out() << protectEnc(atom->string());
902 std::pair<QString, QString> pair = getTableWidthAttr(atom);
903 QString attr = pair.second;
904 QString width = pair.first;
911 out() << R"(<div class="table"><table class=")" << attr <<
'"';
912 if (!width.isEmpty())
913 out() <<
" width=\"" << width <<
'"';
917 case Atom::TableRight:
918 out() <<
"</table></div>\n";
920 case Atom::TableHeaderLeft:
921 out() <<
"<thead><tr class=\"qt-style\">";
924 case Atom::TableHeaderRight:
928 out() <<
"\n<tr class=\"qt-style\">";
930 out() <<
"</thead>\n";
934 case Atom::TableRowLeft:
935 if (!atom->string().isEmpty())
936 out() <<
"<tr " << atom->string() <<
'>';
937 else if (++m_numTableRows % 2 == 1)
938 out() << R"(<tr valign="top" class="odd">)";
940 out() << R"(<tr valign="top" class="even">)";
942 case Atom::TableRowRight:
951 for (
int i = 0; i < atom->count(); ++i) {
954 const QString &p = atom->string(i);
955 if (p.contains(
'=')) {
958 QStringList spans = p.split(QLatin1Char(
','));
959 if (spans.size() == 2) {
960 if (spans.at(0) !=
"1")
961 out() <<
" colspan=\"" << spans.at(0) <<
'"';
962 if (spans.at(1) !=
"1")
963 out() <<
" rowspan=\"" << spans.at(1) <<
'"';
968 if (matchAhead(atom, Atom::ParaLeft))
977 if (matchAhead(atom, Atom::ParaLeft))
985 out() <<
"<span id=\"" << Utilities::asAsciiPrintable(atom->string()) <<
"\"></span>";
987 case Atom::UnhandledFormat:
988 out() <<
"<b class=\"redFont\"><Missing HTML></b>";
990 case Atom::UnknownCommand:
991 out() << R"(<b class="redFont"><code translate=\"no\">\)" << protectEnc(atom->string()) <<
"</code></b>";
1009
1010
1011
1012
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
1039 auto link_for_group = [
this](
const CollectionNode *group) -> QString {
1040 QString target{linkForNode(group,
nullptr)};
1041 return (target.isEmpty()) ? protectEnc(group->name()) :
"<a href=\"" + target +
"\">" + protectEnc(group->fullTitle()) +
"</a>";
1046 const QStringList &groups_names{node->groupNames()};
1047 if (groups_names.isEmpty())
1050 std::vector<CollectionNode *> groups_nodes(groups_names.size(),
nullptr);
1051 std::transform(groups_names.cbegin(), groups_names.cend(), groups_nodes.begin(),
1055 return (group && group
->wasSeen()) ? group :
nullptr;
1057 groups_nodes.erase(
std::remove(groups_nodes.begin(), groups_nodes.end(),
nullptr), groups_nodes.end());
1059 if (!groups_nodes.empty()) {
1060 text += node->name() +
" is part of ";
1062 for (std::vector<CollectionNode *>::size_type index{0}; index < groups_nodes.size(); ++index) {
1063 text += link_for_group(groups_nodes[index]) + Utilities::separator(index, groups_nodes.size());
1070
1071
1072
1073
1084 QString word = aggregate->typeWord(
true);
1087 rawTitle = aggregate->plainName();
1088 fullTitle = aggregate->plainFullName();
1089 title = rawTitle +
" Namespace";
1094 rawTitle = aggregate->plainName();
1095 fullTitle = aggregate->plainFullName();
1096 title = rawTitle + QLatin1Char(
' ') + word;
1100 title = fullTitle = rawTitle = aggregate->fullTitle();
1106 if (rawTitle != fullTitle || templateDecl) {
1109 subtitleText << (*templateDecl).to_qstring() + QLatin1Char(
' ');
1110 subtitleText << aggregate->typeWord(
false) + QLatin1Char(
' ');
1111 const QStringList ancestors = fullTitle.split(QLatin1String(
"::"));
1112 for (
const auto &a : ancestors) {
1113 if (a == rawTitle) {
1117 subtitleText << Atom(Atom::AutoLink, a) <<
"::";
1121 subtitleText << fullTitle;
1125 generateHeader(title, aggregate, marker);
1126 generateTableOfContents(aggregate, marker, summarySections);
1127 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1131 brief <<
"The " << ns->name() <<
" namespace includes the following elements from module "
1138 generateText(brief, ns, marker);
1141 generateBrief(aggregate, marker);
1143 const auto parentIsClass = aggregate
->parent()->isClassNode();
1146 generateRequisites(aggregate, marker);
1151 QString membersLink = generateAllMembersFile(Sections::allMembersSection(), marker);
1152 if (!membersLink.isEmpty()) {
1153 openUnorderedList();
1154 out() <<
"<li><a href=\"" << membersLink <<
"\">"
1155 <<
"List of all members, including inherited members</a></li>\n";
1157 QString obsoleteLink = generateObsoleteMembersFile(sections, marker);
1158 if (!obsoleteLink.isEmpty()) {
1159 openUnorderedList();
1160 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1161 <<
"Deprecated members</a></li>\n";
1164 if (QString groups_text{groupReferenceText(aggregate)}; !groups_text.isEmpty()) {
1165 openUnorderedList();
1167 out() <<
"<li>" << groups_text <<
"</li>\n";
1170 closeUnorderedList();
1176 bool needOtherSection =
false;
1178 for (
const auto §ion : std::as_const(*summarySections)) {
1179 if (section.members().isEmpty() && section.reimplementedMembers().isEmpty()) {
1180 if (!section.inheritedMembers().isEmpty())
1181 needOtherSection =
true;
1183 if (!section.members().isEmpty()) {
1184 QString ref = registerRef(section.title().toLower());
1185 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1186 generateSection(section.members(), aggregate, marker);
1188 if (!section.reimplementedMembers().isEmpty()) {
1189 QString name = QString(
"Reimplemented ") + section.title();
1190 QString ref = registerRef(name.toLower());
1191 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(name) <<
"</h2>\n";
1192 generateSection(section.reimplementedMembers(), aggregate, marker);
1195 if (!section.inheritedMembers().isEmpty()) {
1197 generateSectionInheritedList(section, aggregate);
1203 if (needOtherSection) {
1204 out() <<
"<h3>Additional Inherited Members</h3>\n"
1207 for (
const auto §ion : std::as_const(*summarySections)) {
1208 if (section.members().isEmpty() && !section.inheritedMembers().isEmpty())
1209 generateSectionInheritedList(section, aggregate);
1214 if (aggregate
->doc().isEmpty()) {
1215 QString command =
"documentation";
1217 command = R"('\class' comment)";
1220 QStringLiteral(
"No %1 for '%2'").arg(command, aggregate->plainSignature()));
1223 generateExtractionMark(aggregate, DetailedDescriptionMark);
1224 out() <<
"<div class=\"descr\">\n"
1225 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1226 <<
"Detailed Description"
1229 out() <<
"</div>\n";
1230 generateAlsoList(aggregate, marker);
1231 generateExtractionMark(aggregate, EndMark);
1234 for (
const auto §ion : std::as_const(*detailsSections)) {
1235 bool headerGenerated =
false;
1236 if (section.isEmpty())
1239 const QList<Node *> &members = section.members();
1240 for (
const auto &member : members) {
1241 if (member->access() == Access::Private)
1243 if (!headerGenerated) {
1244 if (!section.divClass().isEmpty())
1245 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1246 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1247 headerGenerated =
true;
1249 if (!member->isClassNode())
1250 generateDetailedMember(member, aggregate, marker);
1252 out() <<
"<h3> class ";
1253 generateFullName(member, aggregate);
1255 generateBrief(member, marker, aggregate);
1259 names << member->name();
1260 if (member->isFunction()) {
1261 const auto *func =
reinterpret_cast<
const FunctionNode *>(member);
1262 if (func->isSomeCtor() || func->isDtor() || func->overloadNumber() != 0)
1264 }
else if (member->isProperty()) {
1265 const auto *prop =
reinterpret_cast<
const PropertyNode *>(member);
1266 if (!prop->getters().isEmpty() && !names.contains(prop->getters().first()->name()))
1267 names << prop->getters().first()->name();
1268 if (!prop->setters().isEmpty())
1269 names << prop->setters().first()->name();
1270 if (!prop->resetters().isEmpty())
1271 names << prop->resetters().first()->name();
1272 if (!prop->notifiers().isEmpty())
1273 names << prop->notifiers().first()->name();
1274 }
else if (member->isEnumType()) {
1275 const auto *enume =
reinterpret_cast<
const EnumNode *>(member);
1276 if (enume->flagsType())
1277 names << enume->flagsType()->name();
1278 const auto &enumItemNameList = enume->doc().enumItemNames();
1279 const auto &omitEnumItemNameList = enume->doc().omitEnumItemNames();
1280 const auto items = QSet<QString>(enumItemNameList.cbegin(), enumItemNameList.cend())
1281 - QSet<QString>(omitEnumItemNameList.cbegin(), omitEnumItemNameList.cend());
1282 for (
const QString &enumName : items) {
1283 names << plainCode(marker->markedUpEnumValue(enumName, enume));
1287 if (headerGenerated && !section.divClass().isEmpty())
1288 out() <<
"</div>\n";
1290 generateFooter(aggregate);
1305 rawTitle = aggregate->plainName();
1306 fullTitle = aggregate->plainFullName();
1307 title = rawTitle +
" Proxy Page";
1310 generateHeader(title, aggregate, marker);
1311 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1312 generateBrief(aggregate, marker);
1313 for (
auto it = summarySections->constBegin(); it != summarySections->constEnd(); ++it) {
1314 if (!it->members().isEmpty()) {
1315 QString ref = registerRef(it->title().toLower());
1316 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(it->title()) <<
"</h2>\n";
1317 generateSection(it->members(), aggregate, marker);
1321 if (!aggregate
->doc().isEmpty()) {
1322 generateExtractionMark(aggregate, DetailedDescriptionMark);
1323 out() <<
"<div class=\"descr\">\n"
1324 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1325 <<
"Detailed Description"
1328 out() <<
"</div>\n";
1329 generateAlsoList(aggregate, marker);
1330 generateExtractionMark(aggregate, EndMark);
1333 for (
const auto §ion : std::as_const(*detailsSections)) {
1334 if (section.isEmpty())
1337 if (!section.divClass().isEmpty())
1338 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1339 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1341 const QList<Node *> &members = section.members();
1342 for (
const auto &member : members) {
1343 if (!member->isPrivate()) {
1344 if (!member->isClassNode())
1345 generateDetailedMember(member, aggregate, marker);
1347 out() <<
"<h3> class ";
1348 generateFullName(member, aggregate);
1350 generateBrief(member, marker, aggregate);
1354 names << member->name();
1355 if (member->isFunction()) {
1356 const auto *func =
reinterpret_cast<
const FunctionNode *>(member);
1357 if (func->isSomeCtor() || func->isDtor() || func->overloadNumber() != 0)
1359 }
else if (member->isEnumType()) {
1360 const auto *enume =
reinterpret_cast<
const EnumNode *>(member);
1361 if (enume->flagsType())
1362 names << enume->flagsType()->name();
1363 const auto &enumItemNameList = enume->doc().enumItemNames();
1364 const auto &omitEnumItemNameList = enume->doc().omitEnumItemNames();
1366 QSet<QString>(enumItemNameList.cbegin(), enumItemNameList.cend())
1367 - QSet<QString>(omitEnumItemNameList.cbegin(),
1368 omitEnumItemNameList.cend());
1369 for (
const QString &enumName : items)
1370 names << plainCode(marker->markedUpEnumValue(enumName, enume));
1374 if (!section.divClass().isEmpty())
1375 out() <<
"</div>\n";
1377 generateFooter(aggregate);
1381
1382
1383
1387 SubTitleSize subTitleSize = LargeSubTitle;
1388 QString htmlTitle = qcn->fullTitle();
1390 htmlTitle.append(
" QML Value Type");
1392 htmlTitle.append(
" QML Type");
1395 generateHeader(htmlTitle, qcn, marker);
1397 generateTableOfContents(qcn, marker, §ions.stdQmlTypeSummarySections());
1398 marker = CodeMarker::markerForLanguage(QLatin1String(
"QML"));
1399 generateTitle(htmlTitle, Text() << qcn->subtitle(), subTitleSize, qcn, marker);
1400 generateBrief(qcn, marker);
1401 generateQmlRequisites(qcn, marker);
1404 QString allQmlMembersLink;
1407 if (!qcn->isQmlBasicType())
1408 allQmlMembersLink = generateAllQmlMembersFile(sections, marker);
1409 QString obsoleteLink = generateObsoleteQmlMembersFile(sections, marker);
1410 if (!allQmlMembersLink.isEmpty() || !obsoleteLink.isEmpty()) {
1411 openUnorderedList();
1413 if (!allQmlMembersLink.isEmpty()) {
1414 out() <<
"<li><a href=\"" << allQmlMembersLink <<
"\">"
1415 <<
"List of all members, including inherited members</a></li>\n";
1417 if (!obsoleteLink.isEmpty()) {
1418 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1419 <<
"Deprecated members</a></li>\n";
1423 if (QString groups_text{groupReferenceText(qcn)}; !groups_text.isEmpty()) {
1424 openUnorderedList();
1426 out() <<
"<li>" << groups_text <<
"</li>\n";
1429 closeUnorderedList();
1431 const QList<Section> &stdQmlTypeSummarySections = sections.stdQmlTypeSummarySections();
1432 for (
const auto §ion : stdQmlTypeSummarySections) {
1433 if (!section.isEmpty()) {
1434 QString ref = registerRef(section.title().toLower());
1435 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1436 generateQmlSummary(section.members(), qcn, marker);
1440 generateExtractionMark(qcn, DetailedDescriptionMark);
1441 out() <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1442 <<
"Detailed Description"
1445 generateAlsoList(qcn, marker);
1446 generateExtractionMark(qcn, EndMark);
1448 const QList<Section> &stdQmlTypeDetailsSections = sections.stdQmlTypeDetailsSections();
1449 for (
const auto §ion : stdQmlTypeDetailsSections) {
1450 if (!section.isEmpty()) {
1451 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1452 const QList<Node *> &members = section.members();
1453 for (
const auto member : members) {
1454 generateDetailedQmlMember(member, qcn, marker);
1459 generateFooter(qcn);
1464
1465
1466
1469 SubTitleSize subTitleSize = LargeSubTitle;
1470 QString fullTitle = pn->fullTitle();
1472 generateHeader(fullTitle, pn, marker);
1474
1475
1476
1477 if ((pn->name() != QLatin1String(
"index.html")))
1478 generateTableOfContents(pn, marker,
nullptr);
1480 generateTitle(fullTitle, Text() << pn->subtitle(), subTitleSize, pn, marker);
1482 generateBrief(pn, marker,
nullptr,
false);
1485 generateExtractionMark(pn, DetailedDescriptionMark);
1486 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1490 out() <<
"</div>\n";
1491 generateAlsoList(pn, marker);
1492 generateExtractionMark(pn, EndMark);
1498
1499
1502 SubTitleSize subTitleSize = LargeSubTitle;
1503 QString fullTitle = cn->fullTitle();
1506 generateHeader(fullTitle, cn, marker);
1507 generateTableOfContents(cn, marker,
nullptr);
1508 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1513 generateBrief(cn, marker);
1521 if (!nmm.isEmpty()) {
1522 ref = registerRef(
"namespaces");
1523 out() <<
"<h2 id=\"" << ref <<
"\">Namespaces</h2>\n";
1524 generateAnnotatedList(cn, marker, nmm.values());
1527 if (!nmm.isEmpty()) {
1528 ref = registerRef(
"classes");
1529 out() <<
"<h2 id=\"" << ref <<
"\">Classes</h2>\n";
1530 generateAnnotatedList(cn, marker, nmm.values());
1536 generateExtractionMark(cn, DetailedDescriptionMark);
1537 ref = registerRef(
"details");
1538 out() <<
"<div class=\"descr\">\n";
1539 out() <<
"<h2 id=\"" << ref <<
"\">"
1540 <<
"Detailed Description"
1543 generateExtractionMark(cn, DetailedDescriptionMark);
1544 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1549 out() <<
"</div>\n";
1550 generateAlsoList(cn, marker);
1551 generateExtractionMark(cn, EndMark);
1554 if (cn->isGroup() || cn->isQmlModule())
1555 generateAnnotatedList(cn, marker, cn->members());
1561
1562
1563
1564
1567 SubTitleSize subTitleSize = LargeSubTitle;
1568 QString fullTitle = cn->name();
1570 generateHeader(fullTitle, cn, marker);
1571 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1574 brief <<
"Each function or type documented here is related to a class or "
1575 <<
"namespace that is documented in a different module. The reference "
1576 <<
"page for that class or namespace will link to the function or type "
1579 generateText(brief, cn, marker);
1582 const QList<Node *> members = cn->members();
1583 for (
const auto &member : members)
1584 generateDetailedMember(member, cn, marker);
1590
1591
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619void HtmlGenerator::generateNavigationBar(
const QString &title,
const Node *node,
1620 CodeMarker *marker,
const QString &buildversion,
1623 if (m_noNavigationBar || node ==
nullptr)
1634 auto addNavItem = [&](
const QString &link,
const QString &title) {
1635 navigationbar << Atom(itemLeft) << Atom(
Atom::NavLink, link)
1642 auto addNavItemNode = [&](
const Node *node,
const QString &title) {
1643 navigationbar << Atom(itemLeft) <<
Atom(
Atom::LinkNode, CodeMarker::stringForNode(node))
1651 QString moduleState;
1652 if (moduleNode && !moduleNode->state().isEmpty())
1653 moduleState = QStringLiteral(
" (%1)").arg(moduleNode->state());
1655 if (m_hometitle == title)
1657 if (!m_homepage.isEmpty())
1658 addNavItem(m_homepage, m_hometitle);
1659 if (!m_landingpage.isEmpty() && m_landingtitle != title)
1660 addNavItem(m_landingpage, m_landingtitle);
1663 if (!m_cppclassespage.isEmpty() && !m_cppclassestitle.isEmpty())
1664 addNavItem(m_cppclassespage, m_cppclassestitle);
1665 if (!node->physicalModuleName().isEmpty()) {
1669 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_cppclassespage))
1670 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1672 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1674 if (!m_qmltypespage.isEmpty() && !m_qmltypestitle.isEmpty())
1675 addNavItem(m_qmltypespage, m_qmltypestitle);
1679 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_qmltypespage)) {
1680 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1682 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1685 auto currentNode{
static_cast<
const PageNode*>(node)};
1686 std::deque<
const Node *> navNodes;
1688 qsizetype navItems = 0;
1690 if (
std::find(navNodes.cbegin(), navNodes.cend(),
1697 if (navNodes.empty()) {
1698 const QStringList groups =
static_cast<
const PageNode *>(node)->groupNames();
1699 for (
const auto &groupName : groups) {
1700 const auto *groupNode = m_qdb->findNodeByNameAndType(QStringList{groupName}, &Node::isGroup);
1701 if (groupNode && !groupNode->title().isEmpty()) {
1702 navNodes.push_front(groupNode);
1707 while (!navNodes.empty()) {
1708 if (navNodes.front()->isPageNode())
1709 addNavItemNode(navNodes.front(), navNodes.front()->title());
1710 navNodes.pop_front();
1714 navigationbar << Atom(itemLeft) << Atom(
Atom::String, title) << Atom(itemRight);
1718 generateText(navigationbar, node, marker);
1720 if (buildversion.isEmpty())
1726 out() <<
"</tr></table><table class=\"buildversion\"><tr>\n"
1727 << R"(<td id="buildversion" width="100%" align="right">)";
1729 out() <<
"<li id=\"buildversion\">";
1733 if (!m_landingpage.isEmpty() && m_landingtitle != title) {
1734 navigationbar << Atom(Atom::NavLink, m_landingpage)
1736 << Atom(Atom::String, buildversion)
1738 generateText(navigationbar, node, marker);
1740 out() << buildversion;
1750 out() <<
"<!DOCTYPE html>\n";
1751 out() << QString(
"<html lang=\"%1\">\n").arg(naturalLanguage);
1752 out() <<
"<head>\n";
1753 out() <<
" <meta charset=\"utf-8\">\n";
1754 if (node && !node->doc().location().isEmpty())
1755 out() <<
"<!-- " << node->doc().location().fileName() <<
" -->\n";
1758 out() <<
" <meta name=\"description\" content=\""
1759 << protectEnc(node->doc().briefText().toString())
1764 QString titleSuffix;
1765 if (!m_landingtitle.isEmpty()) {
1767 titleSuffix = m_landingtitle;
1768 }
else if (!m_hometitle.isEmpty()) {
1771 if (title != m_hometitle)
1772 titleSuffix = m_hometitle;
1773 }
else if (!m_project.isEmpty()) {
1775 if (title != m_project)
1776 titleSuffix = m_project;
1779 titleSuffix = QLatin1String(
"Qt ");
1781 if (title == titleSuffix)
1782 titleSuffix.clear();
1785 if (!titleSuffix.isEmpty() && !title.isEmpty())
1786 divider = QLatin1String(
" | ");
1789 out() <<
" <title>" << protectEnc(title) << divider << titleSuffix;
1793 QVersionNumber projectVersion = QVersionNumber::fromString(m_qdb->version());
1794 if (!projectVersion.isNull()) {
1795 QVersionNumber titleVersion;
1796 static const QRegularExpression re(QLatin1String(R"(\d+\.\d+)"));
1797 const QString &versionedTitle = titleSuffix.isEmpty() ? title : titleSuffix;
1798 auto match = re.match(versionedTitle);
1799 if (match.hasMatch())
1800 titleVersion = QVersionNumber::fromString(match.captured());
1801 if (titleVersion.isNull() || !titleVersion.isPrefixOf(projectVersion))
1802 out() << QLatin1Char(
' ') << projectVersion.toString();
1804 out() <<
"</title>\n";
1807 out() << m_headerStyles;
1808 out() << m_headerScripts;
1809 if (m_endHeader.isEmpty())
1810 out() <<
"</head>\n<body>\n";
1812 out() << m_endHeader;
1814 out() << QString(m_postHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1815 bool usingTable = m_postHeader.trimmed().endsWith(QLatin1String(
"<tr>"));
1816 generateNavigationBar(title, node, marker, m_buildversion, usingTable);
1817 out() << QString(m_postPostHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1819 m_navigationLinks.clear();
1822 if (node && !node->links().empty()) {
1823 std::pair<QString, QString> linkPair;
1824 std::pair<QString, QString> anchorPair;
1825 const Node *linkNode;
1826 bool useSeparator =
false;
1828 if (node->links().contains(Node::PreviousLink)) {
1829 linkPair = node->links()[Node::PreviousLink];
1830 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1833 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1834 if (linkNode ==
nullptr || linkNode == node)
1835 anchorPair = linkPair;
1837 anchorPair = anchorForNode(linkNode);
1839 out() << R"( <link rel="prev" href=")" << anchorPair.first <<
"\" />\n";
1841 m_navigationLinks += R"(<a class="prevPage" href=")" + anchorPair.first +
"\">";
1842 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1843 m_navigationLinks += protect(anchorPair.second);
1845 m_navigationLinks += protect(linkPair.second);
1846 m_navigationLinks +=
"</a>\n";
1847 useSeparator = !m_navigationSeparator.isEmpty();
1849 if (node->links().contains(Node::NextLink)) {
1850 linkPair = node->links()[Node::NextLink];
1851 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1854 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1855 if (linkNode ==
nullptr || linkNode == node)
1856 anchorPair = linkPair;
1858 anchorPair = anchorForNode(linkNode);
1860 out() << R"( <link rel="next" href=")" << anchorPair.first <<
"\" />\n";
1863 m_navigationLinks += m_navigationSeparator;
1865 m_navigationLinks += R"(<a class="nextPage" href=")" + anchorPair.first +
"\">";
1866 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1867 m_navigationLinks += protect(anchorPair.second);
1869 m_navigationLinks += protect(linkPair.second);
1870 m_navigationLinks +=
"</a>\n";
1872 if (node->links().contains(Node::StartLink)) {
1873 linkPair = node->links()[Node::StartLink];
1874 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1877 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1878 if (linkNode ==
nullptr || linkNode == node)
1879 anchorPair = linkPair;
1881 anchorPair = anchorForNode(linkNode);
1882 out() << R"( <link rel="start" href=")" << anchorPair.first <<
"\" />\n";
1886 if (node && !node->links().empty())
1887 out() <<
"<p class=\"naviNextPrevious headerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1891 SubTitleSize subTitleSize,
const Node *relative,
1894 out() << QString(m_prologue).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1897 attribute = R"( translate="no")";
1899 if (!title.isEmpty())
1900 out() <<
"<h1 class=\"title\"" << attribute <<
">" << protectEnc(title) <<
"</h1>\n";
1903 if (subTitleSize == SmallSubTitle)
1904 out() <<
" class=\"small-subtitle\"" << attribute <<
">";
1906 out() <<
" class=\"subtitle\"" << attribute <<
">";
1907 generateText(subtitle, relative, marker);
1908 out() <<
"</span>\n";
1914 if (node && !node->links().empty())
1915 out() <<
"<p class=\"naviNextPrevious footerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1917 out() << QString(m_footer).replace(
"\\" +
COMMAND_VERSION, m_qdb->version())
1918 << QString(m_address).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1920 out() <<
"</body>\n";
1921 out() <<
"</html>\n";
1925
1926
1927
1930 QMap<QString, Text> requisites;
1933 const QString headerText =
"Header";
1934 const QString sinceText =
"Since";
1935 const QString inheritedBytext =
"Inherited By";
1936 const QString inheritsText =
"Inherits";
1937 const QString nativeTypeText =
"In QML";
1938 const QString qtVariableText =
"qmake";
1939 const QString cmakeText =
"CMake";
1940 const QString statusText =
"Status";
1943 const QStringList requisiteorder { headerText, cmakeText, qtVariableText, sinceText,
1944 nativeTypeText, inheritsText, inheritedBytext, statusText };
1946 addIncludeFileToMap(aggregate, requisites, text, headerText);
1947 addSinceToMap(aggregate, requisites, &text, sinceText);
1950 addCMakeInfoToMap(aggregate, requisites, &text, cmakeText);
1951 addQtVariableToMap(aggregate, requisites, &text, qtVariableText);
1955 auto *classe =
dynamic_cast<
ClassNode *>(aggregate);
1956 if (classe->isQmlNativeType() && !classe->isInternal())
1957 addQmlNativeTypesToMap(requisites, &text, nativeTypeText, classe);
1959 addInheritsToMap(requisites, &text, inheritsText, classe);
1960 addInheritedByToMap(requisites, &text, inheritedBytext, classe);
1964 addStatusToMap(aggregate, requisites, text, statusText);
1966 if (!requisites.isEmpty()) {
1968 generateTheTable(requisiteorder, requisites, aggregate, marker);
1973
1974
1975void HtmlGenerator::generateTheTable(
const QStringList &requisiteOrder,
1976 const QMap<QString, Text> &requisites,
1979 out() <<
"<div class=\"table\"><table class=\"alignedsummary requisites\" translate=\"no\">\n";
1981 for (
auto it = requisiteOrder.constBegin(); it != requisiteOrder.constEnd(); ++it) {
1983 if (requisites.contains(*it)) {
1985 <<
"<td class=\"memItemLeft rightAlign topAlign\"> " << *it
1987 "</td><td class=\"memItemRight bottomAlign\"> ";
1989 generateText(requisites.value(*it), aggregate, marker);
1990 out() <<
"</td></tr>\n";
1993 out() <<
"</table></div>\n";
1997
1998
1999
2000void HtmlGenerator::addInheritedByToMap(QMap<QString, Text> &requisites,
Text *text,
2001 const QString &inheritedBytext,
ClassNode *classe)
2003 if (!classe->derivedClasses().isEmpty()) {
2006 int count = appendSortedNames(*text, classe, classe->derivedClasses());
2009 requisites.insert(inheritedBytext, *text);
2014
2015
2016
2017void HtmlGenerator::addInheritsToMap(QMap<QString, Text> &requisites,
Text *text,
2018 const QString &inheritsText,
ClassNode *classe)
2020 if (!classe->baseClasses().isEmpty()) {
2023 const auto baseClasses = classe->baseClasses();
2024 for (
const auto &cls : baseClasses) {
2026 appendFullName(*text, cls.m_node, classe);
2028 if (cls.m_access == Access::Protected) {
2029 *text <<
" (protected)";
2030 }
else if (cls.m_access == Access::Private) {
2031 *text <<
" (private)";
2033 *text << Utilities::comma(index++, classe->baseClasses().size());
2038 requisites.insert(inheritsText, *text);
2043
2044
2045
2046 void HtmlGenerator::addQmlNativeTypesToMap(QMap<QString, Text> &requisites,
Text *text,
2047 const QString &nativeTypeText,
ClassNode *classe)
const
2054 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2056 qsizetype index { 0 };
2058 for (
const auto &item : std::as_const(nativeTypes)) {
2059 *text << Atom(Atom::LinkNode, CodeMarker::stringForNode(item))
2061 << Atom(Atom::String, item->name())
2063 *text << Utilities::comma(index++, nativeTypes.size());
2065 requisites.insert(nativeTypeText, *text);
2069
2070
2071
2073 Text *text,
const QString &CMakeInfo)
const
2075 if (!aggregate->physicalModuleName().isEmpty() && text !=
nullptr) {
2079 const auto result = cmakeRequisite(cn);
2092 requisites.insert(CMakeInfo, *text);
2097
2098
2099
2101 Text *text,
const QString &qtVariableText)
const
2103 if (!aggregate->physicalModuleName().isEmpty()) {
2107 if (cn && !cn->qtVariable().isEmpty()) {
2110 requisites.insert(qtVariableText, *text);
2116
2117
2118
2119
2121 Text *text,
const QString &sinceText)
const
2123 if (!aggregate->since().isEmpty() && text !=
nullptr) {
2126 requisites.insert(sinceText, *text);
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2142 Text &text,
const QString &statusText)
const
2144 auto status{formatStatus(aggregate, m_qdb)};
2150 spanClass = u"deprecated"_s;
2152 spanClass = Utilities::asAsciiPrintable(status.value());
2155 text << Atom(Atom::String, status.value())
2157 "class=\"status %1\""_L1.arg(spanClass))
2159 requisites.insert(statusText, text);
2163
2164
2165
2166
2168 QMap<QString, Text> &requisites,
Text& text,
2169 const QString &headerText)
2171 if (aggregate->includeFile()) {
2173 text << openCodeTag <<
"#include <%1>"_L1.arg(*aggregate->includeFile()) << closeCodeTag;
2174 requisites.insert(headerText, text);
2179
2180
2181
2186 QMap<QString, Text> requisites;
2189 const QString importText =
"Import Statement";
2190 const QString sinceText =
"Since";
2191 const QString inheritedBytext =
"Inherited By";
2192 const QString inheritsText =
"Inherits";
2193 const QString nativeTypeText =
"In C++";
2194 const QString statusText =
"Status";
2197 QString logicalModuleVersion;
2202 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2205 requisites.insert(importText, text);
2207 qcn
->doc().location().warning(QStringLiteral(
"Could not resolve QML import statement for type '%1'").arg(qcn->name()),
2212 if (!qcn->since().isEmpty()) {
2215 requisites.insert(sinceText, text);
2226 requisites.insert(nativeTypeText, text);
2239 requisites.insert(inheritsText, text);
2245 if (!subs.isEmpty()) {
2251 requisites.insert(inheritedBytext, text);
2255 addStatusToMap(qcn, requisites, text, statusText);
2258 const QStringList requisiteorder { importText, sinceText, nativeTypeText, inheritsText,
2259 inheritedBytext, statusText };
2261 if (!requisites.isEmpty())
2262 generateTheTable(requisiteorder, requisites, qcn, marker);
2274 QStringLiteral(
"'\\brief' statement does not end with a full stop."));
2276 generateExtractionMark(node, BriefMark);
2278 generateText(brief, node, marker);
2281 if (!relative || node == relative)
2282 out() <<
" <a href=\"#";
2284 out() <<
" <a href=\"" << linkForNode(node, relative) <<
'#';
2285 out() << registerRef(
"details") <<
"\">More...</a>";
2289 generateExtractionMark(node, EndMark);
2294
2295
2296
2298 QList<Section> *sections)
2302 toc = node
->doc().tableOfContents();
2303 if (tocDepth == 0 || (toc.isEmpty() && !sections && !node
->isModule())) {
2308 int sectionNumber = 1;
2309 int detailsBase = 0;
2314 out() <<
"<div class=\"sidebar\">\n";
2315 out() <<
"<div class=\"toc\">\n";
2316 out() <<
"<h3 id=\"toc\">Contents</h3>\n";
2319 openUnorderedList();
2322 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2323 << registerRef(
"namespaces") <<
"\">Namespaces</a></li>\n";
2326 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2327 << registerRef(
"classes") <<
"\">Classes</a></li>\n";
2330 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#" << registerRef(
"details")
2331 <<
"\">Detailed Description</a></li>\n";
2332 for (
const auto &entry : std::as_const(toc)) {
2333 if (entry->string().toInt() == 1) {
2339 for (
const auto §ion : std::as_const(*sections)) {
2340 if (!section.members().isEmpty()) {
2341 openUnorderedList();
2342 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2343 << registerRef(section.plural()) <<
"\">" << section.title() <<
"</a></li>\n";
2345 if (!section.reimplementedMembers().isEmpty()) {
2346 openUnorderedList();
2347 QString ref = QString(
"Reimplemented ") + section.plural();
2348 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2349 << registerRef(ref.toLower()) <<
"\">"
2350 << QString(
"Reimplemented ") + section.title() <<
"</a></li>\n";
2354 openUnorderedList();
2355 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2356 << registerRef(
"details") <<
"\">Detailed Description</a></li>\n";
2358 for (
const auto &entry : toc) {
2359 if (entry->string().toInt() == 1) {
2366 for (
const auto &atom : toc) {
2367 sectionNumber = atom->string().toInt() + detailsBase;
2370 if (sectionNumber <= tocDepth || tocDepth < 0) {
2371 openUnorderedList();
2373 Text headingText = Text::sectionHeading(atom);
2374 out() <<
"<li class=\"level" << sectionNumber <<
"\">";
2375 out() <<
"<a href=\"" <<
'#' << Tree::refForAtom(atom) <<
"\">";
2376 generateAtomList(headingText.firstAtom(), node, marker,
true, numAtoms);
2377 out() <<
"</a></li>\n";
2380 closeUnorderedList();
2381 out() <<
"</div>\n";
2382 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2383 out() <<
"</div>\n";
2389
2390
2393 out() <<
"<div class=\"sidebar\">";
2394 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2395 out() <<
"</div>\n";
2404 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2405 beginSubPage(aggregate, fileName);
2406 QString title =
"List of All Members for " + aggregate->name();
2407 generateHeader(title, aggregate, marker);
2409 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2410 out() <<
"<p>This is the complete list of members for ";
2411 generateFullName(aggregate,
nullptr);
2412 out() <<
", including inherited members.</p>\n";
2414 generateSectionList(section, aggregate, marker);
2422
2423
2424
2425
2426
2434 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2435 beginSubPage(aggregate, fileName);
2436 QString title =
"List of All Members for " + aggregate->name();
2437 generateHeader(title, aggregate, marker);
2439 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2440 out() <<
"<p>This is the complete list of members for ";
2441 generateFullName(aggregate,
nullptr);
2442 out() <<
", including inherited members.</p>\n";
2445 for (
int i = 0; i < cknl.size(); i++) {
2449 if (nodes.isEmpty())
2452 out() <<
"<p>The following members are inherited from ";
2453 generateFullName(qcn,
nullptr);
2456 openUnorderedList();
2457 for (
int j = 0; j < nodes.size(); j++) {
2458 Node *node = nodes[j];
2464 std::function<
void(
Node *)> generate = [&](Node *n) {
2465 out() <<
"<li class=\"fn\" translate=\"no\">";
2466 generateQmlItem(n, aggregate, marker,
true);
2468 out() <<
" [default]";
2469 else if (n->isAttached())
2470 out() <<
" [attached]";
2472 if (n->isPropertyGroup()) {
2474 const QList<Node *> &collective =
2475 static_cast<SharedCommentNode *>(n)->collective();
2476 std::for_each(collective.begin(), collective.end(), generate);
2483 closeUnorderedList();
2500 QString title =
"Obsolete Members for " + aggregate->name();
2501 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2503 beginSubPage(aggregate, fileName);
2504 generateHeader(title, aggregate, marker);
2506 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2508 out() <<
"<p><b>The following members of class "
2509 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\" translate=\"no\">"
2510 << protectEnc(aggregate->name()) <<
"</a>"
2511 <<
" are deprecated.</b> "
2512 <<
"They are provided to keep old source code working. "
2513 <<
"We strongly advise against using them in new code.</p>\n";
2515 for (
const auto §ion : summary_spv) {
2516 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2517 generateSectionList(*section, aggregate, marker,
true);
2520 for (
const auto §ion : details_spv) {
2521 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2523 const NodeVector &members = section->obsoleteMembers();
2524 for (
const auto &member : members) {
2525 if (member->access() != Access::Private)
2526 generateDetailedMember(member, aggregate, marker);
2536
2537
2538
2539
2548 QString title =
"Obsolete Members for " + aggregate->name();
2549 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2551 beginSubPage(aggregate, fileName);
2552 generateHeader(title, aggregate, marker);
2554 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2556 out() <<
"<p><b>The following members of QML type "
2557 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\">"
2558 << protectEnc(aggregate->name()) <<
"</a>"
2559 <<
" are deprecated.</b> "
2560 <<
"They are provided to keep old source code working. "
2561 <<
"We strongly advise against using them in new code.</p>\n";
2563 for (
const auto §ion : summary_spv) {
2564 QString ref = registerRef(section->title().toLower());
2565 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section->title()) <<
"</h2>\n";
2566 generateQmlSummary(section->obsoleteMembers(), aggregate, marker);
2569 for (
const auto §ion : details_spv) {
2570 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2571 const NodeVector &members = section->obsoleteMembers();
2572 for (
const auto &member : members) {
2573 generateDetailedQmlMember(member, aggregate, marker);
2585 if (classMap.isEmpty())
2589 for (
const auto &it : classMap) {
2590 auto *classe =
static_cast<ClassNode *>(it);
2591 if (classe->baseClasses().isEmpty())
2592 topLevel.insert(classe->name(), classe);
2595 QStack<NodeMap> stack;
2596 stack.push(topLevel);
2599 while (!stack.isEmpty()) {
2600 if (stack.top().isEmpty()) {
2606 generateFullName(child, relative);
2608 stack.top().erase(stack.top().begin());
2611 const auto derivedClasses = child->derivedClasses();
2612 for (
const RelatedClass &d : derivedClasses) {
2613 if (d.m_node && d.m_node->isInAPI())
2614 newTop.insert(d.m_node->name(), d.m_node);
2616 if (!newTop.isEmpty()) {
2625
2626
2627
2629 const NodeList &unsortedNodes, Qt::SortOrder sortOrder)
2631 if (unsortedNodes.isEmpty() || relative ==
nullptr)
2635 bool allInternal =
true;
2636 for (
auto *node : unsortedNodes) {
2637 if (!node->isInternal() && !node->isDeprecated()) {
2638 allInternal =
false;
2639 nmm.insert(node->fullName(relative), node);
2644 out() <<
"<div class=\"table\"><table class=\"annotated\">\n";
2648 if (sortOrder == Qt::DescendingOrder)
2653 for (
const auto *node : std::as_const(nodes)) {
2655 out() <<
"<tr class=\"odd topAlign\">";
2657 out() <<
"<tr class=\"even topAlign\">";
2658 out() <<
"<td class=\"tblName\" translate=\"no\"><p>";
2659 generateFullName(node, relative);
2660 out() <<
"</p></td>";
2662 if (!node->isTextPageNode()) {
2663 Text brief = node->doc().trimmedBriefText(node->name());
2664 if (!brief.isEmpty()) {
2665 out() <<
"<td class=\"tblDescr\"><p>";
2666 generateText(brief, node, marker);
2667 out() <<
"</p></td>";
2668 }
else if (!node->reconstitutedBrief().isEmpty()) {
2669 out() <<
"<td class=\"tblDescr\"><p>";
2670 out() << node->reconstitutedBrief();
2671 out() <<
"</p></td>";
2674 out() <<
"<td class=\"tblDescr\"><p>";
2675 if (!node->reconstitutedBrief().isEmpty()) {
2676 out() << node->reconstitutedBrief();
2678 out() << protectEnc(node->doc().briefText().toString());
2679 out() <<
"</p></td>";
2683 out() <<
"</table></div>\n";
2687
2688
2689
2693 const auto &uniqueKeys = nmm.uniqueKeys();
2694 for (
const QString &name : uniqueKeys) {
2695 if (!name.isEmpty()) {
2696 out() <<
"<h2 id=\"" << registerRef(name.toLower()) <<
"\">" << protectEnc(name)
2699 generateAnnotatedList(relative, marker, nmm.values(name));
2704
2705
2706
2707
2708
2709
2710
2711
2712
2715 const QString &commonPrefix)
2720 const int NumParagraphs = 37;
2721 qsizetype commonPrefixLen = commonPrefix.size();
2724
2725
2726
2727
2728
2730 QString paragraphName[NumParagraphs + 1];
2731 QSet<
char> usedParagraphNames;
2733 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
2734 QStringList pieces = c.key().split(
"::");
2735 int idx = commonPrefixLen;
2736 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
2738 QString last = pieces.last().toLower();
2739 QString key = last.mid(idx);
2741 int paragraphNr = NumParagraphs - 1;
2743 if (key[0].digitValue() != -1) {
2744 paragraphNr = key[0].digitValue();
2745 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
2746 paragraphNr = 10 + key[0].unicode() -
'a';
2749 paragraphName[paragraphNr] = key[0].toUpper();
2750 usedParagraphNames.insert(key[0].toLower().cell());
2751 paragraph[paragraphNr].insert(last, c.value());
2755
2756
2757
2758
2759
2760
2761
2762 qsizetype paragraphOffset[NumParagraphs + 1];
2763 paragraphOffset[0] = 0;
2764 for (
int i = 0; i < NumParagraphs; i++)
2765 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
2768
2769
2770 if (includeAlphabet) {
2771 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2772 for (
int i = 0; i < 26; i++) {
2774 if (usedParagraphNames.contains(
char(
'a' + i)))
2775 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2777 out() <<
"</b></p>\n";
2781
2782
2783 out() <<
"<div class=\"flowListDiv\" translate=\"no\">\n";
2787 int curParOffset = 0;
2788 QString previousName;
2789 bool multipleOccurrences =
false;
2791 for (
int i = 0; i < nmm.size(); i++) {
2792 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
2798
2799
2800 if (curParOffset == 0) {
2803 if (++m_numTableRows % 2 == 1)
2804 out() <<
"<dl class=\"flowList odd\">";
2806 out() <<
"<dl class=\"flowList even\">";
2807 out() <<
"<dt class=\"alphaChar\"";
2808 if (includeAlphabet)
2809 out() << QString(
" id=\"%1\"").arg(paragraphName[curParNr][0].toLower());
2810 out() <<
"><b>" << paragraphName[curParNr] <<
"</b></dt>\n";
2814
2815
2817 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
2818 NodeMultiMap::Iterator it;
2819 NodeMultiMap::Iterator next;
2820 it = paragraph[curParNr].begin();
2821 for (
int j = 0; j < curParOffset; j++)
2826
2827
2828
2829 out() <<
"<a href=\"" << linkForNode(it.value(), relative) <<
"\">";
2831 QString fileName = fileBase(it.value()) +
"-obsolete." + fileExtension();
2833 if (useOutputSubdirs())
2834 link =
"../%1/"_L1.arg(it.value()->tree()->physicalModuleName());
2836 out() <<
"<a href=\"" << link <<
"\">";
2839 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
2840 const auto &name{pieces.last()};
2843 if (name != previousName)
2844 multipleOccurrences =
false;
2845 if ((next != paragraph[curParNr].end()) && (name == next.value()->name())) {
2846 multipleOccurrences =
true;
2847 previousName = name;
2849 if (multipleOccurrences && pieces.size() == 1)
2850 pieces.last().append(
": %1"_L1.arg(it.value()->tree()->camelCaseModuleName()));
2852 out() << protectEnc(pieces.last());
2854 if (pieces.size() > 1) {
2856 generateFullName(it.value()->parent(), relative);
2866 out() <<
"</div>\n";
2871 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2872 for (
int i = 0; i < 26; i++) {
2874 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2876 out() <<
"</b></p>\n";
2878 char nextLetter =
'a';
2880 out() <<
"<ul translate=\"no\">\n";
2882 for (
auto fnMap = funcIndex.constBegin(); fnMap != funcIndex.constEnd(); ++fnMap) {
2883 const QString &key = fnMap.key();
2884 const QChar firstLetter = key.isEmpty() ? QChar(
'A') : key.front();
2885 Q_ASSERT_X(firstLetter.unicode() < 256,
"generateFunctionIndex",
2886 "Only valid C++ identifiers were expected");
2887 const char currentLetter = firstLetter.isLower() ? firstLetter.unicode() : nextLetter - 1;
2889 if (currentLetter < nextLetter) {
2893 while (nextLetter < currentLetter)
2894 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2895 Q_ASSERT(nextLetter == currentLetter);
2896 out() << QStringLiteral(
"<li id=\"%1\">").arg(nextLetter++);
2898 out() << protectEnc(key) <<
':';
2900 for (
auto it = (*fnMap).constBegin(); it != (*fnMap).constEnd(); ++it) {
2902 generateFullName((*it)->parent(), relative, *it);
2906 while (nextLetter <=
'z')
2907 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2914 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
2915 Text text = it.key();
2916 generateText(text, relative, marker);
2920 generateFullName(it.value(), relative);
2923 }
while (it != legaleseTexts.constEnd() && it.key() == text);
2931 QString marked = marker->markedUpQmlItem(node, summary);
2932 marked.replace(
"@param>",
"i>");
2934 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
2935 .arg(summary ?
"summary"_L1 :
"details"_L1));
2936 marked.replace(
"</@extra>",
"</code>");
2940 marked.remove(
"<@name>");
2941 marked.remove(
"</@name>");
2942 marked.remove(
"<@type>");
2943 marked.remove(
"</@type>");
2945 out() << highlightedCode(marked, relative,
false, Node::QML);
2949
2950
2951
2952
2953
2954
2955
2963 if (sortOrder == Qt::DescendingOrder)
2968 for (
const auto *node : std::as_const(members)) {
2969 out() <<
"<li translate=\"no\">";
2970 generateFullName(node,
nullptr);
2978 const QString &selector, Qt::SortOrder sortOrder)
2982 if (selector == QLatin1String(
"overviews"))
2984 else if (selector == QLatin1String(
"cpp-modules"))
2986 else if (selector == QLatin1String(
"qml-modules"))
2991 const auto collectionList = cnm.values();
2992 nodeList.reserve(collectionList.size());
2993 for (
auto *collectionNode : collectionList)
2994 nodeList.append(collectionNode);
2995 generateAnnotatedList(relative, marker, nodeList, sortOrder);
2998
2999
3000
3001
3004 QStringLiteral(
"\\generatelist {%1} is only allowed in \\group, "
3005 "\\module and \\qmlmodule comments.")
3009 auto *node =
const_cast<
Node *>(relative);
3012 generateAnnotatedList(collectionNode, marker, collectionNode->members(), sortOrder);
3018 bool alignNames =
true;
3019 if (!nv.isEmpty()) {
3020 bool twoColumn =
false;
3021 if (nv.first()->isProperty()) {
3022 twoColumn = (nv.size() >= 5);
3026 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3029 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3030 <<
"<tr><td class=\"topAlign\">";
3035 for (
const auto &member : nv) {
3036 if (member->access() == Access::Private)
3040 out() <<
"<tr><td class=\"memItemLeft rightAlign topAlign\"> ";
3042 if (twoColumn && i == (nv.size() + 1) / 2)
3043 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3044 out() <<
"<li class=\"fn\" translate=\"no\">";
3047 generateSynopsis(member, relative, marker, Section::Summary, alignNames);
3049 out() <<
"</td></tr>\n";
3055 out() <<
"</table></div>\n";
3059 out() <<
"</td></tr>\n</table></div>\n";
3067 bool alignNames =
true;
3070 if (!members.isEmpty()) {
3071 bool hasPrivateSignals =
false;
3072 bool isInvokable =
false;
3073 bool twoColumn =
false;
3076 twoColumn = (members.size() >= 16);
3077 }
else if (members.first()->isProperty()) {
3078 twoColumn = (members.size() >= 5);
3082 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3085 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3086 <<
"<tr><td class=\"topAlign\">";
3091 for (
const auto &member : members) {
3092 if (member->access() == Access::Private)
3096 out() <<
"<tr><td class=\"memItemLeft topAlign rightAlign\"> ";
3098 if (twoColumn && i == (members.size() + 1) / 2)
3099 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3100 out() <<
"<li class=\"fn\" translate=\"no\">";
3103 generateSynopsis(member, relative, marker, section.style(), alignNames);
3104 if (member->isFunction()) {
3105 const auto *fn =
static_cast<
const FunctionNode *>(member);
3106 if (fn->isPrivateSignal()) {
3107 hasPrivateSignals =
true;
3109 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3110 }
else if (fn->isInvokable()) {
3113 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3117 out() <<
"</td></tr>\n";
3123 out() <<
"</table></div>\n";
3127 out() <<
"</td></tr>\n</table></div>\n";
3130 if (hasPrivateSignals)
3138 && !section.inheritedMembers().isEmpty()) {
3140 generateSectionInheritedList(section, relative);
3147 const QList<std::pair<Aggregate *,
int>> &inheritedMembers = section.inheritedMembers();
3148 for (
const auto &member : inheritedMembers) {
3149 out() <<
"<li class=\"fn\" translate=\"no\">";
3150 out() << member.second <<
' ';
3151 if (member.second == 1) {
3152 out() << section.singular();
3154 out() << section.plural();
3156 out() <<
" inherited from <a href=\"" << fileName(member.first) <<
'#'
3157 << Generator::cleanRef(section.title().toLower()) <<
"\">"
3158 << protectEnc(member.first->plainFullName(relative)) <<
"</a></li>\n";
3165 QString marked = marker->markedUpSynopsis(node, relative, style);
3166 marked.replace(
"@param>",
"i>");
3169 marked.remove(
"<@name>");
3170 marked.remove(
"</@name>");
3174 static const QRegularExpression extraRegExp(
"<@extra>.*</@extra>",
3175 QRegularExpression::InvertedGreedinessOption);
3176 marked.remove(extraRegExp);
3178 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
3179 .arg(style == Section::Summary ?
"summary"_L1 :
"details"_L1));
3180 marked.replace(
"</@extra>",
"</code>");
3184 marked.remove(
"<@type>");
3185 marked.remove(
"</@type>");
3188 out() << highlightedCode(marked, relative, alignNames);
3191QString
HtmlGenerator::highlightedCode(
const QString &markedCode,
const Node *relative,
3194 QString src = markedCode;
3196 html.reserve(src.size());
3200 const QChar charLangle =
'<';
3201 const QChar charAt =
'@';
3203 static const QString typeTag(
"type");
3204 static const QString headerTag(
"headerfile");
3205 static const QString funcTag(
"func");
3206 static const QString linkTag(
"link");
3212 for (
int i = 0, srcSize = src.size(); i < srcSize;) {
3213 if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
3214 if (alignNames && !done) {
3215 html += QLatin1String(
"</td><td class=\"memItemRight bottomAlign\">");
3219 if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) {
3220 html += QLatin1String(
"<b>");
3221 const Node *n = CodeMarker::nodeForString(par1.toString());
3222 QString link = linkForNode(n, relative);
3223 addLink(link, arg, &html);
3224 html += QLatin1String(
"</b>");
3225 }
else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
3226 const FunctionNode *fn =
m_qdb->findFunctionNode(par1.toString(), relative, genus);
3227 QString link = linkForNode(fn, relative);
3228 addLink(link, arg, &html);
3229 par1 = QStringView();
3230 }
else if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
3231 par1 = QStringView();
3232 const Node *n =
m_qdb->findTypeNode(arg.toString(), relative, genus);
3233 html += QLatin1String(
"<span class=\"type\">");
3236 addLink(linkForNode(n, relative), arg, &html);
3240 addLink(linkForNode(n, relative), arg, &html);
3241 html += QLatin1String(
"</span>");
3242 }
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
3243 par1 = QStringView();
3244 if (arg.startsWith(QLatin1Char(
'&')))
3247 const Node *n =
m_qdb->findNodeForInclude(QStringList(arg.toString()));
3248 if (n && n != relative)
3249 addLink(linkForNode(n, relative), arg, &html);
3258 html += src.at(i++);
3275 html.reserve(src.size());
3276 static const QLatin1String spanTags[] = {
3277 QLatin1String(
"comment>"), QLatin1String(
"<span class=\"comment\">"),
3278 QLatin1String(
"preprocessor>"), QLatin1String(
"<span class=\"preprocessor\">"),
3279 QLatin1String(
"string>"), QLatin1String(
"<span class=\"string\">"),
3280 QLatin1String(
"char>"), QLatin1String(
"<span class=\"char\">"),
3281 QLatin1String(
"number>"), QLatin1String(
"<span class=\"number\">"),
3282 QLatin1String(
"op>"), QLatin1String(
"<span class=\"operator\">"),
3283 QLatin1String(
"type>"), QLatin1String(
"<span class=\"type\">"),
3284 QLatin1String(
"name>"), QLatin1String(
"<span class=\"name\">"),
3285 QLatin1String(
"keyword>"), QLatin1String(
"<span class=\"keyword\">")
3290 for (
int i = 0, n = src.size(); i < n;) {
3291 if (src.at(i) == QLatin1Char(
'<')) {
3292 if (src.at(i + 1) == QLatin1Char(
'@')) {
3294 bool handled =
false;
3295 for (
int k = 0; k != nTags; ++k) {
3296 const QLatin1String &tag = spanTags[2 * k];
3297 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3298 html += spanTags[2 * k + 1];
3306 while (i < n && src.at(i) != QLatin1Char(
'>'))
3311 }
else if (src.at(i + 1) == QLatin1Char(
'/') && src.at(i + 2) == QLatin1Char(
'@')) {
3313 bool handled =
false;
3314 for (
int k = 0; k != nTags; ++k) {
3315 const QLatin1String &tag = spanTags[2 * k];
3316 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3317 html += QLatin1String(
"</span>");
3325 while (i < n && src.at(i) != QLatin1Char(
'>'))
3344 if (match.hasMatch()) {
3346 qsizetype leftParenLoc = match.capturedStart(1);
3347 out() << protectEnc(atom->string().left(leftParenLoc));
3349 out() << protectEnc(atom->string().mid(leftParenLoc));
3353 out() << protectEnc(atom->string());
3358 return protect(string);
3364 if (html.isEmpty()) {
3371 qsizetype n = string.size();
3373 for (
int i = 0; i < n; ++i) {
3374 QChar ch = string.at(i);
3376 if (ch == QLatin1Char(
'&')) {
3378 }
else if (ch == QLatin1Char(
'<')) {
3380 }
else if (ch == QLatin1Char(
'>')) {
3382 }
else if (ch == QChar(8211)) {
3384 }
else if (ch == QChar(8212)) {
3386 }
else if (ch == QLatin1Char(
'"')) {
3389 if (!html.isEmpty())
3394 if (!html.isEmpty())
3403 QString result = Generator::fileBase(node);
3405 result += QLatin1String(
"-obsolete");
3412 return node->name();
3413 return Generator::fileName(node);
3417 const Node *actualNode)
3419 if (actualNode ==
nullptr)
3420 actualNode = apparentNode;
3421 bool link = !linkForNode(actualNode, relative).isEmpty();
3423 out() <<
"<a href=\"" << linkForNode(actualNode, relative);
3424 if (actualNode->isDeprecated())
3425 out() <<
"\" class=\"obsolete";
3428 out() << protectEnc(apparentNode->fullName(relative));
3437 generateExtractionMark(node, MemberMark);
3438 QString nodeRef =
nullptr;
3441 const QList<Node *> &collective = scn->collective();
3442 if (collective.size() > 1)
3443 out() <<
"<div class=\"fngroup\">\n";
3444 for (
const auto *sharedNode : collective) {
3445 nodeRef = refForNode(sharedNode);
3446 out() << R"(<h3 class="fn fngroupitem" translate="no" id=")" << nodeRef <<
"\">";
3447 generateSynopsis(sharedNode, relative, marker, Section::Details);
3450 if (collective.size() > 1)
3454 nodeRef = refForNode(node);
3456 out() << R"(<h3 class="flags" id=")" << nodeRef <<
"\">";
3462 out() << R"(<h3 class="fn" translate="no" id=")" << nodeRef <<
"\">";
3464 out() <<
"</h3>" <<
'\n';
3477 const auto property =
static_cast<
const PropertyNode *>(node);
3486 out() <<
"<p><b>Access functions:</b></p>\n";
3487 generateSectionList(section, node, marker);
3494 out() <<
"<p><b>Notifier signal:</b></p>\n";
3495 generateSectionList(notifiers, node, marker);
3499 const auto *enumTypeNode =
static_cast<
const EnumNode *>(node);
3501 out() <<
"<p>The " << protectEnc(enumTypeNode->flagsType()->name())
3502 <<
" type is a typedef for "
3503 <<
"<a href=\"" << m_qflagsHref <<
"\">QFlags</a><"
3504 << protectEnc(enumTypeNode->name()) <<
">. It stores an OR combination of "
3505 << protectEnc(enumTypeNode->name()) <<
" values.</p>\n";
3508 generateAlsoList(node, marker);
3509 generateExtractionMark(node, EndMark);
3513
3514
3515
3516
3523 if (!m_link.isEmpty())
3524 out() <<
"<a href=\"" << m_link <<
"\" translate=\"no\">";
3532 if (m_link.isEmpty())
3535 const QString &translate_attr =
3536 (node && node->genus() & Node::API) ?
" translate=\"no\""_L1 :
""_L1;
3538 if (node ==
nullptr || (relative !=
nullptr && node->status() == relative->status()))
3539 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3540 else if (node->isDeprecated())
3541 out() <<
"<a href=\"" << m_link <<
"\" class=\"obsolete\"%1>"_L1.arg(translate_attr);
3543 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3554 if (!m_link.isEmpty())
3559
3560
3561
3565 if (!members.isEmpty()) {
3567 for (
const auto &member : members) {
3568 out() <<
"<li class=\"fn\" translate=\"no\">";
3569 generateQmlItem(member, relative, marker,
true);
3570 if (member->isPropertyGroup()) {
3571 const auto *scn =
static_cast<
const SharedCommentNode *>(member);
3572 if (scn->count() > 0) {
3574 const QList<Node *> &sharedNodes = scn->collective();
3575 for (
const auto &node : sharedNodes) {
3576 if (node->isQmlProperty()) {
3577 out() <<
"<li class=\"fn\" translate=\"no\">";
3578 generateQmlItem(node, relative, marker,
true);
3592
3593
3594
3598 generateExtractionMark(node, MemberMark);
3600 QString qmlItemHeader(
"<div class=\"qmlproto\" translate=\"no\">\n"
3601 "<div class=\"table\"><table class=\"qmlname\">\n");
3603 QString qmlItemStart(
"<tr valign=\"top\" class=\"odd\" id=\"%1\">\n"
3604 "<td class=\"%2\"><p>\n");
3605 QString qmlItemEnd(
"</p></td></tr>\n");
3607 QString qmlItemFooter(
"</table></div></div>\n");
3609 auto generateQmlProperty = [&](
Node *n) {
3610 out() << qmlItemStart.arg(refForNode(n),
"tblQmlPropNode");
3611 generateQmlItem(n, relative, marker,
false);
3612 out() << qmlItemEnd;
3615 auto generateQmlMethod = [&](
Node *n) {
3616 out() << qmlItemStart.arg(refForNode(n),
"tblQmlFuncNode");
3618 out() << qmlItemEnd;
3621 out() <<
"<div class=\"qmlitem\">";
3624 out() << qmlItemHeader;
3625 if (!scn->name().isEmpty()) {
3626 const QString nodeRef = refForNode(scn);
3627 out() << R"(<tr valign="top" class="even" id=")" << nodeRef <<
"\">";
3628 out() <<
"<th class=\"centerAlign\"><p>";
3629 out() <<
"<b>" << scn->name() <<
" group</b>";
3630 out() <<
"</p></th></tr>\n";
3632 const QList<Node *> sharedNodes = scn->collective();
3633 for (
const auto &sharedNode : sharedNodes) {
3634 if (sharedNode->isQmlProperty())
3635 generateQmlProperty(sharedNode);
3637 out() << qmlItemFooter;
3639 out() << qmlItemHeader;
3640 generateQmlProperty(node);
3641 out() << qmlItemFooter;
3644 const QList<Node *> &sharedNodes = scn->collective();
3645 if (sharedNodes.size() > 1)
3646 out() <<
"<div class=\"fngroup\">\n";
3647 out() << qmlItemHeader;
3648 for (
const auto &sharedNode : sharedNodes) {
3650 if (sharedNode->isFunction(Node::QML))
3651 generateQmlMethod(sharedNode);
3652 else if (sharedNode->isQmlProperty())
3653 generateQmlProperty(sharedNode);
3655 out() << qmlItemFooter;
3656 if (sharedNodes.size() > 1)
3659 out() << qmlItemHeader;
3660 generateQmlMethod(node);
3661 out() << qmlItemFooter;
3664 out() <<
"<div class=\"qmldoc\">";
3669 generateAlsoList(node, marker);
3670 out() <<
"</div></div>";
3671 generateExtractionMark(node, EndMark);
3674void HtmlGenerator::generateExtractionMark(
const Node *node, ExtractionMarkType markType)
3676 if (markType != EndMark) {
3677 out() <<
"<!-- $$$" + node->name();
3678 if (markType == MemberMark) {
3680 const auto *func =
static_cast<
const FunctionNode *>(node);
3682 if (func->overloadNumber() == 0)
3683 out() <<
"[overload1]";
3684 out() <<
"$$$" + func->name() + func->parameters().rawSignature().remove(
' ');
3688 const auto *prop =
static_cast<
const PropertyNode *>(node);
3690 for (
const auto *propFuncNode : list) {
3691 if (propFuncNode->isFunction()) {
3692 const auto *func =
static_cast<
const FunctionNode *>(propFuncNode);
3693 out() <<
"$$$" + func->name()
3694 + func->parameters().rawSignature().remove(
' ');
3698 const auto *enumNode =
static_cast<
const EnumNode *>(node);
3699 const auto &items = enumNode->items();
3700 for (
const auto &item : items)
3701 out() <<
"$$$" + item.name();
3703 }
else if (markType == BriefMark) {
3705 }
else if (markType == DetailedDescriptionMark) {
3706 out() <<
"-description";
3710 out() <<
"<!-- @@@" + node->name() +
" -->\n";
#define ATOM_FORMATTING_TELETYPE
#define ATOM_LIST_LOWERALPHA
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_LIST_UPPERALPHA
#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
NodeMap getMembers(Node::NodeType type) const
Returns a map containing this collection node's member nodes with a specified node type.
bool wasSeen() const override
Returns the seen flag data member of this node if it is a NamespaceNode or a CollectionNode.
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.
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.
int appendSortedQmlNames(Text &text, const Node *base, const NodeList &subs)
void generateOverloadedSignal(const Node *node, CodeMarker *marker)
If the node is an overloaded signal, add a node with an example on how to connect to it.
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()
Updates the generator's m_showInternal from the Config.
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.
The Location class provides a way to mark a location in a file.
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.
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.
NodeType
An unsigned char value that identifies an object as a particular subclass of Node.
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 isFunction(Genus g=DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
bool isSharedCommentNode() const
Returns true if the node type is SharedComment.
virtual bool isInternal() const
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
bool isHeader() const
Returns true if the node type is HeaderFile.
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.
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
Access access() const
Returns the node's Access setting, which can be Public, Protected, or Private.
Genus
An unsigned char value that specifies whether the Node represents a C++ element, a QML element,...
bool isProperty() const
Returns true if the node type is Property.
bool isModule() const
Returns true if the node type is Module.
virtual bool isPropertyGroup() const
Returns true if the node is a SharedCommentNode for documenting multiple C++ properties or multiple Q...
Genus genus() const
Returns this node's Genus.
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...
LinkType
An unsigned char value that probably should be moved out of the Node base class.
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.
Status status() const
Returns the node's status value.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.
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.
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(Node::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...
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...
bool isInternal() const override
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
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 & stdDetailsSections()
SectionVector & stdCppClassDetailsSections()
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()
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 Node::NodeType typeFromString(const Atom *atom)
Returns the type of this atom as an enumeration.
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
#define COMMAND_INQMLMODULE
#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_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
Represents a file that is reachable by QDoc based on its current configuration.