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};
154 .asString(m_project + QLatin1String(
" Reference Documentation"));
156 m_projectUrl = config->get(
CONFIG_URL).asString();
165
166
167
168 if (m_helpProjectWriter)
169 m_helpProjectWriter->reset(m_project.toLower() +
".qhp",
this);
171 m_helpProjectWriter =
new HelpProjectWriter(m_project.toLower() +
".qhp",
this);
173 if (!m_manifestWriter)
186 .asString(m_homepage);
193 .asString(m_landingpage);
200 .asString(QLatin1String(
"C++ Classes"));
207 .asString(QLatin1String(
"QML Types"));
216
217
229
230
231
232
233
234
235
238 Node *qflags =
m_qdb->findClassNode(QStringList(
"QFlags"));
240 m_qflagsHref = linkForNode(qflags,
nullptr);
246 m_project.toLower().simplified().replace(QLatin1Char(
' '), QLatin1Char(
'-'));
247 m_qdb->generateIndex(outputDir() + QLatin1Char(
'/') + fileBase +
".index", m_projectUrl,
248 m_projectDescription,
this);
255
256
257 if (!tagFile_.isEmpty()) {
259 tagFileWriter.generateTagFile(tagFile_,
this);
265
266
269 SubTitleSize subTitleSize = LargeSubTitle;
270 QString fullTitle = en->fullTitle();
272 beginSubPage(en, linkForExampleFile(resolved_file.get_query()));
273 generateHeader(fullTitle, en, marker);
274 generateTitle(fullTitle, Text() << en->subtitle(), subTitleSize, en, marker);
279 QString code = quoter.quoteTo(en->location(), QString(), QString());
280 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
284 generateText(text, en, codeMarker);
289
290
293 qsizetype idx, skipAhead = 0;
294 static bool in_para =
false;
299 QString name = atom->string();
300 if (relative && relative->name() == name.replace(QLatin1String(
"()"), QLatin1String())) {
301 out() << protectEnc(atom->string());
310 const Node *node =
nullptr;
311 QString link = getAutoLink(atom, relative, &node, genus);
312 if (link.isEmpty()) {
315 QStringLiteral(
"Can't autolink to '%1'").arg(atom->string()));
320 if (link.isEmpty()) {
321 out() << protectEnc(atom->string());
323 beginLink(link, node, relative);
328 out() << protectEnc(atom->string());
335 skipAhead = skipAtoms(atom, Atom::BriefRight);
341 case Atom::BriefRight:
342 if (hasBrief(relative))
350 out() << protectEnc(plainCode(atom->string()));
353 case Atom::CaptionLeft:
354 out() <<
"<p class=\"figCaption\">";
365 out() <<
"<pre class=\"qml\" translate=\"no\">"
366 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative,
368 m_codePrefix, m_codeSuffix)
372 out() <<
"<pre class=\"cpp\" translate=\"no\">"
373 << trimmedTrailing(highlightedCode(indent(m_codeIndent, atom->string()), relative),
374 m_codePrefix, m_codeSuffix)
378 out() <<
"<pre class=\"cpp plain\" translate=\"no\">"
379 << trimmedTrailing(protectEnc(plainCode(indent(m_codeIndent, atom->string()))),
380 m_codePrefix, m_codeSuffix)
383 case Atom::DetailsLeft:
384 out() <<
"<details>\n";
385 if (!atom->string().isEmpty())
386 out() <<
"<summary>" << protectEnc(atom->string()) <<
"</summary>\n";
388 out() <<
"<summary>...</summary>\n";
390 case Atom::DetailsRight:
391 out() <<
"</details>\n";
395 if (!atom->string().isEmpty())
396 out() <<
' ' << atom->string();
410 case Atom::FootnoteRight:
418 case Atom::FormattingLeft:
419 if (atom->string().startsWith(
"span "))
420 out() <<
'<' + atom->string() <<
'>';
422 out() << formattingLeftMap()[atom->string()];
430 const Node *node{
nullptr};
431 const Atom tm_link(Atom::NavLink, m_trademarkspage);
432 if (
const auto &link = getLink(&tm_link, relative, &node);
433 !link.isEmpty() && node != relative)
434 out() <<
"<a href=\"%1\">%2</a>"_L1.arg(link, formattingRightMap()[atom->string()]);
436 out() << formattingRightMap()[atom->string()];
439 }
else if (atom->string().startsWith(
"span ")) {
442 out() << formattingRightMap()[atom->string()];
446 if (
const auto *cn = m_qdb->getCollectionNode(atom->string(), Node::Group); cn)
447 generateList(cn, marker, atom->string(), Generator::sortOrder(atom->strings().last()));
450 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
451 if (atom->string() == QLatin1String(
"annotatedclasses")) {
452 generateAnnotatedList(relative, marker, m_qdb->getCppClasses().values(), sortOrder);
453 }
else if (atom->string() == QLatin1String(
"annotatedexamples")) {
455 }
else if (atom->string() == QLatin1String(
"annotatedattributions")) {
457 }
else if (atom->string() == QLatin1String(
"classes")) {
458 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true,
460 }
else if (atom->string().contains(
"classes ")) {
461 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
462 generateCompactList(Generic, relative, m_qdb->getCppClasses(),
true, rootName);
463 }
else if (atom->string() == QLatin1String(
"qmlvaluetypes")
464 || atom->string() == QLatin1String(
"qmlbasictypes")) {
465 generateCompactList(Generic, relative, m_qdb->getQmlValueTypes(),
true,
467 }
else if (atom->string() == QLatin1String(
"qmltypes")) {
468 generateCompactList(Generic, relative, m_qdb->getQmlTypes(),
true, QStringLiteral(
""));
469 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
471 QString moduleName = atom->string().mid(idx + 8).trimmed();
473 if (
const auto *cn = qdb->getCollectionNode(moduleName, moduleType)) {
475 switch (moduleType) {
479 generateAnnotatedList(relative, marker, map.values(), sortOrder);
482 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
486 generateAnnotatedList(relative, marker, map.values(), sortOrder);
489 generateAnnotatedList(relative, marker, cn->members(), sortOrder);
493 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
495 }
else if (atom->string() == QLatin1String(
"obsoleteclasses")) {
496 generateCompactList(Generic, relative, m_qdb->getObsoleteClasses(),
false,
497 QStringLiteral(
"Q"));
498 }
else if (atom->string() == QLatin1String(
"obsoleteqmltypes")) {
499 generateCompactList(Generic, relative, m_qdb->getObsoleteQmlTypes(),
false,
501 }
else if (atom->string() == QLatin1String(
"obsoletecppmembers")) {
502 generateCompactList(Obsolete, relative, m_qdb->getClassesWithObsoleteMembers(),
false,
503 QStringLiteral(
"Q"));
504 }
else if (atom->string() == QLatin1String(
"obsoleteqmlmembers")) {
505 generateCompactList(Obsolete, relative, m_qdb->getQmlTypesWithObsoleteMembers(),
false,
507 }
else if (atom->string() == QLatin1String(
"functionindex")) {
508 generateFunctionIndex(relative);
509 }
else if (atom->string() == QLatin1String(
"attributions")) {
510 generateAnnotatedList(relative, marker, m_qdb->getAttributions().values(), sortOrder);
511 }
else if (atom->string() == QLatin1String(
"legalese")) {
512 generateLegaleseList(relative, marker);
513 }
else if (atom->string() == QLatin1String(
"overviews")) {
514 generateList(relative, marker,
"overviews", sortOrder);
515 }
else if (atom->string() == QLatin1String(
"cpp-modules")) {
516 generateList(relative, marker,
"cpp-modules", sortOrder);
517 }
else if (atom->string() == QLatin1String(
"qml-modules")) {
518 generateList(relative, marker,
"qml-modules", sortOrder);
519 }
else if (atom->string() == QLatin1String(
"namespaces")) {
520 generateAnnotatedList(relative, marker, m_qdb->getNamespaces().values(), sortOrder);
521 }
else if (atom->string() == QLatin1String(
"related")) {
522 generateList(relative, marker,
"related", sortOrder);
526 if (!generateGroupList(
const_cast<CollectionNode *>(cn), sortOrder))
528 QString(
"'\\generatelist %1' group is empty").arg(atom->string()));
531 QString(
"'\\generatelist %1' no such group").arg(atom->string()));
545 const QList<Section> sinceSections = sections.sinceSections();
546 for (
const auto §ion : sinceSections) {
547 if (!section.members().isEmpty()) {
549 <<
"<a href=\"#" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
550 << section.title() <<
"</a></li>\n";
556 for (
const auto §ion : sinceSections) {
557 if (!section.members().isEmpty()) {
558 out() <<
"<h3 id=\"" << Utilities::asAsciiPrintable(section.title()) <<
"\">"
559 << protectEnc(section.title()) <<
"</h3>\n";
560 if (index == Sections::SinceClasses)
561 generateCompactList(Generic, relative, ncmap,
false, QStringLiteral(
"Q"));
562 else if (index == Sections::SinceQmlTypes)
563 generateCompactList(Generic, relative, nqcmap,
false, QStringLiteral(
""));
564 else if (index == Sections::SinceMemberFunctions
565 || index == Sections::SinceQmlMethods
566 || index == Sections::SinceQmlProperties) {
568 QMap<QString, NodeMultiMap> parentmaps;
570 const QList<Node *> &members = section.members();
571 for (
const auto &member : members) {
572 QString parent_full_name = (*member).parent()->fullName();
574 auto parent_entry = parentmaps.find(parent_full_name);
575 if (parent_entry == parentmaps.end())
576 parent_entry = parentmaps.insert(parent_full_name, NodeMultiMap());
577 parent_entry->insert(member->name(), member);
580 for (
auto map = parentmaps.begin(); map != parentmaps.end(); ++map) {
581 NodeVector nv = map->values().toVector();
582 auto parent = nv.front()->parent();
584 out() << ((index == Sections::SinceMemberFunctions) ?
"<p>Class " :
"<p>QML Type ");
586 out() <<
"<a href=\"" << linkForNode(parent, relative) <<
"\" translate=\"no\">";
587 QStringList pieces = parent->fullName().split(
"::");
588 out() << protectEnc(pieces.last());
592 generateSection(nv, relative, marker);
595 }
else if (index == Sections::SinceEnumValues) {
596 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
597 const auto map_it = m_qdb->newEnumValueMaps().constFind(atom->string());
598 for (
auto it = map_it->cbegin(); it != map_it->cend(); ++it) {
599 out() <<
"<tr><td class=\"memItemLeft\"> enum value </td><td class=\"memItemRight\">"
600 <<
"<b><a href=\"" << linkForNode(it.value(),
nullptr) <<
"\">"
601 << it.key() <<
"</a></b></td></tr>\n";
603 out() <<
"</table></div>\n";
605 generateSection(section.members(), relative, marker);
622 if (atom->type() == Atom::Image)
623 out() <<
"<p class=\"centerAlign\">";
625 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
626 if (!maybe_resolved_file) {
628 relative->location().warning(
629 QStringLiteral(
"Missing image: %1").arg(protectEnc(atom->string())));
630 out() <<
"<font color=\"red\">[Missing image " << protectEnc(atom->string())
634 QString file_name{QFileInfo{file.get_path()}.fileName()};
653 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
656 out() <<
"<img src=\"" <<
"images/" + protectEnc(file_name) <<
'"';
664 out() <<
" alt=\"" << protectEnc(text) <<
'"';
666 out() <<
" alt=\"\"";
671 m_helpProjectWriter->addExtraFile(
"images/" + file_name);
672 setImageFileName(relative,
"images/" + file_name);
675 if (atom->type() == Atom::Image)
684 QString admonType = atom->typeString();
687 out() <<
"<div class=\"admonition " << admonType.toLower() <<
"\">\n"
690 out() << admonType <<
": ";
693 case Atom::ImportantRight:
694 case Atom::NoteRight:
695 case Atom::WarningRight:
699 case Atom::LegaleseLeft:
700 out() <<
"<div class=\"LegaleseLeft\">";
702 case Atom::LegaleseRight:
705 case Atom::LineBreak:
714 const Node *node =
nullptr;
715 QString link = getLink(atom, relative, &node);
720 QStringLiteral(
"Can't link to '%1'").arg(atom->string()));
722 beginLink(link, node, relative);
726 QString link = linkForExampleFile(atom->string());
731 QString link = atom->string();
732 link =
"images/used-in-examples/" + link;
737 const Node *node = CodeMarker::nodeForString(atom->string());
738 beginLink(linkForNode(node, relative), node, relative);
751 out() << R"(<div class="table"><table class="valuelist">)";
754 if (++m_numTableRows % 2 == 1)
755 out() << R"(<tr valign="top" class="odd">)";
757 out() << R"(<tr valign="top" class="even">)";
759 out() <<
"<th class=\"tblConst\">Constant</th>";
762 if (relative->isEnumType())
763 out() <<
"<th class=\"tblval\">Value</th>";
765 out() <<
"<th class=\"tbldscr\">Description</th></tr>\n";
767 out() <<
"<tr><th class=\"tblConst\">Constant</th><th "
768 "class=\"tblVal\">Value</th></tr>\n";
785 out() << QString(R"(<ol class="%1" type="%1" start="%2">)")
786 .arg(olType, atom->next()->string());
788 out() << QString(R"(<ol class="%1" type="%1">)").arg(olType);
797 std::pair<QString,
int> pair = getAtomListValue(atom);
798 skipAhead = pair.second;
799 QString t = protectEnc(plainCode(marker->markedUpEnumValue(pair.first, relative)));
800 out() <<
"<tr><td class=\"topAlign\"><code translate=\"no\">" << t <<
"</code>";
803 out() <<
"</td><td class=\"topAlign tblval\">";
804 const auto *enume =
static_cast<
const EnumNode *>(relative);
805 QString itemValue = enume->itemValue(atom->next()->string());
806 if (itemValue.isEmpty())
809 out() <<
"<code translate=\"no\">" << protectEnc(itemValue) <<
"</code>";
813 case Atom::SinceTagRight:
814 case Atom::ListTagRight:
823 out() <<
"</td><td class=\"topAlign\">";
824 if (matchAhead(atom, Atom::ListItemRight))
830 if (matchAhead(atom, Atom::ParaLeft))
837 out() <<
"</td></tr>\n";
848 out() <<
"</table></div>\n";
868 case Atom::QuotationLeft:
869 out() <<
"<blockquote>";
871 case Atom::QuotationRight:
872 out() <<
"</blockquote>\n";
874 case Atom::RawString:
875 out() << atom->string();
881 int unit = atom->string().toInt() +
hOffset(relative
);
882 out() <<
"<h" + QString::number(unit) + QLatin1Char(
' ') <<
"id=\""
883 << Tree::refForAtom(atom) <<
"\">";
887 case Atom::SectionHeadingRight:
888 out() <<
"</h" + QString::number(atom->string().toInt() + hOffset(relative)) +
">\n";
899 out() << protectEnc(atom->string());
903 std::pair<QString, QString> pair = getTableWidthAttr(atom);
904 QString attr = pair.second;
905 QString width = pair.first;
912 out() << R"(<div class="table"><table class=")" << attr <<
'"';
913 if (!width.isEmpty())
914 out() <<
" width=\"" << width <<
'"';
918 case Atom::TableRight:
919 out() <<
"</table></div>\n";
921 case Atom::TableHeaderLeft:
922 out() <<
"<thead><tr class=\"qt-style\">";
925 case Atom::TableHeaderRight:
929 out() <<
"\n<tr class=\"qt-style\">";
931 out() <<
"</thead>\n";
935 case Atom::TableRowLeft:
936 if (!atom->string().isEmpty())
937 out() <<
"<tr " << atom->string() <<
'>';
938 else if (++m_numTableRows % 2 == 1)
939 out() << R"(<tr valign="top" class="odd">)";
941 out() << R"(<tr valign="top" class="even">)";
943 case Atom::TableRowRight:
952 for (
int i = 0; i < atom->count(); ++i) {
955 const QString &p = atom->string(i);
956 if (p.contains(
'=')) {
959 QStringList spans = p.split(QLatin1Char(
','));
960 if (spans.size() == 2) {
961 if (spans.at(0) !=
"1")
962 out() <<
" colspan=\"" << spans.at(0) <<
'"';
963 if (spans.at(1) !=
"1")
964 out() <<
" rowspan=\"" << spans.at(1) <<
'"';
969 if (matchAhead(atom, Atom::ParaLeft))
978 if (matchAhead(atom, Atom::ParaLeft))
986 out() <<
"<span id=\"" << Utilities::asAsciiPrintable(atom->string()) <<
"\"></span>";
988 case Atom::UnhandledFormat:
989 out() <<
"<b class=\"redFont\"><Missing HTML></b>";
991 case Atom::UnknownCommand:
992 out() << R"(<b class="redFont"><code translate=\"no\">\)" << protectEnc(atom->string()) <<
"</code></b>";
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
1038
1040 auto link_for_group = [
this](
const CollectionNode *group) -> QString {
1041 QString target{linkForNode(group,
nullptr)};
1042 return (target.isEmpty()) ? protectEnc(group->name()) :
"<a href=\"" + target +
"\">" + protectEnc(group->fullTitle()) +
"</a>";
1047 const QStringList &groups_names{node->groupNames()};
1048 if (groups_names.isEmpty())
1051 std::vector<CollectionNode *> groups_nodes(groups_names.size(),
nullptr);
1052 std::transform(groups_names.cbegin(), groups_names.cend(), groups_nodes.begin(),
1056 return (group && group
->wasSeen()) ? group :
nullptr;
1058 groups_nodes.erase(
std::remove(groups_nodes.begin(), groups_nodes.end(),
nullptr), groups_nodes.end());
1060 if (!groups_nodes.empty()) {
1061 text += node->name() +
" is part of ";
1063 for (std::vector<CollectionNode *>::size_type index{0}; index < groups_nodes.size(); ++index) {
1064 text += link_for_group(groups_nodes[index]) + Utilities::separator(index, groups_nodes.size());
1071
1072
1073
1074
1084 QString typeWord = aggregate->typeWord(
true);
1087 fullTitle = aggregate->plainFullName();
1088 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1093 fullTitle = aggregate->plainFullName();
1094 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1098 title = fullTitle = aggregate->fullTitle();
1105 if (aggregate
->parent()->isInAPI() || templateDecl) {
1107 subtitleText <<
"%1 "_L1.arg((*templateDecl).to_qstring());
1108 subtitleText << aggregate->typeWord(
false) <<
" "_L1;
1109 auto ancestors = fullTitle.split(
"::"_L1);
1110 ancestors.pop_back();
1111 for (
const auto &a : ancestors)
1112 subtitleText << Atom(Atom::AutoLink, a) <<
"::"_L1;
1113 subtitleText << aggregate->plainName();
1116 generateHeader(title, aggregate, marker);
1117 generateTableOfContents(aggregate, marker, summarySections);
1118 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1122 brief <<
"The " << ns->name() <<
" namespace includes the following elements from module "
1129 generateText(brief, ns, marker);
1132 generateBrief(aggregate, marker);
1134 const auto parentIsClass = aggregate
->parent()->isClassNode();
1137 generateRequisites(aggregate, marker);
1142 QString membersLink = generateAllMembersFile(Sections::allMembersSection(), marker);
1143 if (!membersLink.isEmpty()) {
1144 openUnorderedList();
1145 out() <<
"<li><a href=\"" << membersLink <<
"\">"
1146 <<
"List of all members, including inherited members</a></li>\n";
1148 QString obsoleteLink = generateObsoleteMembersFile(sections, marker);
1149 if (!obsoleteLink.isEmpty()) {
1150 openUnorderedList();
1151 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1152 <<
"Deprecated members</a></li>\n";
1155 if (QString groups_text{groupReferenceText(aggregate)}; !groups_text.isEmpty()) {
1156 openUnorderedList();
1158 out() <<
"<li>" << groups_text <<
"</li>\n";
1161 closeUnorderedList();
1167 bool needOtherSection =
false;
1169 for (
const auto §ion : std::as_const(*summarySections)) {
1170 if (section.members().isEmpty() && section.reimplementedMembers().isEmpty()) {
1171 if (!section.inheritedMembers().isEmpty())
1172 needOtherSection =
true;
1174 if (!section.members().isEmpty()) {
1175 QString ref = registerRef(section.title().toLower());
1176 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1177 generateSection(section.members(), aggregate, marker);
1179 if (!section.reimplementedMembers().isEmpty()) {
1180 QString name = QString(
"Reimplemented ") + section.title();
1181 QString ref = registerRef(name.toLower());
1182 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(name) <<
"</h2>\n";
1183 generateSection(section.reimplementedMembers(), aggregate, marker);
1186 if (!section.inheritedMembers().isEmpty()) {
1188 generateSectionInheritedList(section, aggregate);
1194 if (needOtherSection) {
1195 out() <<
"<h3>Additional Inherited Members</h3>\n"
1198 for (
const auto §ion : std::as_const(*summarySections)) {
1199 if (section.members().isEmpty() && !section.inheritedMembers().isEmpty())
1200 generateSectionInheritedList(section, aggregate);
1205 if (aggregate
->doc().isEmpty()) {
1206 QString command =
"documentation";
1208 command = R"('\class' comment)";
1211 QStringLiteral(
"No %1 for '%2'").arg(command, aggregate->plainSignature()));
1214 generateExtractionMark(aggregate, DetailedDescriptionMark);
1215 out() <<
"<div class=\"descr\">\n"
1216 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1217 <<
"Detailed Description"
1220 out() <<
"</div>\n";
1221 generateAlsoList(aggregate, marker);
1222 generateExtractionMark(aggregate, EndMark);
1225 for (
const auto §ion : std::as_const(*detailsSections)) {
1226 bool headerGenerated =
false;
1227 if (section.isEmpty())
1230 const QList<Node *> &members = section.members();
1231 for (
const auto &member : members) {
1232 if (member->access() == Access::Private)
1234 if (!headerGenerated) {
1235 if (!section.divClass().isEmpty())
1236 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1237 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1238 headerGenerated =
true;
1240 if (!member->isClassNode())
1241 generateDetailedMember(member, aggregate, marker);
1243 out() <<
"<h3> class ";
1244 generateFullName(member, aggregate);
1246 generateBrief(member, marker, aggregate);
1250 names << member->name();
1251 if (member->isFunction()) {
1252 const auto *func =
reinterpret_cast<
const FunctionNode *>(member);
1253 if (func->isSomeCtor() || func->isDtor() || func->overloadNumber() != 0)
1255 }
else if (member->isProperty()) {
1256 const auto *prop =
reinterpret_cast<
const PropertyNode *>(member);
1257 if (!prop->getters().isEmpty() && !names.contains(prop->getters().first()->name()))
1258 names << prop->getters().first()->name();
1259 if (!prop->setters().isEmpty())
1260 names << prop->setters().first()->name();
1261 if (!prop->resetters().isEmpty())
1262 names << prop->resetters().first()->name();
1263 if (!prop->notifiers().isEmpty())
1264 names << prop->notifiers().first()->name();
1265 }
else if (member->isEnumType()) {
1266 const auto *enume =
reinterpret_cast<
const EnumNode *>(member);
1267 if (enume->flagsType())
1268 names << enume->flagsType()->name();
1269 const auto &enumItemNameList = enume->doc().enumItemNames();
1270 const auto &omitEnumItemNameList = enume->doc().omitEnumItemNames();
1271 const auto items = QSet<QString>(enumItemNameList.cbegin(), enumItemNameList.cend())
1272 - QSet<QString>(omitEnumItemNameList.cbegin(), omitEnumItemNameList.cend());
1273 for (
const QString &enumName : items) {
1274 names << plainCode(marker->markedUpEnumValue(enumName, enume));
1278 if (headerGenerated && !section.divClass().isEmpty())
1279 out() <<
"</div>\n";
1281 generateFooter(aggregate);
1296 rawTitle = aggregate->plainName();
1297 fullTitle = aggregate->plainFullName();
1298 title = rawTitle +
" Proxy Page";
1301 generateHeader(title, aggregate, marker);
1302 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1303 generateBrief(aggregate, marker);
1304 for (
auto it = summarySections->constBegin(); it != summarySections->constEnd(); ++it) {
1305 if (!it->members().isEmpty()) {
1306 QString ref = registerRef(it->title().toLower());
1307 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(it->title()) <<
"</h2>\n";
1308 generateSection(it->members(), aggregate, marker);
1312 if (!aggregate
->doc().isEmpty()) {
1313 generateExtractionMark(aggregate, DetailedDescriptionMark);
1314 out() <<
"<div class=\"descr\">\n"
1315 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1316 <<
"Detailed Description"
1319 out() <<
"</div>\n";
1320 generateAlsoList(aggregate, marker);
1321 generateExtractionMark(aggregate, EndMark);
1324 for (
const auto §ion : std::as_const(*detailsSections)) {
1325 if (section.isEmpty())
1328 if (!section.divClass().isEmpty())
1329 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1330 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1332 const QList<Node *> &members = section.members();
1333 for (
const auto &member : members) {
1334 if (!member->isPrivate()) {
1335 if (!member->isClassNode())
1336 generateDetailedMember(member, aggregate, marker);
1338 out() <<
"<h3> class ";
1339 generateFullName(member, aggregate);
1341 generateBrief(member, marker, aggregate);
1345 names << member->name();
1346 if (member->isFunction()) {
1347 const auto *func =
reinterpret_cast<
const FunctionNode *>(member);
1348 if (func->isSomeCtor() || func->isDtor() || func->overloadNumber() != 0)
1350 }
else if (member->isEnumType()) {
1351 const auto *enume =
reinterpret_cast<
const EnumNode *>(member);
1352 if (enume->flagsType())
1353 names << enume->flagsType()->name();
1354 const auto &enumItemNameList = enume->doc().enumItemNames();
1355 const auto &omitEnumItemNameList = enume->doc().omitEnumItemNames();
1357 QSet<QString>(enumItemNameList.cbegin(), enumItemNameList.cend())
1358 - QSet<QString>(omitEnumItemNameList.cbegin(),
1359 omitEnumItemNameList.cend());
1360 for (
const QString &enumName : items)
1361 names << plainCode(marker->markedUpEnumValue(enumName, enume));
1365 if (!section.divClass().isEmpty())
1366 out() <<
"</div>\n";
1368 generateFooter(aggregate);
1372
1373
1374
1378 SubTitleSize subTitleSize = LargeSubTitle;
1379 QString htmlTitle = qcn->fullTitle();
1381 htmlTitle.append(
" QML Value Type");
1383 htmlTitle.append(
" QML Type");
1386 generateHeader(htmlTitle, qcn, marker);
1388 generateTableOfContents(qcn, marker, §ions.stdQmlTypeSummarySections());
1389 marker = CodeMarker::markerForLanguage(QLatin1String(
"QML"));
1390 generateTitle(htmlTitle, Text() << qcn->subtitle(), subTitleSize, qcn, marker);
1391 generateBrief(qcn, marker);
1392 generateQmlRequisites(qcn, marker);
1395 QString allQmlMembersLink;
1398 if (!qcn->isQmlBasicType())
1399 allQmlMembersLink = generateAllQmlMembersFile(sections, marker);
1400 QString obsoleteLink = generateObsoleteQmlMembersFile(sections, marker);
1401 if (!allQmlMembersLink.isEmpty() || !obsoleteLink.isEmpty()) {
1402 openUnorderedList();
1404 if (!allQmlMembersLink.isEmpty()) {
1405 out() <<
"<li><a href=\"" << allQmlMembersLink <<
"\">"
1406 <<
"List of all members, including inherited members</a></li>\n";
1408 if (!obsoleteLink.isEmpty()) {
1409 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1410 <<
"Deprecated members</a></li>\n";
1414 if (QString groups_text{groupReferenceText(qcn)}; !groups_text.isEmpty()) {
1415 openUnorderedList();
1417 out() <<
"<li>" << groups_text <<
"</li>\n";
1420 closeUnorderedList();
1422 const QList<Section> &stdQmlTypeSummarySections = sections.stdQmlTypeSummarySections();
1423 for (
const auto §ion : stdQmlTypeSummarySections) {
1424 if (!section.isEmpty()) {
1425 QString ref = registerRef(section.title().toLower());
1426 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1427 generateQmlSummary(section.members(), qcn, marker);
1431 generateExtractionMark(qcn, DetailedDescriptionMark);
1432 out() <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1433 <<
"Detailed Description"
1436 generateAlsoList(qcn, marker);
1437 generateExtractionMark(qcn, EndMark);
1439 const QList<Section> &stdQmlTypeDetailsSections = sections.stdQmlTypeDetailsSections();
1440 for (
const auto §ion : stdQmlTypeDetailsSections) {
1441 if (!section.isEmpty()) {
1442 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1443 const QList<Node *> &members = section.members();
1444 for (
const auto member : members) {
1445 generateDetailedQmlMember(member, qcn, marker);
1450 generateFooter(qcn);
1455
1456
1457
1460 SubTitleSize subTitleSize = LargeSubTitle;
1461 QString fullTitle = pn->fullTitle();
1463 generateHeader(fullTitle, pn, marker);
1465
1466
1467
1468 if ((pn->name() != QLatin1String(
"index.html")))
1469 generateTableOfContents(pn, marker,
nullptr);
1471 generateTitle(fullTitle, Text() << pn->subtitle(), subTitleSize, pn, marker);
1473 generateBrief(pn, marker,
nullptr,
false);
1476 generateExtractionMark(pn, DetailedDescriptionMark);
1477 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1481 out() <<
"</div>\n";
1482 generateAlsoList(pn, marker);
1483 generateExtractionMark(pn, EndMark);
1489
1490
1493 SubTitleSize subTitleSize = LargeSubTitle;
1494 QString fullTitle = cn->fullTitle();
1497 generateHeader(fullTitle, cn, marker);
1498 generateTableOfContents(cn, marker,
nullptr);
1499 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1504 generateBrief(cn, marker);
1512 if (!nmm.isEmpty()) {
1513 ref = registerRef(
"namespaces");
1514 out() <<
"<h2 id=\"" << ref <<
"\">Namespaces</h2>\n";
1515 generateAnnotatedList(cn, marker, nmm.values());
1518 if (!nmm.isEmpty()) {
1519 ref = registerRef(
"classes");
1520 out() <<
"<h2 id=\"" << ref <<
"\">Classes</h2>\n";
1521 generateAnnotatedList(cn, marker, nmm.values());
1527 generateExtractionMark(cn, DetailedDescriptionMark);
1528 ref = registerRef(
"details");
1529 out() <<
"<div class=\"descr\">\n";
1530 out() <<
"<h2 id=\"" << ref <<
"\">"
1531 <<
"Detailed Description"
1534 generateExtractionMark(cn, DetailedDescriptionMark);
1535 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1540 out() <<
"</div>\n";
1541 generateAlsoList(cn, marker);
1542 generateExtractionMark(cn, EndMark);
1545 if (cn->isGroup() || cn->isQmlModule())
1546 generateAnnotatedList(cn, marker, cn->members());
1552
1553
1554
1555
1558 SubTitleSize subTitleSize = LargeSubTitle;
1559 QString fullTitle = cn->name();
1561 generateHeader(fullTitle, cn, marker);
1562 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1565 brief <<
"Each function or type documented here is related to a class or "
1566 <<
"namespace that is documented in a different module. The reference "
1567 <<
"page for that class or namespace will link to the function or type "
1570 generateText(brief, cn, marker);
1573 const QList<Node *> members = cn->members();
1574 for (
const auto &member : members)
1575 generateDetailedMember(member, cn, marker);
1581
1582
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610void HtmlGenerator::generateNavigationBar(
const QString &title,
const Node *node,
1611 CodeMarker *marker,
const QString &buildversion,
1614 if (m_noNavigationBar || node ==
nullptr)
1625 auto addNavItem = [&](
const QString &link,
const QString &title) {
1626 navigationbar << Atom(itemLeft) << Atom(
Atom::NavLink, link)
1633 auto addNavItemNode = [&](
const Node *node,
const QString &title) {
1634 navigationbar << Atom(itemLeft) <<
Atom(
Atom::LinkNode, CodeMarker::stringForNode(node))
1642 QString moduleState;
1643 if (moduleNode && !moduleNode->state().isEmpty())
1644 moduleState = QStringLiteral(
" (%1)").arg(moduleNode->state());
1646 if (m_hometitle == title)
1648 if (!m_homepage.isEmpty())
1649 addNavItem(m_homepage, m_hometitle);
1650 if (!m_landingpage.isEmpty() && m_landingtitle != title)
1651 addNavItem(m_landingpage, m_landingtitle);
1654 if (!m_cppclassespage.isEmpty() && !m_cppclassestitle.isEmpty())
1655 addNavItem(m_cppclassespage, m_cppclassestitle);
1656 if (!node->physicalModuleName().isEmpty()) {
1660 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_cppclassespage))
1661 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1663 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1665 if (!m_qmltypespage.isEmpty() && !m_qmltypestitle.isEmpty())
1666 addNavItem(m_qmltypespage, m_qmltypestitle);
1670 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_qmltypespage)) {
1671 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1673 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1676 auto currentNode{
static_cast<
const PageNode*>(node)};
1677 std::deque<
const Node *> navNodes;
1679 qsizetype navItems = 0;
1681 if (
std::find(navNodes.cbegin(), navNodes.cend(),
1688 if (navNodes.empty()) {
1689 const QStringList groups =
static_cast<
const PageNode *>(node)->groupNames();
1690 for (
const auto &groupName : groups) {
1691 const auto *groupNode = m_qdb->findNodeByNameAndType(QStringList{groupName}, &Node::isGroup);
1692 if (groupNode && !groupNode->title().isEmpty()) {
1693 navNodes.push_front(groupNode);
1698 while (!navNodes.empty()) {
1699 if (navNodes.front()->isPageNode())
1700 addNavItemNode(navNodes.front(), navNodes.front()->title());
1701 navNodes.pop_front();
1705 navigationbar << Atom(itemLeft) << Atom(
Atom::String, title) << Atom(itemRight);
1709 generateText(navigationbar, node, marker);
1711 if (buildversion.isEmpty())
1717 out() <<
"</tr></table><table class=\"buildversion\"><tr>\n"
1718 << R"(<td id="buildversion" width="100%" align="right">)";
1720 out() <<
"<li id=\"buildversion\">";
1724 if (!m_landingpage.isEmpty() && m_landingtitle != title) {
1725 navigationbar << Atom(Atom::NavLink, m_landingpage)
1727 << Atom(Atom::String, buildversion)
1729 generateText(navigationbar, node, marker);
1731 out() << buildversion;
1741 out() <<
"<!DOCTYPE html>\n";
1742 out() << QString(
"<html lang=\"%1\">\n").arg(naturalLanguage);
1743 out() <<
"<head>\n";
1744 out() <<
" <meta charset=\"utf-8\">\n";
1745 if (node && !node->doc().location().isEmpty())
1746 out() <<
"<!-- " << node->doc().location().fileName() <<
" -->\n";
1749 out() <<
" <meta name=\"description\" content=\""
1750 << protectEnc(node->doc().briefText().toString())
1755 QString titleSuffix;
1756 if (!m_landingtitle.isEmpty()) {
1758 titleSuffix = m_landingtitle;
1759 }
else if (!m_hometitle.isEmpty()) {
1762 if (title != m_hometitle)
1763 titleSuffix = m_hometitle;
1766 titleSuffix = m_productName.isEmpty() ? m_project : m_productName;
1768 if (title == titleSuffix)
1769 titleSuffix.clear();
1771 out() <<
" <title>";
1772 if (!titleSuffix.isEmpty() && !title.isEmpty()) {
1773 out() <<
"%1 | %2"_L1.arg(protectEnc(title), titleSuffix);
1775 out() << protectEnc(title);
1780 QVersionNumber projectVersion = QVersionNumber::fromString(m_qdb->version());
1781 if (!projectVersion.isNull()) {
1782 QVersionNumber titleVersion;
1783 static const QRegularExpression re(QLatin1String(R"(\d+\.\d+)"));
1784 const QString &versionedTitle = titleSuffix.isEmpty() ? title : titleSuffix;
1785 auto match = re.match(versionedTitle);
1786 if (match.hasMatch())
1787 titleVersion = QVersionNumber::fromString(match.captured());
1788 if (titleVersion.isNull() || !titleVersion.isPrefixOf(projectVersion)) {
1790 if (!m_productName.isEmpty() && titleSuffix != m_productName)
1791 out() <<
" | %1"_L1.arg(m_productName);
1792 out() <<
" %1"_L1.arg(projectVersion.toString());
1795 out() <<
"</title>\n";
1798 out() << m_headerStyles;
1799 out() << m_headerScripts;
1800 if (m_endHeader.isEmpty())
1801 out() <<
"</head>\n<body>\n";
1803 out() << m_endHeader;
1805 out() << QString(m_postHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1806 bool usingTable = m_postHeader.trimmed().endsWith(QLatin1String(
"<tr>"));
1807 generateNavigationBar(title, node, marker, m_buildversion, usingTable);
1808 out() << QString(m_postPostHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1810 m_navigationLinks.clear();
1813 if (node && !node->links().empty()) {
1814 std::pair<QString, QString> linkPair;
1815 std::pair<QString, QString> anchorPair;
1816 const Node *linkNode;
1817 bool useSeparator =
false;
1819 if (node->links().contains(Node::PreviousLink)) {
1820 linkPair = node->links()[Node::PreviousLink];
1821 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1824 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1825 if (linkNode ==
nullptr || linkNode == node)
1826 anchorPair = linkPair;
1828 anchorPair = anchorForNode(linkNode);
1830 out() << R"( <link rel="prev" href=")" << anchorPair.first <<
"\" />\n";
1832 m_navigationLinks += R"(<a class="prevPage" href=")" + anchorPair.first +
"\">";
1833 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1834 m_navigationLinks += protect(anchorPair.second);
1836 m_navigationLinks += protect(linkPair.second);
1837 m_navigationLinks +=
"</a>\n";
1838 useSeparator = !m_navigationSeparator.isEmpty();
1840 if (node->links().contains(Node::NextLink)) {
1841 linkPair = node->links()[Node::NextLink];
1842 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1845 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1846 if (linkNode ==
nullptr || linkNode == node)
1847 anchorPair = linkPair;
1849 anchorPair = anchorForNode(linkNode);
1851 out() << R"( <link rel="next" href=")" << anchorPair.first <<
"\" />\n";
1854 m_navigationLinks += m_navigationSeparator;
1856 m_navigationLinks += R"(<a class="nextPage" href=")" + anchorPair.first +
"\">";
1857 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1858 m_navigationLinks += protect(anchorPair.second);
1860 m_navigationLinks += protect(linkPair.second);
1861 m_navigationLinks +=
"</a>\n";
1863 if (node->links().contains(Node::StartLink)) {
1864 linkPair = node->links()[Node::StartLink];
1865 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1868 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1869 if (linkNode ==
nullptr || linkNode == node)
1870 anchorPair = linkPair;
1872 anchorPair = anchorForNode(linkNode);
1873 out() << R"( <link rel="start" href=")" << anchorPair.first <<
"\" />\n";
1877 if (node && !node->links().empty())
1878 out() <<
"<p class=\"naviNextPrevious headerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1882 SubTitleSize subTitleSize,
const Node *relative,
1885 out() << QString(m_prologue).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1888 attribute = R"( translate="no")";
1890 if (!title.isEmpty())
1891 out() <<
"<h1 class=\"title\"" << attribute <<
">" << protectEnc(title) <<
"</h1>\n";
1894 if (subTitleSize == SmallSubTitle)
1895 out() <<
" class=\"small-subtitle\"" << attribute <<
">";
1897 out() <<
" class=\"subtitle\"" << attribute <<
">";
1898 generateText(subtitle, relative, marker);
1899 out() <<
"</span>\n";
1905 if (node && !node->links().empty())
1906 out() <<
"<p class=\"naviNextPrevious footerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1908 out() << QString(m_footer).replace(
"\\" +
COMMAND_VERSION, m_qdb->version())
1909 << QString(m_address).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1911 out() <<
"</body>\n";
1912 out() <<
"</html>\n";
1916
1917
1918
1921 QMap<QString, Text> requisites;
1924 const QString headerText =
"Header";
1925 const QString sinceText =
"Since";
1926 const QString inheritedBytext =
"Inherited By";
1927 const QString inheritsText =
"Inherits";
1928 const QString nativeTypeText =
"In QML";
1929 const QString qtVariableText =
"qmake";
1930 const QString cmakeText =
"CMake";
1931 const QString statusText =
"Status";
1934 const QStringList requisiteorder { headerText, cmakeText, qtVariableText, sinceText,
1935 nativeTypeText, inheritsText, inheritedBytext, statusText };
1937 addIncludeFileToMap(aggregate, requisites, text, headerText);
1938 addSinceToMap(aggregate, requisites, &text, sinceText);
1941 addCMakeInfoToMap(aggregate, requisites, &text, cmakeText);
1942 addQtVariableToMap(aggregate, requisites, &text, qtVariableText);
1946 auto *classe =
dynamic_cast<
ClassNode *>(aggregate);
1947 if (classe->isQmlNativeType() && !classe->isInternal())
1948 addQmlNativeTypesToMap(requisites, &text, nativeTypeText, classe);
1950 addInheritsToMap(requisites, &text, inheritsText, classe);
1951 addInheritedByToMap(requisites, &text, inheritedBytext, classe);
1955 addStatusToMap(aggregate, requisites, text, statusText);
1957 if (!requisites.isEmpty()) {
1959 generateTheTable(requisiteorder, requisites, aggregate, marker);
1964
1965
1966void HtmlGenerator::generateTheTable(
const QStringList &requisiteOrder,
1967 const QMap<QString, Text> &requisites,
1970 out() <<
"<div class=\"table\"><table class=\"alignedsummary requisites\" translate=\"no\">\n";
1972 for (
auto it = requisiteOrder.constBegin(); it != requisiteOrder.constEnd(); ++it) {
1974 if (requisites.contains(*it)) {
1976 <<
"<td class=\"memItemLeft rightAlign topAlign\"> " << *it
1978 "</td><td class=\"memItemRight bottomAlign\"> ";
1980 generateText(requisites.value(*it), aggregate, marker);
1981 out() <<
"</td></tr>\n";
1984 out() <<
"</table></div>\n";
1988
1989
1990
1991void HtmlGenerator::addInheritedByToMap(QMap<QString, Text> &requisites,
Text *text,
1992 const QString &inheritedBytext,
ClassNode *classe)
1994 if (!classe->derivedClasses().isEmpty()) {
1997 int count = appendSortedNames(*text, classe, classe->derivedClasses());
2000 requisites.insert(inheritedBytext, *text);
2005
2006
2007
2008void HtmlGenerator::addInheritsToMap(QMap<QString, Text> &requisites,
Text *text,
2009 const QString &inheritsText,
ClassNode *classe)
2011 if (!classe->baseClasses().isEmpty()) {
2014 const auto baseClasses = classe->baseClasses();
2015 for (
const auto &cls : baseClasses) {
2017 appendFullName(*text, cls.m_node, classe);
2019 if (cls.m_access == Access::Protected) {
2020 *text <<
" (protected)";
2021 }
else if (cls.m_access == Access::Private) {
2022 *text <<
" (private)";
2024 *text << Utilities::comma(index++, classe->baseClasses().size());
2029 requisites.insert(inheritsText, *text);
2034
2035
2036
2037 void HtmlGenerator::addQmlNativeTypesToMap(QMap<QString, Text> &requisites,
Text *text,
2038 const QString &nativeTypeText,
ClassNode *classe)
const
2045 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2047 qsizetype index { 0 };
2049 for (
const auto &item : std::as_const(nativeTypes)) {
2050 *text << Atom(Atom::LinkNode, CodeMarker::stringForNode(item))
2052 << Atom(Atom::String, item->name())
2054 *text << Utilities::comma(index++, nativeTypes.size());
2056 requisites.insert(nativeTypeText, *text);
2060
2061
2062
2064 Text *text,
const QString &CMakeInfo)
const
2066 if (!aggregate->physicalModuleName().isEmpty() && text !=
nullptr) {
2070 const auto result = cmakeRequisite(cn);
2083 requisites.insert(CMakeInfo, *text);
2088
2089
2090
2092 Text *text,
const QString &qtVariableText)
const
2094 if (!aggregate->physicalModuleName().isEmpty()) {
2098 if (cn && !cn->qtVariable().isEmpty()) {
2101 requisites.insert(qtVariableText, *text);
2107
2108
2109
2110
2112 Text *text,
const QString &sinceText)
const
2114 if (!aggregate->since().isEmpty() && text !=
nullptr) {
2117 requisites.insert(sinceText, *text);
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2133 Text &text,
const QString &statusText)
const
2135 auto status{formatStatus(aggregate, m_qdb)};
2141 spanClass = u"deprecated"_s;
2143 spanClass = Utilities::asAsciiPrintable(status.value());
2146 text << Atom(Atom::String, status.value())
2148 "class=\"status %1\""_L1.arg(spanClass))
2150 requisites.insert(statusText, text);
2154
2155
2156
2157
2159 QMap<QString, Text> &requisites,
Text& text,
2160 const QString &headerText)
2162 if (aggregate->includeFile()) {
2164 text << openCodeTag <<
"#include <%1>"_L1.arg(*aggregate->includeFile()) << closeCodeTag;
2165 requisites.insert(headerText, text);
2170
2171
2172
2177 QMap<QString, Text> requisites;
2180 const QString importText =
"Import Statement";
2181 const QString sinceText =
"Since";
2182 const QString inheritedBytext =
"Inherited By";
2183 const QString inheritsText =
"Inherits";
2184 const QString nativeTypeText =
"In C++";
2185 const QString statusText =
"Status";
2188 QString logicalModuleVersion;
2193 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2196 requisites.insert(importText, text);
2198 qcn
->doc().location().warning(QStringLiteral(
"Could not resolve QML import statement for type '%1'").arg(qcn->name()),
2203 if (!qcn->since().isEmpty()) {
2206 requisites.insert(sinceText, text);
2217 requisites.insert(nativeTypeText, text);
2230 requisites.insert(inheritsText, text);
2236 if (!subs.isEmpty()) {
2242 requisites.insert(inheritedBytext, text);
2246 addStatusToMap(qcn, requisites, text, statusText);
2249 const QStringList requisiteorder { importText, sinceText, nativeTypeText, inheritsText,
2250 inheritedBytext, statusText };
2252 if (!requisites.isEmpty())
2253 generateTheTable(requisiteorder, requisites, qcn, marker);
2265 QStringLiteral(
"'\\brief' statement does not end with a full stop."));
2267 generateExtractionMark(node, BriefMark);
2269 generateText(brief, node, marker);
2272 if (!relative || node == relative)
2273 out() <<
" <a href=\"#";
2275 out() <<
" <a href=\"" << linkForNode(node, relative) <<
'#';
2276 out() << registerRef(
"details") <<
"\">More...</a>";
2280 generateExtractionMark(node, EndMark);
2285
2286
2287
2289 QList<Section> *sections)
2293 toc = node
->doc().tableOfContents();
2294 if (tocDepth == 0 || (toc.isEmpty() && !sections && !node
->isModule())) {
2299 int sectionNumber = 1;
2300 int detailsBase = 0;
2305 out() <<
"<div class=\"sidebar\">\n";
2306 out() <<
"<div class=\"toc\">\n";
2307 out() <<
"<h3 id=\"toc\">Contents</h3>\n";
2310 openUnorderedList();
2313 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2314 << registerRef(
"namespaces") <<
"\">Namespaces</a></li>\n";
2317 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2318 << registerRef(
"classes") <<
"\">Classes</a></li>\n";
2321 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#" << registerRef(
"details")
2322 <<
"\">Detailed Description</a></li>\n";
2323 for (
const auto &entry : std::as_const(toc)) {
2324 if (entry->string().toInt() == 1) {
2330 for (
const auto §ion : std::as_const(*sections)) {
2331 if (!section.members().isEmpty()) {
2332 openUnorderedList();
2333 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2334 << registerRef(section.plural()) <<
"\">" << section.title() <<
"</a></li>\n";
2336 if (!section.reimplementedMembers().isEmpty()) {
2337 openUnorderedList();
2338 QString ref = QString(
"Reimplemented ") + section.plural();
2339 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2340 << registerRef(ref.toLower()) <<
"\">"
2341 << QString(
"Reimplemented ") + section.title() <<
"</a></li>\n";
2345 openUnorderedList();
2346 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2347 << registerRef(
"details") <<
"\">Detailed Description</a></li>\n";
2349 for (
const auto &entry : toc) {
2350 if (entry->string().toInt() == 1) {
2357 for (
const auto &atom : toc) {
2358 sectionNumber = atom->string().toInt() + detailsBase;
2361 if (sectionNumber <= tocDepth || tocDepth < 0) {
2362 openUnorderedList();
2364 Text headingText = Text::sectionHeading(atom);
2365 out() <<
"<li class=\"level" << sectionNumber <<
"\">";
2366 out() <<
"<a href=\"" <<
'#' << Tree::refForAtom(atom) <<
"\">";
2367 generateAtomList(headingText.firstAtom(), node, marker,
true, numAtoms);
2368 out() <<
"</a></li>\n";
2371 closeUnorderedList();
2372 out() <<
"</div>\n";
2373 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2374 out() <<
"</div>\n";
2380
2381
2384 out() <<
"<div class=\"sidebar\">";
2385 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2386 out() <<
"</div>\n";
2395 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2396 beginSubPage(aggregate, fileName);
2397 QString title =
"List of All Members for " + aggregate->plainFullName();
2398 generateHeader(title, aggregate, marker);
2400 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2401 out() <<
"<p>This is the complete list of members for ";
2402 generateFullName(aggregate,
nullptr);
2403 out() <<
", including inherited members.</p>\n";
2405 generateSectionList(section, aggregate, marker);
2413
2414
2415
2416
2417
2425 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2426 beginSubPage(aggregate, fileName);
2427 QString title =
"List of All Members for " + aggregate->name();
2428 generateHeader(title, aggregate, marker);
2430 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2431 out() <<
"<p>This is the complete list of members for ";
2432 generateFullName(aggregate,
nullptr);
2433 out() <<
", including inherited members.</p>\n";
2436 for (
int i = 0; i < cknl.size(); i++) {
2440 if (nodes.isEmpty())
2443 out() <<
"<p>The following members are inherited from ";
2444 generateFullName(qcn,
nullptr);
2447 openUnorderedList();
2448 for (
int j = 0; j < nodes.size(); j++) {
2449 Node *node = nodes[j];
2455 std::function<
void(
Node *)> generate = [&](Node *n) {
2456 out() <<
"<li class=\"fn\" translate=\"no\">";
2457 generateQmlItem(n, aggregate, marker,
true);
2459 out() <<
" [default]";
2460 else if (n->isAttached())
2461 out() <<
" [attached]";
2463 if (n->isPropertyGroup()) {
2465 const QList<Node *> &collective =
2466 static_cast<SharedCommentNode *>(n)->collective();
2467 std::for_each(collective.begin(), collective.end(), generate);
2474 closeUnorderedList();
2491 QString title =
"Obsolete Members for " + aggregate->plainFullName();
2492 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2494 beginSubPage(aggregate, fileName);
2495 generateHeader(title, aggregate, marker);
2497 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2499 out() <<
"<p><b>The following members of class "
2500 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\" translate=\"no\">"
2501 << protectEnc(aggregate->name()) <<
"</a>"
2502 <<
" are deprecated.</b> "
2503 <<
"They are provided to keep old source code working. "
2504 <<
"We strongly advise against using them in new code.</p>\n";
2506 for (
const auto §ion : summary_spv) {
2507 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2508 generateSectionList(*section, aggregate, marker,
true);
2511 for (
const auto §ion : details_spv) {
2512 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2514 const NodeVector &members = section->obsoleteMembers();
2515 for (
const auto &member : members) {
2516 if (member->access() != Access::Private)
2517 generateDetailedMember(member, aggregate, marker);
2527
2528
2529
2530
2539 QString title =
"Obsolete Members for " + aggregate->name();
2540 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2542 beginSubPage(aggregate, fileName);
2543 generateHeader(title, aggregate, marker);
2545 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2547 out() <<
"<p><b>The following members of QML type "
2548 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\">"
2549 << protectEnc(aggregate->name()) <<
"</a>"
2550 <<
" are deprecated.</b> "
2551 <<
"They are provided to keep old source code working. "
2552 <<
"We strongly advise against using them in new code.</p>\n";
2554 for (
const auto §ion : summary_spv) {
2555 QString ref = registerRef(section->title().toLower());
2556 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section->title()) <<
"</h2>\n";
2557 generateQmlSummary(section->obsoleteMembers(), aggregate, marker);
2560 for (
const auto §ion : details_spv) {
2561 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2562 const NodeVector &members = section->obsoleteMembers();
2563 for (
const auto &member : members) {
2564 generateDetailedQmlMember(member, aggregate, marker);
2576 if (classMap.isEmpty())
2580 for (
const auto &it : classMap) {
2581 auto *classe =
static_cast<ClassNode *>(it);
2582 if (classe->baseClasses().isEmpty())
2583 topLevel.insert(classe->name(), classe);
2586 QStack<NodeMap> stack;
2587 stack.push(topLevel);
2590 while (!stack.isEmpty()) {
2591 if (stack.top().isEmpty()) {
2597 generateFullName(child, relative);
2599 stack.top().erase(stack.top().begin());
2602 const auto derivedClasses = child->derivedClasses();
2603 for (
const RelatedClass &d : derivedClasses) {
2604 if (d.m_node && d.m_node->isInAPI())
2605 newTop.insert(d.m_node->name(), d.m_node);
2607 if (!newTop.isEmpty()) {
2616
2617
2618
2620 const NodeList &unsortedNodes, Qt::SortOrder sortOrder)
2622 if (unsortedNodes.isEmpty() || relative ==
nullptr)
2626 bool allInternal =
true;
2627 for (
auto *node : unsortedNodes) {
2628 if (!node->isInternal() && !node->isDeprecated()) {
2629 allInternal =
false;
2630 nmm.insert(node->fullName(relative), node);
2635 out() <<
"<div class=\"table\"><table class=\"annotated\">\n";
2639 if (sortOrder == Qt::DescendingOrder)
2644 for (
const auto *node : std::as_const(nodes)) {
2646 out() <<
"<tr class=\"odd topAlign\">";
2648 out() <<
"<tr class=\"even topAlign\">";
2649 out() <<
"<td class=\"tblName\" translate=\"no\"><p>";
2650 generateFullName(node, relative);
2651 out() <<
"</p></td>";
2653 if (!node->isTextPageNode()) {
2654 Text brief = node->doc().trimmedBriefText(node->name());
2655 if (!brief.isEmpty()) {
2656 out() <<
"<td class=\"tblDescr\"><p>";
2657 generateText(brief, node, marker);
2658 out() <<
"</p></td>";
2659 }
else if (!node->reconstitutedBrief().isEmpty()) {
2660 out() <<
"<td class=\"tblDescr\"><p>";
2661 out() << node->reconstitutedBrief();
2662 out() <<
"</p></td>";
2665 out() <<
"<td class=\"tblDescr\"><p>";
2666 if (!node->reconstitutedBrief().isEmpty()) {
2667 out() << node->reconstitutedBrief();
2669 out() << protectEnc(node->doc().briefText().toString());
2670 out() <<
"</p></td>";
2674 out() <<
"</table></div>\n";
2678
2679
2680
2684 const auto &uniqueKeys = nmm.uniqueKeys();
2685 for (
const QString &name : uniqueKeys) {
2686 if (!name.isEmpty()) {
2687 out() <<
"<h2 id=\"" << registerRef(name.toLower()) <<
"\">" << protectEnc(name)
2690 generateAnnotatedList(relative, marker, nmm.values(name));
2695
2696
2697
2698
2699
2700
2701
2702
2703
2706 const QString &commonPrefix)
2711 const int NumParagraphs = 37;
2712 qsizetype commonPrefixLen = commonPrefix.size();
2715
2716
2717
2718
2719
2721 QString paragraphName[NumParagraphs + 1];
2722 QSet<
char> usedParagraphNames;
2724 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
2725 QStringList pieces = c.key().split(
"::");
2726 int idx = commonPrefixLen;
2727 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
2729 QString last = pieces.last().toLower();
2730 QString key = last.mid(idx);
2732 int paragraphNr = NumParagraphs - 1;
2734 if (key[0].digitValue() != -1) {
2735 paragraphNr = key[0].digitValue();
2736 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
2737 paragraphNr = 10 + key[0].unicode() -
'a';
2740 paragraphName[paragraphNr] = key[0].toUpper();
2741 usedParagraphNames.insert(key[0].toLower().cell());
2742 paragraph[paragraphNr].insert(last, c.value());
2746
2747
2748
2749
2750
2751
2752
2753 qsizetype paragraphOffset[NumParagraphs + 1];
2754 paragraphOffset[0] = 0;
2755 for (
int i = 0; i < NumParagraphs; i++)
2756 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
2759
2760
2761 if (includeAlphabet) {
2762 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2763 for (
int i = 0; i < 26; i++) {
2765 if (usedParagraphNames.contains(
char(
'a' + i)))
2766 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2768 out() <<
"</b></p>\n";
2772
2773
2774 out() <<
"<div class=\"flowListDiv\" translate=\"no\">\n";
2778 int curParOffset = 0;
2779 QString previousName;
2780 bool multipleOccurrences =
false;
2782 for (
int i = 0; i < nmm.size(); i++) {
2783 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
2789
2790
2791 if (curParOffset == 0) {
2794 if (++m_numTableRows % 2 == 1)
2795 out() <<
"<dl class=\"flowList odd\">";
2797 out() <<
"<dl class=\"flowList even\">";
2798 out() <<
"<dt class=\"alphaChar\"";
2799 if (includeAlphabet)
2800 out() << QString(
" id=\"%1\"").arg(paragraphName[curParNr][0].toLower());
2801 out() <<
"><b>" << paragraphName[curParNr] <<
"</b></dt>\n";
2805
2806
2808 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
2809 NodeMultiMap::Iterator it;
2810 NodeMultiMap::Iterator next;
2811 it = paragraph[curParNr].begin();
2812 for (
int j = 0; j < curParOffset; j++)
2817
2818
2819
2820 out() <<
"<a href=\"" << linkForNode(it.value(), relative) <<
"\">";
2822 QString fileName = fileBase(it.value()) +
"-obsolete." + fileExtension();
2824 if (useOutputSubdirs())
2825 link =
"../%1/"_L1.arg(it.value()->tree()->physicalModuleName());
2827 out() <<
"<a href=\"" << link <<
"\">";
2830 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
2831 const auto &name{pieces.last()};
2834 if (name != previousName)
2835 multipleOccurrences =
false;
2836 if ((next != paragraph[curParNr].end()) && (name == next.value()->name())) {
2837 multipleOccurrences =
true;
2838 previousName = name;
2840 if (multipleOccurrences && pieces.size() == 1)
2841 pieces.last().append(
": %1"_L1.arg(it.value()->tree()->camelCaseModuleName()));
2843 out() << protectEnc(pieces.last());
2845 if (pieces.size() > 1) {
2847 generateFullName(it.value()->parent(), relative);
2857 out() <<
"</div>\n";
2862 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2863 for (
int i = 0; i < 26; i++) {
2865 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2867 out() <<
"</b></p>\n";
2869 char nextLetter =
'a';
2871 out() <<
"<ul translate=\"no\">\n";
2873 for (
auto fnMap = funcIndex.constBegin(); fnMap != funcIndex.constEnd(); ++fnMap) {
2874 const QString &key = fnMap.key();
2875 const QChar firstLetter = key.isEmpty() ? QChar(
'A') : key.front();
2876 Q_ASSERT_X(firstLetter.unicode() < 256,
"generateFunctionIndex",
2877 "Only valid C++ identifiers were expected");
2878 const char currentLetter = firstLetter.isLower() ? firstLetter.unicode() : nextLetter - 1;
2880 if (currentLetter < nextLetter) {
2884 while (nextLetter < currentLetter)
2885 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2886 Q_ASSERT(nextLetter == currentLetter);
2887 out() << QStringLiteral(
"<li id=\"%1\">").arg(nextLetter++);
2889 out() << protectEnc(key) <<
':';
2891 for (
auto it = (*fnMap).constBegin(); it != (*fnMap).constEnd(); ++it) {
2893 generateFullName((*it)->parent(), relative, *it);
2897 while (nextLetter <=
'z')
2898 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2905 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
2906 Text text = it.key();
2907 generateText(text, relative, marker);
2911 generateFullName(it.value(), relative);
2914 }
while (it != legaleseTexts.constEnd() && it.key() == text);
2922 QString marked = marker->markedUpQmlItem(node, summary);
2923 marked.replace(
"@param>",
"i>");
2925 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
2926 .arg(summary ?
"summary"_L1 :
"details"_L1));
2927 marked.replace(
"</@extra>",
"</code>");
2931 marked.remove(
"<@name>");
2932 marked.remove(
"</@name>");
2933 marked.remove(
"<@type>");
2934 marked.remove(
"</@type>");
2936 out() << highlightedCode(marked, relative,
false, Node::QML);
2940
2941
2942
2943
2944
2945
2946
2954 if (sortOrder == Qt::DescendingOrder)
2959 for (
const auto *node : std::as_const(members)) {
2960 out() <<
"<li translate=\"no\">";
2961 generateFullName(node,
nullptr);
2969 const QString &selector, Qt::SortOrder sortOrder)
2973 if (selector == QLatin1String(
"overviews"))
2975 else if (selector == QLatin1String(
"cpp-modules"))
2977 else if (selector == QLatin1String(
"qml-modules"))
2982 const auto collectionList = cnm.values();
2983 nodeList.reserve(collectionList.size());
2984 for (
auto *collectionNode : collectionList)
2985 nodeList.append(collectionNode);
2986 generateAnnotatedList(relative, marker, nodeList, sortOrder);
2989
2990
2991
2992
2995 QStringLiteral(
"\\generatelist {%1} is only allowed in \\group, "
2996 "\\module and \\qmlmodule comments.")
3000 auto *node =
const_cast<
Node *>(relative);
3003 generateAnnotatedList(collectionNode, marker, collectionNode->members(), sortOrder);
3009 bool alignNames =
true;
3010 if (!nv.isEmpty()) {
3011 bool twoColumn =
false;
3012 if (nv.first()->isProperty()) {
3013 twoColumn = (nv.size() >= 5);
3017 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3020 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3021 <<
"<tr><td class=\"topAlign\">";
3026 for (
const auto &member : nv) {
3027 if (member->access() == Access::Private)
3031 out() <<
"<tr><td class=\"memItemLeft rightAlign topAlign\"> ";
3033 if (twoColumn && i == (nv.size() + 1) / 2)
3034 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3035 out() <<
"<li class=\"fn\" translate=\"no\">";
3038 generateSynopsis(member, relative, marker, Section::Summary, alignNames);
3040 out() <<
"</td></tr>\n";
3046 out() <<
"</table></div>\n";
3050 out() <<
"</td></tr>\n</table></div>\n";
3058 bool alignNames =
true;
3061 if (!members.isEmpty()) {
3062 bool hasPrivateSignals =
false;
3063 bool isInvokable =
false;
3064 bool twoColumn =
false;
3067 twoColumn = (members.size() >= 16);
3068 }
else if (members.first()->isProperty()) {
3069 twoColumn = (members.size() >= 5);
3073 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3076 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3077 <<
"<tr><td class=\"topAlign\">";
3082 for (
const auto &member : members) {
3083 if (member->access() == Access::Private)
3087 out() <<
"<tr><td class=\"memItemLeft topAlign rightAlign\"> ";
3089 if (twoColumn && i == (members.size() + 1) / 2)
3090 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3091 out() <<
"<li class=\"fn\" translate=\"no\">";
3094 generateSynopsis(member, relative, marker, section.style(), alignNames);
3095 if (member->isFunction()) {
3096 const auto *fn =
static_cast<
const FunctionNode *>(member);
3097 if (fn->isPrivateSignal()) {
3098 hasPrivateSignals =
true;
3100 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3101 }
else if (fn->isInvokable()) {
3104 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3108 out() <<
"</td></tr>\n";
3114 out() <<
"</table></div>\n";
3118 out() <<
"</td></tr>\n</table></div>\n";
3121 if (hasPrivateSignals)
3129 && !section.inheritedMembers().isEmpty()) {
3131 generateSectionInheritedList(section, relative);
3138 const QList<std::pair<Aggregate *,
int>> &inheritedMembers = section.inheritedMembers();
3139 for (
const auto &member : inheritedMembers) {
3140 out() <<
"<li class=\"fn\" translate=\"no\">";
3141 out() << member.second <<
' ';
3142 if (member.second == 1) {
3143 out() << section.singular();
3145 out() << section.plural();
3147 out() <<
" inherited from <a href=\"" << fileName(member.first) <<
'#'
3148 << Generator::cleanRef(section.title().toLower()) <<
"\">"
3149 << protectEnc(member.first->plainFullName(relative)) <<
"</a></li>\n";
3156 QString marked = marker->markedUpSynopsis(node, relative, style);
3157 marked.replace(
"@param>",
"i>");
3160 marked.remove(
"<@name>");
3161 marked.remove(
"</@name>");
3165 static const QRegularExpression extraRegExp(
"<@extra>.*</@extra>",
3166 QRegularExpression::InvertedGreedinessOption);
3167 marked.remove(extraRegExp);
3169 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
3170 .arg(style == Section::Summary ?
"summary"_L1 :
"details"_L1));
3171 marked.replace(
"</@extra>",
"</code>");
3175 marked.remove(
"<@type>");
3176 marked.remove(
"</@type>");
3179 out() << highlightedCode(marked, relative, alignNames);
3182QString
HtmlGenerator::highlightedCode(
const QString &markedCode,
const Node *relative,
3185 QString src = markedCode;
3187 html.reserve(src.size());
3191 const QChar charLangle =
'<';
3192 const QChar charAt =
'@';
3194 static const QString typeTag(
"type");
3195 static const QString headerTag(
"headerfile");
3196 static const QString funcTag(
"func");
3197 static const QString linkTag(
"link");
3203 for (
int i = 0, srcSize = src.size(); i < srcSize;) {
3204 if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
3205 if (alignNames && !done) {
3206 html += QLatin1String(
"</td><td class=\"memItemRight bottomAlign\">");
3210 if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) {
3211 html += QLatin1String(
"<b>");
3212 const Node *n = CodeMarker::nodeForString(par1.toString());
3213 QString link = linkForNode(n, relative);
3214 addLink(link, arg, &html);
3215 html += QLatin1String(
"</b>");
3216 }
else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
3217 const FunctionNode *fn =
m_qdb->findFunctionNode(par1.toString(), relative, genus);
3218 QString link = linkForNode(fn, relative);
3219 addLink(link, arg, &html);
3220 par1 = QStringView();
3221 }
else if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
3222 par1 = QStringView();
3223 const Node *n =
m_qdb->findTypeNode(arg.toString(), relative, genus);
3224 html += QLatin1String(
"<span class=\"type\">");
3227 addLink(linkForNode(n, relative), arg, &html);
3231 addLink(linkForNode(n, relative), arg, &html);
3232 html += QLatin1String(
"</span>");
3233 }
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
3234 par1 = QStringView();
3235 if (arg.startsWith(QLatin1Char(
'&')))
3238 const Node *n =
m_qdb->findNodeForInclude(QStringList(arg.toString()));
3239 if (n && n != relative)
3240 addLink(linkForNode(n, relative), arg, &html);
3249 html += src.at(i++);
3266 html.reserve(src.size());
3267 static const QLatin1String spanTags[] = {
3268 QLatin1String(
"comment>"), QLatin1String(
"<span class=\"comment\">"),
3269 QLatin1String(
"preprocessor>"), QLatin1String(
"<span class=\"preprocessor\">"),
3270 QLatin1String(
"string>"), QLatin1String(
"<span class=\"string\">"),
3271 QLatin1String(
"char>"), QLatin1String(
"<span class=\"char\">"),
3272 QLatin1String(
"number>"), QLatin1String(
"<span class=\"number\">"),
3273 QLatin1String(
"op>"), QLatin1String(
"<span class=\"operator\">"),
3274 QLatin1String(
"type>"), QLatin1String(
"<span class=\"type\">"),
3275 QLatin1String(
"name>"), QLatin1String(
"<span class=\"name\">"),
3276 QLatin1String(
"keyword>"), QLatin1String(
"<span class=\"keyword\">")
3281 for (
int i = 0, n = src.size(); i < n;) {
3282 if (src.at(i) == QLatin1Char(
'<')) {
3283 if (src.at(i + 1) == QLatin1Char(
'@')) {
3285 bool handled =
false;
3286 for (
int k = 0; k != nTags; ++k) {
3287 const QLatin1String &tag = spanTags[2 * k];
3288 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3289 html += spanTags[2 * k + 1];
3297 while (i < n && src.at(i) != QLatin1Char(
'>'))
3302 }
else if (src.at(i + 1) == QLatin1Char(
'/') && src.at(i + 2) == QLatin1Char(
'@')) {
3304 bool handled =
false;
3305 for (
int k = 0; k != nTags; ++k) {
3306 const QLatin1String &tag = spanTags[2 * k];
3307 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3308 html += QLatin1String(
"</span>");
3316 while (i < n && src.at(i) != QLatin1Char(
'>'))
3335 if (match.hasMatch()) {
3337 qsizetype leftParenLoc = match.capturedStart(1);
3338 out() << protectEnc(atom->string().left(leftParenLoc));
3340 out() << protectEnc(atom->string().mid(leftParenLoc));
3344 out() << protectEnc(atom->string());
3349 return protect(string);
3355 if (html.isEmpty()) {
3362 qsizetype n = string.size();
3364 for (
int i = 0; i < n; ++i) {
3365 QChar ch = string.at(i);
3367 if (ch == QLatin1Char(
'&')) {
3369 }
else if (ch == QLatin1Char(
'<')) {
3371 }
else if (ch == QLatin1Char(
'>')) {
3373 }
else if (ch == QChar(8211)) {
3375 }
else if (ch == QChar(8212)) {
3377 }
else if (ch == QLatin1Char(
'"')) {
3380 if (!html.isEmpty())
3385 if (!html.isEmpty())
3394 QString result = Generator::fileBase(node);
3396 result += QLatin1String(
"-obsolete");
3403 return node->name();
3404 return Generator::fileName(node);
3408 const Node *actualNode)
3410 if (actualNode ==
nullptr)
3411 actualNode = apparentNode;
3412 bool link = !linkForNode(actualNode, relative).isEmpty();
3414 out() <<
"<a href=\"" << linkForNode(actualNode, relative);
3415 if (actualNode->isDeprecated())
3416 out() <<
"\" class=\"obsolete";
3419 out() << protectEnc(apparentNode->fullName(relative));
3428 generateExtractionMark(node, MemberMark);
3429 QString nodeRef =
nullptr;
3432 const QList<Node *> &collective = scn->collective();
3433 if (collective.size() > 1)
3434 out() <<
"<div class=\"fngroup\">\n";
3435 for (
const auto *sharedNode : collective) {
3436 nodeRef = refForNode(sharedNode);
3437 out() << R"(<h3 class="fn fngroupitem" translate="no" id=")" << nodeRef <<
"\">";
3438 generateSynopsis(sharedNode, relative, marker, Section::Details);
3441 if (collective.size() > 1)
3445 nodeRef = refForNode(node);
3447 out() << R"(<h3 class="flags" id=")" << nodeRef <<
"\">";
3453 out() << R"(<h3 class="fn" translate="no" id=")" << nodeRef <<
"\">";
3455 out() <<
"</h3>" <<
'\n';
3468 const auto property =
static_cast<
const PropertyNode *>(node);
3477 out() <<
"<p><b>Access functions:</b></p>\n";
3478 generateSectionList(section, node, marker);
3485 out() <<
"<p><b>Notifier signal:</b></p>\n";
3486 generateSectionList(notifiers, node, marker);
3490 const auto *enumTypeNode =
static_cast<
const EnumNode *>(node);
3492 out() <<
"<p>The " << protectEnc(enumTypeNode->flagsType()->name())
3493 <<
" type is a typedef for "
3494 <<
"<a href=\"" << m_qflagsHref <<
"\">QFlags</a><"
3495 << protectEnc(enumTypeNode->name()) <<
">. It stores an OR combination of "
3496 << protectEnc(enumTypeNode->name()) <<
" values.</p>\n";
3499 generateAlsoList(node, marker);
3500 generateExtractionMark(node, EndMark);
3504
3505
3506
3507
3514 if (!m_link.isEmpty())
3515 out() <<
"<a href=\"" << m_link <<
"\" translate=\"no\">";
3523 if (m_link.isEmpty())
3526 const QString &translate_attr =
3527 (node && node->genus() & Node::API) ?
" translate=\"no\""_L1 :
""_L1;
3529 if (node ==
nullptr || (relative !=
nullptr && node->status() == relative->status()))
3530 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3531 else if (node->isDeprecated())
3532 out() <<
"<a href=\"" << m_link <<
"\" class=\"obsolete\"%1>"_L1.arg(translate_attr);
3534 out() <<
"<a href=\"" << m_link <<
"\"%1>"_L1.arg(translate_attr);
3545 if (!m_link.isEmpty())
3550
3551
3552
3556 if (!members.isEmpty()) {
3558 for (
const auto &member : members) {
3559 out() <<
"<li class=\"fn\" translate=\"no\">";
3560 generateQmlItem(member, relative, marker,
true);
3561 if (member->isPropertyGroup()) {
3562 const auto *scn =
static_cast<
const SharedCommentNode *>(member);
3563 if (scn->count() > 0) {
3565 const QList<Node *> &sharedNodes = scn->collective();
3566 for (
const auto &node : sharedNodes) {
3567 if (node->isQmlProperty()) {
3568 out() <<
"<li class=\"fn\" translate=\"no\">";
3569 generateQmlItem(node, relative, marker,
true);
3583
3584
3585
3589 generateExtractionMark(node, MemberMark);
3591 QString qmlItemHeader(
"<div class=\"qmlproto\" translate=\"no\">\n"
3592 "<div class=\"table\"><table class=\"qmlname\">\n");
3594 QString qmlItemStart(
"<tr valign=\"top\" class=\"odd\" id=\"%1\">\n"
3595 "<td class=\"%2\"><p>\n");
3596 QString qmlItemEnd(
"</p></td></tr>\n");
3598 QString qmlItemFooter(
"</table></div></div>\n");
3600 auto generateQmlProperty = [&](
Node *n) {
3601 out() << qmlItemStart.arg(refForNode(n),
"tblQmlPropNode");
3602 generateQmlItem(n, relative, marker,
false);
3603 out() << qmlItemEnd;
3606 auto generateQmlMethod = [&](
Node *n) {
3607 out() << qmlItemStart.arg(refForNode(n),
"tblQmlFuncNode");
3609 out() << qmlItemEnd;
3612 out() <<
"<div class=\"qmlitem\">";
3615 out() << qmlItemHeader;
3616 if (!scn->name().isEmpty()) {
3617 const QString nodeRef = refForNode(scn);
3618 out() << R"(<tr valign="top" class="even" id=")" << nodeRef <<
"\">";
3619 out() <<
"<th class=\"centerAlign\"><p>";
3620 out() <<
"<b>" << scn->name() <<
" group</b>";
3621 out() <<
"</p></th></tr>\n";
3623 const QList<Node *> sharedNodes = scn->collective();
3624 for (
const auto &sharedNode : sharedNodes) {
3625 if (sharedNode->isQmlProperty())
3626 generateQmlProperty(sharedNode);
3628 out() << qmlItemFooter;
3630 out() << qmlItemHeader;
3631 generateQmlProperty(node);
3632 out() << qmlItemFooter;
3635 const QList<Node *> &sharedNodes = scn->collective();
3636 if (sharedNodes.size() > 1)
3637 out() <<
"<div class=\"fngroup\">\n";
3638 out() << qmlItemHeader;
3639 for (
const auto &sharedNode : sharedNodes) {
3641 if (sharedNode->isFunction(Node::QML))
3642 generateQmlMethod(sharedNode);
3643 else if (sharedNode->isQmlProperty())
3644 generateQmlProperty(sharedNode);
3646 out() << qmlItemFooter;
3647 if (sharedNodes.size() > 1)
3650 out() << qmlItemHeader;
3651 generateQmlMethod(node);
3652 out() << qmlItemFooter;
3655 out() <<
"<div class=\"qmldoc\">";
3660 generateAlsoList(node, marker);
3661 out() <<
"</div></div>";
3662 generateExtractionMark(node, EndMark);
3665void HtmlGenerator::generateExtractionMark(
const Node *node, ExtractionMarkType markType)
3667 if (markType != EndMark) {
3668 out() <<
"<!-- $$$" + node->name();
3669 if (markType == MemberMark) {
3671 const auto *func =
static_cast<
const FunctionNode *>(node);
3673 if (func->overloadNumber() == 0)
3674 out() <<
"[overload1]";
3675 out() <<
"$$$" + func->name() + func->parameters().rawSignature().remove(
' ');
3679 const auto *prop =
static_cast<
const PropertyNode *>(node);
3681 for (
const auto *propFuncNode : list) {
3682 if (propFuncNode->isFunction()) {
3683 const auto *func =
static_cast<
const FunctionNode *>(propFuncNode);
3684 out() <<
"$$$" + func->name()
3685 + func->parameters().rawSignature().remove(
' ');
3689 const auto *enumNode =
static_cast<
const EnumNode *>(node);
3690 const auto &items = enumNode->items();
3691 for (
const auto &item : items)
3692 out() <<
"$$$" + item.name();
3694 }
else if (markType == BriefMark) {
3696 }
else if (markType == DetailedDescriptionMark) {
3697 out() <<
"-description";
3701 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_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
Represents a file that is reachable by QDoc based on its current configuration.