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()));
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) <<
'"';
658 const QString altAndTitleText = protectEnc(text);
659 out() <<
" alt=\"" << altAndTitleText;
661 out() <<
"\" title=\"" << altAndTitleText;
665 m_helpProjectWriter->addExtraFile(
"images/" + file_name);
666 setImageFileName(relative,
"images/" + file_name);
669 if (atom->type() == Atom::Image)
678 QString admonType = atom->typeString();
681 out() <<
"<div class=\"admonition " << admonType.toLower() <<
"\">\n"
684 out() << admonType <<
": ";
687 case Atom::ImportantRight:
688 case Atom::NoteRight:
689 case Atom::WarningRight:
693 case Atom::LegaleseLeft:
694 out() <<
"<div class=\"LegaleseLeft\">";
696 case Atom::LegaleseRight:
699 case Atom::LineBreak:
708 const Node *node =
nullptr;
709 QString link = getLink(atom, relative, &node);
714 QStringLiteral(
"Can't link to '%1'").arg(atom->string()));
716 beginLink(link, node, relative);
720 QString link = linkForExampleFile(atom->string());
725 QString link = atom->string();
726 link =
"images/used-in-examples/" + link;
731 const Node *node = CodeMarker::nodeForString(atom->string());
732 beginLink(linkForNode(node, relative), node, relative);
745 out() << R"(<div class="table"><table class="valuelist">)";
748 if (++m_numTableRows % 2 == 1)
749 out() << R"(<tr valign="top" class="odd">)";
751 out() << R"(<tr valign="top" class="even">)";
753 out() <<
"<th class=\"tblConst\">Constant</th>";
756 if (relative->isEnumType())
757 out() <<
"<th class=\"tblval\">Value</th>";
759 out() <<
"<th class=\"tbldscr\">Description</th></tr>\n";
761 out() <<
"<tr><th class=\"tblConst\">Constant</th><th "
762 "class=\"tblVal\">Value</th></tr>\n";
779 out() << QString(R"(<ol class="%1" type="%1" start="%2">)")
780 .arg(olType, atom->next()->string());
782 out() << QString(R"(<ol class="%1" type="%1">)").arg(olType);
791 std::pair<QString,
int> pair = getAtomListValue(atom);
792 skipAhead = pair.second;
793 QString t = protectEnc(plainCode(marker->markedUpEnumValue(pair.first, relative)));
794 out() <<
"<tr><td class=\"topAlign\"><code translate=\"no\">" << t <<
"</code>";
797 out() <<
"</td><td class=\"topAlign tblval\">";
798 const auto *enume =
static_cast<
const EnumNode *>(relative);
799 QString itemValue = enume->itemValue(atom->next()->string());
800 if (itemValue.isEmpty())
803 out() <<
"<code translate=\"no\">" << protectEnc(itemValue) <<
"</code>";
807 case Atom::SinceTagRight:
808 case Atom::ListTagRight:
817 out() <<
"</td><td class=\"topAlign\">";
818 if (matchAhead(atom, Atom::ListItemRight))
824 if (matchAhead(atom, Atom::ParaLeft))
831 out() <<
"</td></tr>\n";
842 out() <<
"</table></div>\n";
862 case Atom::QuotationLeft:
863 out() <<
"<blockquote>";
865 case Atom::QuotationRight:
866 out() <<
"</blockquote>\n";
868 case Atom::RawString:
869 out() << atom->string();
875 int unit = atom->string().toInt() +
hOffset(relative
);
876 out() <<
"<h" + QString::number(unit) + QLatin1Char(
' ') <<
"id=\""
877 << Tree::refForAtom(atom) <<
"\">";
881 case Atom::SectionHeadingRight:
882 out() <<
"</h" + QString::number(atom->string().toInt() + hOffset(relative)) +
">\n";
893 out() << protectEnc(atom->string());
897 std::pair<QString, QString> pair = getTableWidthAttr(atom);
898 QString attr = pair.second;
899 QString width = pair.first;
906 out() << R"(<div class="table"><table class=")" << attr <<
'"';
907 if (!width.isEmpty())
908 out() <<
" width=\"" << width <<
'"';
912 case Atom::TableRight:
913 out() <<
"</table></div>\n";
915 case Atom::TableHeaderLeft:
916 out() <<
"<thead><tr class=\"qt-style\">";
919 case Atom::TableHeaderRight:
923 out() <<
"\n<tr class=\"qt-style\">";
925 out() <<
"</thead>\n";
929 case Atom::TableRowLeft:
930 if (!atom->string().isEmpty())
931 out() <<
"<tr " << atom->string() <<
'>';
932 else if (++m_numTableRows % 2 == 1)
933 out() << R"(<tr valign="top" class="odd">)";
935 out() << R"(<tr valign="top" class="even">)";
937 case Atom::TableRowRight:
946 for (
int i = 0; i < atom->count(); ++i) {
949 const QString &p = atom->string(i);
950 if (p.contains(
'=')) {
953 QStringList spans = p.split(QLatin1Char(
','));
954 if (spans.size() == 2) {
955 if (spans.at(0) !=
"1")
956 out() <<
" colspan=\"" << spans.at(0) <<
'"';
957 if (spans.at(1) !=
"1")
958 out() <<
" rowspan=\"" << spans.at(1) <<
'"';
963 if (matchAhead(atom, Atom::ParaLeft))
972 if (matchAhead(atom, Atom::ParaLeft))
980 out() <<
"<span id=\"" << Utilities::asAsciiPrintable(atom->string()) <<
"\"></span>";
982 case Atom::UnhandledFormat:
983 out() <<
"<b class=\"redFont\"><Missing HTML></b>";
985 case Atom::UnknownCommand:
986 out() << R"(<b class="redFont"><code translate=\"no\">\)" << protectEnc(atom->string()) <<
"</code></b>";
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1034 auto link_for_group = [
this](
const CollectionNode *group) -> QString {
1035 QString target{linkForNode(group,
nullptr)};
1036 return (target.isEmpty()) ? protectEnc(group->name()) :
"<a href=\"" + target +
"\">" + protectEnc(group->fullTitle()) +
"</a>";
1041 const QStringList &groups_names{node->groupNames()};
1042 if (groups_names.isEmpty())
1045 std::vector<CollectionNode *> groups_nodes(groups_names.size(),
nullptr);
1046 std::transform(groups_names.cbegin(), groups_names.cend(), groups_nodes.begin(),
1050 return (group && group
->wasSeen()) ? group :
nullptr;
1052 groups_nodes.erase(
std::remove(groups_nodes.begin(), groups_nodes.end(),
nullptr), groups_nodes.end());
1054 if (!groups_nodes.empty()) {
1055 text += node->name() +
" is part of ";
1057 for (std::vector<CollectionNode *>::size_type index{0}; index < groups_nodes.size(); ++index) {
1058 text += link_for_group(groups_nodes[index]) + Utilities::separator(index, groups_nodes.size());
1065
1066
1067
1068
1078 QString typeWord = aggregate->typeWord(
true);
1081 fullTitle = aggregate->plainFullName();
1082 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1087 fullTitle = aggregate->plainFullName();
1088 title =
"%1 %2"_L1.arg(fullTitle, typeWord);
1092 title = fullTitle = aggregate->fullTitle();
1099 if (aggregate
->parent()->isInAPI() || templateDecl) {
1101 subtitleText <<
"%1 "_L1.arg((*templateDecl).to_qstring());
1102 subtitleText << aggregate->typeWord(
false) <<
" "_L1;
1103 auto ancestors = fullTitle.split(
"::"_L1);
1104 ancestors.pop_back();
1105 for (
const auto &a : ancestors)
1106 subtitleText << Atom(Atom::AutoLink, a) <<
"::"_L1;
1107 subtitleText << aggregate->plainName();
1110 generateHeader(title, aggregate, marker);
1111 generateTableOfContents(aggregate, marker, summarySections);
1112 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1116 brief <<
"The " << ns->name() <<
" namespace includes the following elements from module "
1123 generateText(brief, ns, marker);
1126 generateBrief(aggregate, marker);
1128 const auto parentIsClass = aggregate
->parent()->isClassNode();
1131 generateRequisites(aggregate, marker);
1136 QString membersLink = generateAllMembersFile(Sections::allMembersSection(), marker);
1137 if (!membersLink.isEmpty()) {
1138 openUnorderedList();
1139 out() <<
"<li><a href=\"" << membersLink <<
"\">"
1140 <<
"List of all members, including inherited members</a></li>\n";
1142 QString obsoleteLink = generateObsoleteMembersFile(sections, marker);
1143 if (!obsoleteLink.isEmpty()) {
1144 openUnorderedList();
1145 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1146 <<
"Deprecated members</a></li>\n";
1149 if (QString groups_text{groupReferenceText(aggregate)}; !groups_text.isEmpty()) {
1150 openUnorderedList();
1152 out() <<
"<li>" << groups_text <<
"</li>\n";
1155 closeUnorderedList();
1161 bool needOtherSection =
false;
1163 for (
const auto §ion : std::as_const(*summarySections)) {
1164 if (section.members().isEmpty() && section.reimplementedMembers().isEmpty()) {
1165 if (!section.inheritedMembers().isEmpty())
1166 needOtherSection =
true;
1168 if (!section.members().isEmpty()) {
1169 QString ref = registerRef(section.title().toLower());
1170 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1171 generateSection(section.members(), aggregate, marker);
1173 if (!section.reimplementedMembers().isEmpty()) {
1174 QString name = QString(
"Reimplemented ") + section.title();
1175 QString ref = registerRef(name.toLower());
1176 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(name) <<
"</h2>\n";
1177 generateSection(section.reimplementedMembers(), aggregate, marker);
1180 if (!section.inheritedMembers().isEmpty()) {
1182 generateSectionInheritedList(section, aggregate);
1188 if (needOtherSection) {
1189 out() <<
"<h3>Additional Inherited Members</h3>\n"
1192 for (
const auto §ion : std::as_const(*summarySections)) {
1193 if (section.members().isEmpty() && !section.inheritedMembers().isEmpty())
1194 generateSectionInheritedList(section, aggregate);
1199 if (aggregate
->doc().isEmpty()) {
1200 QString command =
"documentation";
1202 command = R"('\class' comment)";
1205 QStringLiteral(
"No %1 for '%2'").arg(command, aggregate->plainSignature()));
1208 generateExtractionMark(aggregate, DetailedDescriptionMark);
1209 out() <<
"<div class=\"descr\">\n"
1210 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1211 <<
"Detailed Description"
1214 out() <<
"</div>\n";
1215 generateAlsoList(aggregate, marker);
1216 generateExtractionMark(aggregate, EndMark);
1219 for (
const auto §ion : std::as_const(*detailsSections)) {
1220 bool headerGenerated =
false;
1221 if (section.isEmpty())
1224 const QList<Node *> &members = section.members();
1225 for (
const auto &member : members) {
1226 if (member->access() == Access::Private)
1228 if (!headerGenerated) {
1229 if (!section.divClass().isEmpty())
1230 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1231 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1232 headerGenerated =
true;
1234 if (!member->isClassNode())
1235 generateDetailedMember(member, aggregate, marker);
1237 out() <<
"<h3> class ";
1238 generateFullName(member, aggregate);
1240 generateBrief(member, marker, aggregate);
1244 names << member->name();
1245 if (member->isFunction()) {
1246 const auto *func =
reinterpret_cast<
const FunctionNode *>(member);
1247 if (func->isSomeCtor() || func->isDtor() || func->overloadNumber() != 0)
1249 }
else if (member->isProperty()) {
1250 const auto *prop =
reinterpret_cast<
const PropertyNode *>(member);
1251 if (!prop->getters().isEmpty() && !names.contains(prop->getters().first()->name()))
1252 names << prop->getters().first()->name();
1253 if (!prop->setters().isEmpty())
1254 names << prop->setters().first()->name();
1255 if (!prop->resetters().isEmpty())
1256 names << prop->resetters().first()->name();
1257 if (!prop->notifiers().isEmpty())
1258 names << prop->notifiers().first()->name();
1259 }
else if (member->isEnumType()) {
1260 const auto *enume =
reinterpret_cast<
const EnumNode *>(member);
1261 if (enume->flagsType())
1262 names << enume->flagsType()->name();
1263 const auto &enumItemNameList = enume->doc().enumItemNames();
1264 const auto &omitEnumItemNameList = enume->doc().omitEnumItemNames();
1265 const auto items = QSet<QString>(enumItemNameList.cbegin(), enumItemNameList.cend())
1266 - QSet<QString>(omitEnumItemNameList.cbegin(), omitEnumItemNameList.cend());
1267 for (
const QString &enumName : items) {
1268 names << plainCode(marker->markedUpEnumValue(enumName, enume));
1272 if (headerGenerated && !section.divClass().isEmpty())
1273 out() <<
"</div>\n";
1275 generateFooter(aggregate);
1290 rawTitle = aggregate->plainName();
1291 fullTitle = aggregate->plainFullName();
1292 title = rawTitle +
" Proxy Page";
1295 generateHeader(title, aggregate, marker);
1296 generateTitle(title, subtitleText, SmallSubTitle, aggregate, marker);
1297 generateBrief(aggregate, marker);
1298 for (
auto it = summarySections->constBegin(); it != summarySections->constEnd(); ++it) {
1299 if (!it->members().isEmpty()) {
1300 QString ref = registerRef(it->title().toLower());
1301 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(it->title()) <<
"</h2>\n";
1302 generateSection(it->members(), aggregate, marker);
1306 if (!aggregate
->doc().isEmpty()) {
1307 generateExtractionMark(aggregate, DetailedDescriptionMark);
1308 out() <<
"<div class=\"descr\">\n"
1309 <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1310 <<
"Detailed Description"
1313 out() <<
"</div>\n";
1314 generateAlsoList(aggregate, marker);
1315 generateExtractionMark(aggregate, EndMark);
1318 for (
const auto §ion : std::as_const(*detailsSections)) {
1319 if (section.isEmpty())
1322 if (!section.divClass().isEmpty())
1323 out() <<
"<div class=\"" << section.divClass() <<
"\">\n";
1324 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1326 const QList<Node *> &members = section.members();
1327 for (
const auto &member : members) {
1328 if (!member->isPrivate()) {
1329 if (!member->isClassNode())
1330 generateDetailedMember(member, aggregate, marker);
1332 out() <<
"<h3> class ";
1333 generateFullName(member, aggregate);
1335 generateBrief(member, marker, aggregate);
1339 names << member->name();
1340 if (member->isFunction()) {
1341 const auto *func =
reinterpret_cast<
const FunctionNode *>(member);
1342 if (func->isSomeCtor() || func->isDtor() || func->overloadNumber() != 0)
1344 }
else if (member->isEnumType()) {
1345 const auto *enume =
reinterpret_cast<
const EnumNode *>(member);
1346 if (enume->flagsType())
1347 names << enume->flagsType()->name();
1348 const auto &enumItemNameList = enume->doc().enumItemNames();
1349 const auto &omitEnumItemNameList = enume->doc().omitEnumItemNames();
1351 QSet<QString>(enumItemNameList.cbegin(), enumItemNameList.cend())
1352 - QSet<QString>(omitEnumItemNameList.cbegin(),
1353 omitEnumItemNameList.cend());
1354 for (
const QString &enumName : items)
1355 names << plainCode(marker->markedUpEnumValue(enumName, enume));
1359 if (!section.divClass().isEmpty())
1360 out() <<
"</div>\n";
1362 generateFooter(aggregate);
1366
1367
1368
1372 SubTitleSize subTitleSize = LargeSubTitle;
1373 QString htmlTitle = qcn->fullTitle();
1375 htmlTitle.append(
" QML Value Type");
1377 htmlTitle.append(
" QML Type");
1380 generateHeader(htmlTitle, qcn, marker);
1382 generateTableOfContents(qcn, marker, §ions.stdQmlTypeSummarySections());
1383 marker = CodeMarker::markerForLanguage(QLatin1String(
"QML"));
1384 generateTitle(htmlTitle, Text() << qcn->subtitle(), subTitleSize, qcn, marker);
1385 generateBrief(qcn, marker);
1386 generateQmlRequisites(qcn, marker);
1389 QString allQmlMembersLink;
1392 if (!qcn->isQmlBasicType())
1393 allQmlMembersLink = generateAllQmlMembersFile(sections, marker);
1394 QString obsoleteLink = generateObsoleteQmlMembersFile(sections, marker);
1395 if (!allQmlMembersLink.isEmpty() || !obsoleteLink.isEmpty()) {
1396 openUnorderedList();
1398 if (!allQmlMembersLink.isEmpty()) {
1399 out() <<
"<li><a href=\"" << allQmlMembersLink <<
"\">"
1400 <<
"List of all members, including inherited members</a></li>\n";
1402 if (!obsoleteLink.isEmpty()) {
1403 out() <<
"<li><a href=\"" << obsoleteLink <<
"\">"
1404 <<
"Deprecated members</a></li>\n";
1408 if (QString groups_text{groupReferenceText(qcn)}; !groups_text.isEmpty()) {
1409 openUnorderedList();
1411 out() <<
"<li>" << groups_text <<
"</li>\n";
1414 closeUnorderedList();
1417 for (
const auto §ion : stdQmlTypeSummarySections) {
1418 if (!section.isEmpty()) {
1419 QString ref = registerRef(section.title().toLower());
1420 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section.title()) <<
"</h2>\n";
1421 generateQmlSummary(section.members(), qcn, marker);
1425 generateExtractionMark(qcn, DetailedDescriptionMark);
1426 out() <<
"<h2 id=\"" << registerRef(
"details") <<
"\">"
1427 <<
"Detailed Description"
1430 generateAlsoList(qcn, marker);
1431 generateExtractionMark(qcn, EndMark);
1434 for (
const auto §ion : stdQmlTypeDetailsSections) {
1435 if (!section.isEmpty()) {
1436 out() <<
"<h2>" << protectEnc(section.title()) <<
"</h2>\n";
1437 const QList<Node *> &members = section.members();
1438 for (
const auto member : members) {
1439 generateDetailedQmlMember(member, qcn, marker);
1444 generateFooter(qcn);
1449
1450
1451
1454 SubTitleSize subTitleSize = LargeSubTitle;
1455 QString fullTitle = pn->fullTitle();
1457 generateHeader(fullTitle, pn, marker);
1459
1460
1461
1462 if ((pn->name() != QLatin1String(
"index.html")))
1463 generateTableOfContents(pn, marker,
nullptr);
1465 generateTitle(fullTitle, Text() << pn->subtitle(), subTitleSize, pn, marker);
1467 generateBrief(pn, marker,
nullptr,
false);
1470 generateExtractionMark(pn, DetailedDescriptionMark);
1471 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1475 out() <<
"</div>\n";
1476 generateAlsoList(pn, marker);
1477 generateExtractionMark(pn, EndMark);
1483
1484
1487 SubTitleSize subTitleSize = LargeSubTitle;
1488 QString fullTitle = cn->fullTitle();
1491 generateHeader(fullTitle, cn, marker);
1492 generateTableOfContents(cn, marker,
nullptr);
1493 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1498 generateBrief(cn, marker);
1506 if (!nmm.isEmpty()) {
1507 ref = registerRef(
"namespaces");
1508 out() <<
"<h2 id=\"" << ref <<
"\">Namespaces</h2>\n";
1509 generateAnnotatedList(cn, marker, nmm.values());
1512 if (!nmm.isEmpty()) {
1513 ref = registerRef(
"classes");
1514 out() <<
"<h2 id=\"" << ref <<
"\">Classes</h2>\n";
1515 generateAnnotatedList(cn, marker, nmm.values());
1521 generateExtractionMark(cn, DetailedDescriptionMark);
1522 ref = registerRef(
"details");
1523 out() <<
"<div class=\"descr\">\n";
1524 out() <<
"<h2 id=\"" << ref <<
"\">"
1525 <<
"Detailed Description"
1528 generateExtractionMark(cn, DetailedDescriptionMark);
1529 out() << R"(<div class="descr" id=")" << registerRef(
"details")
1534 out() <<
"</div>\n";
1535 generateAlsoList(cn, marker);
1536 generateExtractionMark(cn, EndMark);
1539 if (cn->isGroup() || cn->isQmlModule())
1540 generateAnnotatedList(cn, marker, cn->members());
1546
1547
1548
1549
1552 SubTitleSize subTitleSize = LargeSubTitle;
1553 QString fullTitle = cn->name();
1555 generateHeader(fullTitle, cn, marker);
1556 generateTitle(fullTitle, Text() << cn->subtitle(), subTitleSize, cn, marker);
1559 brief <<
"Each function or type documented here is related to a class or "
1560 <<
"namespace that is documented in a different module. The reference "
1561 <<
"page for that class or namespace will link to the function or type "
1564 generateText(brief, cn, marker);
1568 for (
const auto &member : members)
1569 generateDetailedMember(member, cn, marker);
1575
1576
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604void HtmlGenerator::generateNavigationBar(
const QString &title,
const Node *node,
1605 CodeMarker *marker,
const QString &buildversion,
1608 if (m_noNavigationBar || node ==
nullptr)
1619 auto addNavItem = [&](
const QString &link,
const QString &title) {
1620 navigationbar << Atom(itemLeft) << Atom(
Atom::NavLink, link)
1627 auto addNavItemNode = [&](
const Node *node,
const QString &title) {
1628 navigationbar << Atom(itemLeft) <<
Atom(
Atom::LinkNode, CodeMarker::stringForNode(node))
1636 QString moduleState;
1637 if (moduleNode && !moduleNode->state().isEmpty())
1638 moduleState = QStringLiteral(
" (%1)").arg(moduleNode->state());
1640 if (m_hometitle == title)
1642 if (!m_homepage.isEmpty())
1643 addNavItem(m_homepage, m_hometitle);
1644 if (!m_landingpage.isEmpty() && m_landingtitle != title)
1645 addNavItem(m_landingpage, m_landingtitle);
1648 if (!m_cppclassespage.isEmpty() && !m_cppclassestitle.isEmpty())
1649 addNavItem(m_cppclassespage, m_cppclassestitle);
1650 if (!node->physicalModuleName().isEmpty()) {
1654 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_cppclassespage))
1655 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1657 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1659 if (!m_qmltypespage.isEmpty() && !m_qmltypestitle.isEmpty())
1660 addNavItem(m_qmltypespage, m_qmltypestitle);
1664 if (moduleNode && (!moduleState.isEmpty() || moduleNode->title() != m_qmltypespage)) {
1665 addNavItemNode(moduleNode, moduleNode->name() + moduleState);
1667 navigationbar << Atom(itemLeft) <<
Atom(
Atom::String, node->name()) << Atom(itemRight);
1670 auto currentNode{
static_cast<
const PageNode*>(node)};
1671 std::deque<
const Node *> navNodes;
1673 qsizetype navItems = 0;
1675 if (
std::find(navNodes.cbegin(), navNodes.cend(),
1682 if (navNodes.empty()) {
1683 const QStringList groups =
static_cast<
const PageNode *>(node)->groupNames();
1684 for (
const auto &groupName : groups) {
1685 const auto *groupNode = m_qdb->findNodeByNameAndType(QStringList{groupName}, &Node::isGroup);
1686 if (groupNode && !groupNode->title().isEmpty()) {
1687 navNodes.push_front(groupNode);
1692 while (!navNodes.empty()) {
1693 if (navNodes.front()->isPageNode())
1694 addNavItemNode(navNodes.front(), navNodes.front()->title());
1695 navNodes.pop_front();
1699 navigationbar << Atom(itemLeft) << Atom(
Atom::String, title) << Atom(itemRight);
1703 generateText(navigationbar, node, marker);
1705 if (buildversion.isEmpty())
1711 out() <<
"</tr></table><table class=\"buildversion\"><tr>\n"
1712 << R"(<td id="buildversion" width="100%" align="right">)";
1714 out() <<
"<li id=\"buildversion\">";
1718 if (!m_landingpage.isEmpty() && m_landingtitle != title) {
1719 navigationbar << Atom(Atom::NavLink, m_landingpage)
1721 << Atom(Atom::String, buildversion)
1723 generateText(navigationbar, node, marker);
1725 out() << buildversion;
1735 out() <<
"<!DOCTYPE html>\n";
1736 out() << QString(
"<html lang=\"%1\">\n").arg(naturalLanguage);
1737 out() <<
"<head>\n";
1738 out() <<
" <meta charset=\"utf-8\">\n";
1739 if (node && !node->doc().location().isEmpty())
1740 out() <<
"<!-- " << node->doc().location().fileName() <<
" -->\n";
1743 out() <<
" <meta name=\"description\" content=\""
1744 << protectEnc(node->doc().briefText().toString())
1749 QString titleSuffix;
1750 if (!m_landingtitle.isEmpty()) {
1752 titleSuffix = m_landingtitle;
1753 }
else if (!m_hometitle.isEmpty()) {
1756 if (title != m_hometitle)
1757 titleSuffix = m_hometitle;
1760 titleSuffix = m_productName.isEmpty() ? m_project : m_productName;
1762 if (title == titleSuffix)
1763 titleSuffix.clear();
1765 out() <<
" <title>";
1766 if (!titleSuffix.isEmpty() && !title.isEmpty()) {
1767 out() <<
"%1 | %2"_L1.arg(protectEnc(title), titleSuffix);
1769 out() << protectEnc(title);
1774 QVersionNumber projectVersion = QVersionNumber::fromString(m_qdb->version());
1775 if (!projectVersion.isNull()) {
1776 QVersionNumber titleVersion;
1777 static const QRegularExpression re(QLatin1String(R"(\d+\.\d+)"));
1778 const QString &versionedTitle = titleSuffix.isEmpty() ? title : titleSuffix;
1779 auto match = re.match(versionedTitle);
1780 if (match.hasMatch())
1781 titleVersion = QVersionNumber::fromString(match.captured());
1782 if (titleVersion.isNull() || !titleVersion.isPrefixOf(projectVersion)) {
1784 if (!m_productName.isEmpty() && titleSuffix != m_productName)
1785 out() <<
" | %1"_L1.arg(m_productName);
1786 out() <<
" %1"_L1.arg(projectVersion.toString());
1789 out() <<
"</title>\n";
1792 out() << m_headerStyles;
1793 out() << m_headerScripts;
1794 if (m_endHeader.isEmpty())
1795 out() <<
"</head>\n<body>\n";
1797 out() << m_endHeader;
1799 out() << QString(m_postHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1800 bool usingTable = m_postHeader.trimmed().endsWith(QLatin1String(
"<tr>"));
1801 generateNavigationBar(title, node, marker, m_buildversion, usingTable);
1802 out() << QString(m_postPostHeader).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1804 m_navigationLinks.clear();
1807 if (node && !node->links().empty()) {
1808 std::pair<QString, QString> linkPair;
1809 std::pair<QString, QString> anchorPair;
1810 const Node *linkNode;
1811 bool useSeparator =
false;
1813 if (node->links().contains(Node::PreviousLink)) {
1814 linkPair = node->links()[Node::PreviousLink];
1815 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1818 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1819 if (linkNode ==
nullptr || linkNode == node)
1820 anchorPair = linkPair;
1822 anchorPair = anchorForNode(linkNode);
1824 out() << R"( <link rel="prev" href=")" << anchorPair.first <<
"\" />\n";
1826 m_navigationLinks += R"(<a class="prevPage" href=")" + anchorPair.first +
"\">";
1827 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1828 m_navigationLinks += protect(anchorPair.second);
1830 m_navigationLinks += protect(linkPair.second);
1831 m_navigationLinks +=
"</a>\n";
1832 useSeparator = !m_navigationSeparator.isEmpty();
1834 if (node->links().contains(Node::NextLink)) {
1835 linkPair = node->links()[Node::NextLink];
1836 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1839 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1840 if (linkNode ==
nullptr || linkNode == node)
1841 anchorPair = linkPair;
1843 anchorPair = anchorForNode(linkNode);
1845 out() << R"( <link rel="next" href=")" << anchorPair.first <<
"\" />\n";
1848 m_navigationLinks += m_navigationSeparator;
1850 m_navigationLinks += R"(<a class="nextPage" href=")" + anchorPair.first +
"\">";
1851 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1852 m_navigationLinks += protect(anchorPair.second);
1854 m_navigationLinks += protect(linkPair.second);
1855 m_navigationLinks +=
"</a>\n";
1857 if (node->links().contains(Node::StartLink)) {
1858 linkPair = node->links()[Node::StartLink];
1859 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1862 QStringLiteral(
"Cannot link to '%1'").arg(linkPair.first));
1863 if (linkNode ==
nullptr || linkNode == node)
1864 anchorPair = linkPair;
1866 anchorPair = anchorForNode(linkNode);
1867 out() << R"( <link rel="start" href=")" << anchorPair.first <<
"\" />\n";
1871 if (node && !node->links().empty())
1872 out() <<
"<p class=\"naviNextPrevious headerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1876 SubTitleSize subTitleSize,
const Node *relative,
1879 out() << QString(m_prologue).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1882 attribute = R"( translate="no")";
1884 if (!title.isEmpty())
1885 out() <<
"<h1 class=\"title\"" << attribute <<
">" << protectEnc(title) <<
"</h1>\n";
1888 if (subTitleSize == SmallSubTitle)
1889 out() <<
" class=\"small-subtitle\"" << attribute <<
">";
1891 out() <<
" class=\"subtitle\"" << attribute <<
">";
1892 generateText(subtitle, relative, marker);
1893 out() <<
"</span>\n";
1899 if (node && !node->links().empty())
1900 out() <<
"<p class=\"naviNextPrevious footerNavi\">\n" << m_navigationLinks <<
"</p>\n";
1902 out() << QString(m_footer).replace(
"\\" +
COMMAND_VERSION, m_qdb->version())
1903 << QString(m_address).replace(
"\\" +
COMMAND_VERSION, m_qdb->version());
1905 out() <<
"</body>\n";
1906 out() <<
"</html>\n";
1910
1911
1912
1915 QMap<QString, Text> requisites;
1918 const QString headerText =
"Header";
1919 const QString sinceText =
"Since";
1920 const QString inheritedByText =
"Inherited By";
1921 const QString inheritsText =
"Inherits";
1922 const QString nativeTypeText =
"In QML";
1923 const QString qtVariableText =
"qmake";
1924 const QString cmakeText =
"CMake";
1925 const QString statusText =
"Status";
1928 const QStringList requisiteorder { headerText, cmakeText, qtVariableText, sinceText,
1929 nativeTypeText, inheritsText, inheritedByText, statusText };
1931 addIncludeFileToMap(aggregate, requisites, text, headerText);
1932 addSinceToMap(aggregate, requisites, &text, sinceText);
1935 addCMakeInfoToMap(aggregate, requisites, &text, cmakeText);
1936 addQtVariableToMap(aggregate, requisites, &text, qtVariableText);
1940 auto *classe =
dynamic_cast<
ClassNode *>(aggregate);
1941 if (classe->isQmlNativeType() && !classe->isInternal())
1942 addQmlNativeTypesToMap(requisites, &text, nativeTypeText, classe);
1944 addInheritsToMap(requisites, &text, inheritsText, classe);
1945 addInheritedByToMap(requisites, &text, inheritedByText, classe);
1949 addStatusToMap(aggregate, requisites, text, statusText);
1951 if (!requisites.isEmpty()) {
1953 generateTheTable(requisiteorder, requisites, aggregate, marker);
1958
1959
1960void HtmlGenerator::generateTheTable(
const QStringList &requisiteOrder,
1961 const QMap<QString, Text> &requisites,
1964 out() <<
"<div class=\"table\"><table class=\"alignedsummary requisites\" translate=\"no\">\n";
1966 for (
auto it = requisiteOrder.constBegin(); it != requisiteOrder.constEnd(); ++it) {
1968 if (requisites.contains(*it)) {
1970 <<
"<td class=\"memItemLeft rightAlign topAlign\"> " << *it
1972 "</td><td class=\"memItemRight bottomAlign\"> ";
1974 generateText(requisites.value(*it), aggregate, marker);
1975 out() <<
"</td></tr>\n";
1978 out() <<
"</table></div>\n";
1982
1983
1984
1985void HtmlGenerator::addInheritedByToMap(QMap<QString, Text> &requisites,
Text *text,
1986 const QString &inheritedByText,
ClassNode *classe)
1988 if (!classe->derivedClasses().isEmpty()) {
1991 int count = appendSortedNames(*text, classe, classe->derivedClasses());
1994 requisites.insert(inheritedByText, *text);
1999
2000
2001
2002void HtmlGenerator::addInheritsToMap(QMap<QString, Text> &requisites,
Text *text,
2003 const QString &inheritsText,
ClassNode *classe)
2005 if (!classe->baseClasses().isEmpty()) {
2008 const auto baseClasses = classe->baseClasses();
2009 for (
const auto &cls : baseClasses) {
2011 appendFullName(*text, cls.m_node, classe);
2013 if (cls.m_access == Access::Protected) {
2014 *text <<
" (protected)";
2015 }
else if (cls.m_access == Access::Private) {
2016 *text <<
" (private)";
2018 *text << Utilities::comma(index++, classe->baseClasses().size());
2023 requisites.insert(inheritsText, *text);
2028
2029
2030
2031 void HtmlGenerator::addQmlNativeTypesToMap(QMap<QString, Text> &requisites,
Text *text,
2032 const QString &nativeTypeText,
ClassNode *classe)
const
2039 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2041 qsizetype index { 0 };
2043 for (
const auto &item : std::as_const(nativeTypes)) {
2044 *text << Atom(Atom::LinkNode, CodeMarker::stringForNode(item))
2046 << Atom(Atom::String, item->name())
2048 *text << Utilities::comma(index++, nativeTypes.size());
2050 requisites.insert(nativeTypeText, *text);
2054
2055
2056
2058 Text *text,
const QString &CMakeInfo)
const
2060 if (!aggregate->physicalModuleName().isEmpty() && text !=
nullptr) {
2064 const auto result = cmakeRequisite(cn);
2077 requisites.insert(CMakeInfo, *text);
2082
2083
2084
2086 Text *text,
const QString &qtVariableText)
const
2088 if (!aggregate->physicalModuleName().isEmpty()) {
2092 if (cn && !cn->qtVariable().isEmpty()) {
2095 requisites.insert(qtVariableText, *text);
2101
2102
2103
2104
2106 Text *text,
const QString &sinceText)
const
2108 if (!aggregate->since().isEmpty() && text !=
nullptr) {
2111 requisites.insert(sinceText, *text);
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2127 Text &text,
const QString &statusText)
const
2129 auto status{formatStatus(aggregate, m_qdb)};
2135 spanClass = u"deprecated"_s;
2137 spanClass = Utilities::asAsciiPrintable(status.value());
2140 text << Atom(Atom::String, status.value())
2142 "class=\"status %1\""_L1.arg(spanClass))
2144 requisites.insert(statusText, text);
2148
2149
2150
2151
2153 QMap<QString, Text> &requisites,
Text& text,
2154 const QString &headerText)
2156 if (aggregate->includeFile()) {
2158 text << openCodeTag <<
"#include <%1>"_L1.arg(*aggregate->includeFile()) << closeCodeTag;
2159 requisites.insert(headerText, text);
2164
2165
2166
2171 QMap<QString, Text> requisites;
2174 const QString importText =
"Import Statement";
2175 const QString sinceText =
"Since";
2176 const QString inheritedByText =
"Inherited By";
2177 const QString inheritsText =
"Inherits";
2178 const QString nativeTypeText =
"In C++";
2179 const QString statusText =
"Status";
2182 QString logicalModuleVersion;
2190 requisites.insert(importText, text);
2192 qcn
->doc().location().warning(QStringLiteral(
"Could not resolve QML import statement for type '%1'").arg(qcn->name()),
2197 if (!qcn->since().isEmpty()) {
2200 requisites.insert(sinceText, text);
2211 requisites.insert(nativeTypeText, text);
2218 QStringList knownTypeNames{qcn->name()};
2224 knownTypeNames << base->name();
2231 for (
const auto sub : std::as_const(subs)) {
2232 if (knownTypeNames.contains(sub->name())) {
2233 text << Atom(Atom::String,
" (%1)"_L1.arg(base->logicalModuleName()));
2238 requisites.insert(inheritsText, text);
2242 if (!subs.isEmpty()) {
2245 int count = appendSortedQmlNames(text, qcn, knownTypeNames, subs);
2248 requisites.insert(inheritedByText, text);
2252 addStatusToMap(qcn, requisites, text, statusText);
2255 const QStringList requisiteorder { importText, sinceText, nativeTypeText, inheritsText,
2256 inheritedByText, statusText };
2258 if (!requisites.isEmpty())
2259 generateTheTable(requisiteorder, requisites, qcn, marker);
2271 QStringLiteral(
"'\\brief' statement does not end with a full stop."));
2273 generateExtractionMark(node, BriefMark);
2275 generateText(brief, node, marker);
2278 if (!relative || node == relative)
2279 out() <<
" <a href=\"#";
2281 out() <<
" <a href=\"" << linkForNode(node, relative) <<
'#';
2282 out() << registerRef(
"details") <<
"\">More...</a>";
2286 generateExtractionMark(node, EndMark);
2291
2292
2293
2295 QList<Section> *sections)
2299 toc = node
->doc().tableOfContents();
2300 if (tocDepth == 0 || (toc.isEmpty() && !sections && !node
->isModule())) {
2305 int sectionNumber = 1;
2306 int detailsBase = 0;
2311 out() <<
"<div class=\"sidebar\">\n";
2312 out() <<
"<div class=\"toc\">\n";
2313 out() <<
"<h3 id=\"toc\">Contents</h3>\n";
2316 openUnorderedList();
2319 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2320 << registerRef(
"namespaces") <<
"\">Namespaces</a></li>\n";
2323 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2324 << registerRef(
"classes") <<
"\">Classes</a></li>\n";
2327 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#" << registerRef(
"details")
2328 <<
"\">Detailed Description</a></li>\n";
2329 for (
const auto &entry : std::as_const(toc)) {
2330 if (entry->string().toInt() == 1) {
2336 for (
const auto §ion : std::as_const(*sections)) {
2337 if (!section.members().isEmpty()) {
2338 openUnorderedList();
2339 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2340 << registerRef(section.plural()) <<
"\">" << section.title() <<
"</a></li>\n";
2342 if (!section.reimplementedMembers().isEmpty()) {
2343 openUnorderedList();
2344 QString ref = QString(
"Reimplemented ") + section.plural();
2345 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2346 << registerRef(ref.toLower()) <<
"\">"
2347 << QString(
"Reimplemented ") + section.title() <<
"</a></li>\n";
2351 openUnorderedList();
2352 out() <<
"<li class=\"level" << sectionNumber <<
"\"><a href=\"#"
2353 << registerRef(
"details") <<
"\">Detailed Description</a></li>\n";
2355 for (
const auto &entry : toc) {
2356 if (entry->string().toInt() == 1) {
2363 for (
const auto &atom : toc) {
2364 sectionNumber = atom->string().toInt() + detailsBase;
2367 if (sectionNumber <= tocDepth || tocDepth < 0) {
2368 openUnorderedList();
2370 Text headingText = Text::sectionHeading(atom);
2371 out() <<
"<li class=\"level" << sectionNumber <<
"\">";
2372 out() <<
"<a href=\"" <<
'#' << Tree::refForAtom(atom) <<
"\">";
2373 generateAtomList(headingText.firstAtom(), node, marker,
true, numAtoms);
2374 out() <<
"</a></li>\n";
2377 closeUnorderedList();
2378 out() <<
"</div>\n";
2379 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2380 out() <<
"</div>\n";
2386
2387
2390 out() <<
"<div class=\"sidebar\">";
2391 out() << R"(<div class="sidebar-content" id="sidebar-content"></div>)";
2392 out() <<
"</div>\n";
2401 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2402 beginSubPage(aggregate, fileName);
2403 QString title =
"List of All Members for " + aggregate->plainFullName();
2404 generateHeader(title, aggregate, marker);
2406 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2407 out() <<
"<p>This is the complete list of members for ";
2408 generateFullName(aggregate,
nullptr);
2409 out() <<
", including inherited members.</p>\n";
2411 generateSectionList(section, aggregate, marker);
2419
2420
2421
2422
2423
2431 QString fileName = fileBase(aggregate) +
"-members." + fileExtension();
2432 beginSubPage(aggregate, fileName);
2433 QString title =
"List of All Members for " + aggregate->name();
2434 generateHeader(title, aggregate, marker);
2436 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2437 out() <<
"<p>This is the complete list of members for ";
2438 generateFullName(aggregate,
nullptr);
2439 out() <<
", including inherited members.</p>\n";
2442 for (
int i = 0; i < cknl.size(); i++) {
2446 if (nodes.isEmpty())
2449 out() <<
"<p>The following members are inherited from ";
2450 generateFullName(qcn,
nullptr);
2453 openUnorderedList();
2454 for (
int j = 0; j < nodes.size(); j++) {
2455 Node *node = nodes[j];
2461 std::function<
void(
Node *)> generate = [&](Node *n) {
2462 out() <<
"<li class=\"fn\" translate=\"no\">";
2463 generateQmlItem(n, aggregate, marker,
true);
2465 out() <<
" [default]";
2466 else if (n->isAttached())
2467 out() <<
" [attached]";
2469 if (n->isPropertyGroup()) {
2471 const QList<Node *> &collective =
2472 static_cast<SharedCommentNode *>(n)->collective();
2473 std::for_each(collective.begin(), collective.end(), generate);
2480 closeUnorderedList();
2497 QString title =
"Obsolete Members for " + aggregate->plainFullName();
2498 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2500 beginSubPage(aggregate, fileName);
2501 generateHeader(title, aggregate, marker);
2503 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2505 out() <<
"<p><b>The following members of class "
2506 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\" translate=\"no\">"
2507 << protectEnc(aggregate->name()) <<
"</a>"
2508 <<
" are deprecated.</b> "
2509 <<
"They are provided to keep old source code working. "
2510 <<
"We strongly advise against using them in new code.</p>\n";
2512 for (
const auto §ion : summary_spv) {
2513 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2514 generateSectionList(*section, aggregate, marker,
true);
2517 for (
const auto §ion : details_spv) {
2518 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2520 const NodeVector &members = section->obsoleteMembers();
2521 for (
const auto &member : members) {
2522 if (member->access() != Access::Private)
2523 generateDetailedMember(member, aggregate, marker);
2533
2534
2535
2536
2545 QString title =
"Obsolete Members for " + aggregate->name();
2546 QString fileName = fileBase(aggregate) +
"-obsolete." + fileExtension();
2548 beginSubPage(aggregate, fileName);
2549 generateHeader(title, aggregate, marker);
2551 generateTitle(title, Text(), SmallSubTitle, aggregate, marker);
2553 out() <<
"<p><b>The following members of QML type "
2554 <<
"<a href=\"" << linkForNode(aggregate,
nullptr) <<
"\">"
2555 << protectEnc(aggregate->name()) <<
"</a>"
2556 <<
" are deprecated.</b> "
2557 <<
"They are provided to keep old source code working. "
2558 <<
"We strongly advise against using them in new code.</p>\n";
2560 for (
const auto §ion : summary_spv) {
2561 QString ref = registerRef(section->title().toLower());
2562 out() <<
"<h2 id=\"" << ref <<
"\">" << protectEnc(section->title()) <<
"</h2>\n";
2563 generateQmlSummary(section->obsoleteMembers(), aggregate, marker);
2566 for (
const auto §ion : details_spv) {
2567 out() <<
"<h2>" << protectEnc(section->title()) <<
"</h2>\n";
2568 const NodeVector &members = section->obsoleteMembers();
2569 for (
const auto &member : members) {
2570 generateDetailedQmlMember(member, aggregate, marker);
2582 if (classMap.isEmpty())
2586 for (
const auto &it : classMap) {
2587 auto *classe =
static_cast<ClassNode *>(it);
2588 if (classe->baseClasses().isEmpty())
2589 topLevel.insert(classe->name(), classe);
2592 QStack<NodeMap> stack;
2593 stack.push(topLevel);
2596 while (!stack.isEmpty()) {
2597 if (stack.top().isEmpty()) {
2603 generateFullName(child, relative);
2605 stack.top().erase(stack.top().begin());
2608 const auto derivedClasses = child->derivedClasses();
2609 for (
const RelatedClass &d : derivedClasses) {
2610 if (d.m_node && d.m_node->isInAPI())
2611 newTop.insert(d.m_node->name(), d.m_node);
2613 if (!newTop.isEmpty()) {
2622
2623
2624
2626 const NodeList &unsortedNodes, Qt::SortOrder sortOrder)
2628 if (unsortedNodes.isEmpty() || relative ==
nullptr)
2632 bool allInternal =
true;
2633 for (
auto *node : unsortedNodes) {
2634 if (!node->isInternal() && !node->isDeprecated()) {
2635 allInternal =
false;
2636 nmm.insert(node->fullName(relative), node);
2641 out() <<
"<div class=\"table\"><table class=\"annotated\">\n";
2645 if (sortOrder == Qt::DescendingOrder)
2650 for (
const auto *node : std::as_const(nodes)) {
2652 out() <<
"<tr class=\"odd topAlign\">";
2654 out() <<
"<tr class=\"even topAlign\">";
2655 out() <<
"<td class=\"tblName\" translate=\"no\"><p>";
2656 generateFullName(node, relative);
2657 out() <<
"</p></td>";
2659 if (!node->isTextPageNode()) {
2660 Text brief = node->doc().trimmedBriefText(node->name());
2661 if (!brief.isEmpty()) {
2662 out() <<
"<td class=\"tblDescr\"><p>";
2663 generateText(brief, node, marker);
2664 out() <<
"</p></td>";
2665 }
else if (!node->reconstitutedBrief().isEmpty()) {
2666 out() <<
"<td class=\"tblDescr\"><p>";
2667 out() << node->reconstitutedBrief();
2668 out() <<
"</p></td>";
2671 out() <<
"<td class=\"tblDescr\"><p>";
2672 if (!node->reconstitutedBrief().isEmpty()) {
2673 out() << node->reconstitutedBrief();
2675 out() << protectEnc(node->doc().briefText().toString());
2676 out() <<
"</p></td>";
2680 out() <<
"</table></div>\n";
2684
2685
2686
2690 const auto &uniqueKeys = nmm.uniqueKeys();
2691 for (
const QString &name : uniqueKeys) {
2692 if (!name.isEmpty()) {
2693 out() <<
"<h2 id=\"" << registerRef(name.toLower()) <<
"\">" << protectEnc(name)
2696 generateAnnotatedList(relative, marker, nmm.values(name));
2701
2702
2703
2704
2705
2706
2707
2708
2709
2712 const QString &commonPrefix)
2717 const int NumParagraphs = 37;
2718 qsizetype commonPrefixLen = commonPrefix.size();
2721
2722
2723
2724
2725
2727 QString paragraphName[NumParagraphs + 1];
2728 QSet<
char> usedParagraphNames;
2730 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
2731 QStringList pieces = c.key().split(
"::");
2732 int idx = commonPrefixLen;
2733 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
2735 QString last = pieces.last().toLower();
2736 QString key = last.mid(idx);
2738 int paragraphNr = NumParagraphs - 1;
2740 if (key[0].digitValue() != -1) {
2741 paragraphNr = key[0].digitValue();
2742 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
2743 paragraphNr = 10 + key[0].unicode() -
'a';
2746 paragraphName[paragraphNr] = key[0].toUpper();
2747 usedParagraphNames.insert(key[0].toLower().cell());
2748 paragraph[paragraphNr].insert(last, c.value());
2752
2753
2754
2755
2756
2757
2758
2759 qsizetype paragraphOffset[NumParagraphs + 1];
2760 paragraphOffset[0] = 0;
2761 for (
int i = 0; i < NumParagraphs; i++)
2762 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
2765
2766
2767 if (includeAlphabet) {
2768 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2769 for (
int i = 0; i < 26; i++) {
2771 if (usedParagraphNames.contains(
char(
'a' + i)))
2772 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2774 out() <<
"</b></p>\n";
2778
2779
2780 out() <<
"<div class=\"flowListDiv\" translate=\"no\">\n";
2784 int curParOffset = 0;
2785 QString previousName;
2786 bool multipleOccurrences =
false;
2788 for (
int i = 0; i < nmm.size(); i++) {
2789 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
2795
2796
2797 if (curParOffset == 0) {
2800 if (++m_numTableRows % 2 == 1)
2801 out() <<
"<dl class=\"flowList odd\">";
2803 out() <<
"<dl class=\"flowList even\">";
2804 out() <<
"<dt class=\"alphaChar\"";
2805 if (includeAlphabet)
2806 out() << QString(
" id=\"%1\"").arg(paragraphName[curParNr][0].toLower());
2807 out() <<
"><b>" << paragraphName[curParNr] <<
"</b></dt>\n";
2811
2812
2814 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
2815 NodeMultiMap::Iterator it;
2816 NodeMultiMap::Iterator next;
2817 it = paragraph[curParNr].begin();
2818 for (
int j = 0; j < curParOffset; j++)
2823
2824
2825
2826 out() <<
"<a href=\"" << linkForNode(it.value(), relative) <<
"\">";
2828 QString fileName = fileBase(it.value()) +
"-obsolete." + fileExtension();
2830 if (useOutputSubdirs())
2831 link =
"../%1/"_L1.arg(it.value()->tree()->physicalModuleName());
2833 out() <<
"<a href=\"" << link <<
"\">";
2836 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
2837 const auto &name{pieces.last()};
2840 if (name != previousName)
2841 multipleOccurrences =
false;
2842 if ((next != paragraph[curParNr].end()) && (name == next.value()->name())) {
2843 multipleOccurrences =
true;
2844 previousName = name;
2846 if (multipleOccurrences && pieces.size() == 1)
2847 pieces.last().append(
": %1"_L1.arg(it.value()->tree()->camelCaseModuleName()));
2849 out() << protectEnc(pieces.last());
2851 if (pieces.size() > 1) {
2853 generateFullName(it.value()->parent(), relative);
2863 out() <<
"</div>\n";
2868 out() <<
"<p class=\"centerAlign functionIndex\" translate=\"no\"><b>";
2869 for (
int i = 0; i < 26; i++) {
2871 out() << QString(
"<a href=\"#%1\">%2</a> ").arg(ch).arg(ch.toUpper());
2873 out() <<
"</b></p>\n";
2875 char nextLetter =
'a';
2877 out() <<
"<ul translate=\"no\">\n";
2879 for (
auto fnMap = funcIndex.constBegin(); fnMap != funcIndex.constEnd(); ++fnMap) {
2880 const QString &key = fnMap.key();
2881 const QChar firstLetter = key.isEmpty() ? QChar(
'A') : key.front();
2882 Q_ASSERT_X(firstLetter.unicode() < 256,
"generateFunctionIndex",
2883 "Only valid C++ identifiers were expected");
2884 const char currentLetter = firstLetter.isLower() ? firstLetter.unicode() : nextLetter - 1;
2886 if (currentLetter < nextLetter) {
2890 while (nextLetter < currentLetter)
2891 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2892 Q_ASSERT(nextLetter == currentLetter);
2893 out() << QStringLiteral(
"<li id=\"%1\">").arg(nextLetter++);
2895 out() << protectEnc(key) <<
':';
2897 for (
auto it = (*fnMap).constBegin(); it != (*fnMap).constEnd(); ++it) {
2899 generateFullName((*it)->parent(), relative, *it);
2903 while (nextLetter <=
'z')
2904 out() << QStringLiteral(
"<li id=\"%1\"></li>").arg(nextLetter++);
2911 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
2912 Text text = it.key();
2913 generateText(text, relative, marker);
2917 generateFullName(it.value(), relative);
2920 }
while (it != legaleseTexts.constEnd() && it.key() == text);
2928 QString marked = marker->markedUpQmlItem(node, summary);
2929 marked.replace(
"@param>",
"i>");
2931 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
2932 .arg(summary ?
"summary"_L1 :
"details"_L1));
2933 marked.replace(
"</@extra>",
"</code>");
2937 marked.remove(
"<@name>");
2938 marked.remove(
"</@name>");
2939 marked.remove(
"<@type>");
2940 marked.remove(
"</@type>");
2942 out() << highlightedCode(marked, relative,
false, Node::QML);
2946
2947
2948
2949
2950
2951
2952
2960 if (sortOrder == Qt::DescendingOrder)
2965 for (
const auto *node : std::as_const(members)) {
2966 out() <<
"<li translate=\"no\">";
2967 generateFullName(node,
nullptr);
2975 const QString &selector, Qt::SortOrder sortOrder)
2979 if (selector == QLatin1String(
"overviews"))
2981 else if (selector == QLatin1String(
"cpp-modules"))
2983 else if (selector == QLatin1String(
"qml-modules"))
2988 const auto collectionList = cnm.values();
2989 nodeList.reserve(collectionList.size());
2990 for (
auto *collectionNode : collectionList)
2991 nodeList.append(collectionNode);
2992 generateAnnotatedList(relative, marker, nodeList, sortOrder);
2995
2996
2997
2998
3001 QStringLiteral(
"\\generatelist {%1} is only allowed in \\group, "
3002 "\\module and \\qmlmodule comments.")
3006 auto *node =
const_cast<
Node *>(relative);
3009 generateAnnotatedList(collectionNode, marker, collectionNode->members(), sortOrder);
3015 bool alignNames =
true;
3016 if (!nv.isEmpty()) {
3017 bool twoColumn =
false;
3018 if (nv.first()->isProperty()) {
3019 twoColumn = (nv.size() >= 5);
3023 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3026 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3027 <<
"<tr><td class=\"topAlign\">";
3032 for (
const auto &member : nv) {
3033 if (member->access() == Access::Private)
3037 out() <<
"<tr><td class=\"memItemLeft rightAlign topAlign\"> ";
3039 if (twoColumn && i == (nv.size() + 1) / 2)
3040 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3041 out() <<
"<li class=\"fn\" translate=\"no\">";
3044 generateSynopsis(member, relative, marker, Section::Summary, alignNames);
3046 out() <<
"</td></tr>\n";
3052 out() <<
"</table></div>\n";
3056 out() <<
"</td></tr>\n</table></div>\n";
3064 bool alignNames =
true;
3067 if (!members.isEmpty()) {
3068 bool hasPrivateSignals =
false;
3069 bool isInvokable =
false;
3070 bool twoColumn =
false;
3073 twoColumn = (members.size() >= 16);
3074 }
else if (members.first()->isProperty()) {
3075 twoColumn = (members.size() >= 5);
3079 out() <<
"<div class=\"table\"><table class=\"alignedsummary\" translate=\"no\">\n";
3082 out() <<
"<div class=\"table\"><table class=\"propsummary\" translate=\"no\">\n"
3083 <<
"<tr><td class=\"topAlign\">";
3088 for (
const auto &member : members) {
3089 if (member->access() == Access::Private)
3093 out() <<
"<tr><td class=\"memItemLeft topAlign rightAlign\"> ";
3095 if (twoColumn && i == (members.size() + 1) / 2)
3096 out() <<
"</ul></td><td class=\"topAlign\"><ul>\n";
3097 out() <<
"<li class=\"fn\" translate=\"no\">";
3100 generateSynopsis(member, relative, marker, section.style(), alignNames);
3101 if (member->isFunction()) {
3102 const auto *fn =
static_cast<
const FunctionNode *>(member);
3103 if (fn->isPrivateSignal()) {
3104 hasPrivateSignals =
true;
3106 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3107 }
else if (fn->isInvokable()) {
3110 out() <<
"</td><td class=\"memItemRight bottomAlign\">[see note below]";
3114 out() <<
"</td></tr>\n";
3120 out() <<
"</table></div>\n";
3124 out() <<
"</td></tr>\n</table></div>\n";
3127 if (hasPrivateSignals)
3135 && !section.inheritedMembers().isEmpty()) {
3137 generateSectionInheritedList(section, relative);
3144 const QList<std::pair<Aggregate *,
int>> &inheritedMembers = section.inheritedMembers();
3145 for (
const auto &member : inheritedMembers) {
3146 out() <<
"<li class=\"fn\" translate=\"no\">";
3147 out() << member.second <<
' ';
3148 if (member.second == 1) {
3149 out() << section.singular();
3151 out() << section.plural();
3153 out() <<
" inherited from <a href=\"" << fileName(member.first) <<
'#'
3154 << Generator::cleanRef(section.title().toLower()) <<
"\">"
3155 << protectEnc(member.first->plainFullName(relative)) <<
"</a></li>\n";
3162 QString marked = marker->markedUpSynopsis(node, relative, style);
3163 marked.replace(
"@param>",
"i>");
3166 marked.remove(
"<@name>");
3167 marked.remove(
"</@name>");
3171 static const QRegularExpression extraRegExp(
"<@extra>.*</@extra>",
3172 QRegularExpression::InvertedGreedinessOption);
3173 marked.remove(extraRegExp);
3175 marked.replace(
"<@extra>",
"<code class=\"%1 extra\" translate=\"no\">"_L1
3176 .arg(style == Section::Summary ?
"summary"_L1 :
"details"_L1));
3177 marked.replace(
"</@extra>",
"</code>");
3181 marked.remove(
"<@type>");
3182 marked.remove(
"</@type>");
3185 out() << highlightedCode(marked, relative, alignNames);
3188QString
HtmlGenerator::highlightedCode(
const QString &markedCode,
const Node *relative,
3191 QString src = markedCode;
3193 html.reserve(src.size());
3197 const QChar charLangle =
'<';
3198 const QChar charAt =
'@';
3200 static const QString typeTag(
"type");
3201 static const QString headerTag(
"headerfile");
3202 static const QString funcTag(
"func");
3203 static const QString linkTag(
"link");
3209 for (
int i = 0, srcSize = src.size(); i < srcSize;) {
3210 if (src.at(i) == charLangle && src.at(i + 1) == charAt) {
3211 if (alignNames && !done) {
3212 html += QLatin1String(
"</td><td class=\"memItemRight bottomAlign\">");
3216 if (parseArg(src, linkTag, &i, srcSize, &arg, &par1)) {
3217 html += QLatin1String(
"<b>");
3218 const Node *n = CodeMarker::nodeForString(par1.toString());
3219 QString link = linkForNode(n, relative);
3220 addLink(link, arg, &html);
3221 html += QLatin1String(
"</b>");
3222 }
else if (parseArg(src, funcTag, &i, srcSize, &arg, &par1)) {
3223 const FunctionNode *fn =
m_qdb->findFunctionNode(par1.toString(), relative, genus);
3224 QString link = linkForNode(fn, relative);
3225 addLink(link, arg, &html);
3226 par1 = QStringView();
3227 }
else if (parseArg(src, typeTag, &i, srcSize, &arg, &par1)) {
3228 par1 = QStringView();
3229 const Node *n =
m_qdb->findTypeNode(arg.toString(), relative, genus);
3230 html += QLatin1String(
"<span class=\"type\">");
3233 addLink(linkForNode(n, relative), arg, &html);
3237 addLink(linkForNode(n, relative), arg, &html);
3238 html += QLatin1String(
"</span>");
3239 }
else if (parseArg(src, headerTag, &i, srcSize, &arg, &par1)) {
3240 par1 = QStringView();
3241 if (arg.startsWith(QLatin1Char(
'&')))
3244 const Node *n =
m_qdb->findNodeForInclude(QStringList(arg.toString()));
3245 if (n && n != relative)
3246 addLink(linkForNode(n, relative), arg, &html);
3255 html += src.at(i++);
3272 html.reserve(src.size());
3273 static const QLatin1String spanTags[] = {
3274 QLatin1String(
"comment>"), QLatin1String(
"<span class=\"comment\">"),
3275 QLatin1String(
"preprocessor>"), QLatin1String(
"<span class=\"preprocessor\">"),
3276 QLatin1String(
"string>"), QLatin1String(
"<span class=\"string\">"),
3277 QLatin1String(
"char>"), QLatin1String(
"<span class=\"char\">"),
3278 QLatin1String(
"number>"), QLatin1String(
"<span class=\"number\">"),
3279 QLatin1String(
"op>"), QLatin1String(
"<span class=\"operator\">"),
3280 QLatin1String(
"type>"), QLatin1String(
"<span class=\"type\">"),
3281 QLatin1String(
"name>"), QLatin1String(
"<span class=\"name\">"),
3282 QLatin1String(
"keyword>"), QLatin1String(
"<span class=\"keyword\">")
3287 for (
int i = 0, n = src.size(); i < n;) {
3288 if (src.at(i) == QLatin1Char(
'<')) {
3289 if (src.at(i + 1) == QLatin1Char(
'@')) {
3291 bool handled =
false;
3292 for (
int k = 0; k != nTags; ++k) {
3293 const QLatin1String &tag = spanTags[2 * k];
3294 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3295 html += spanTags[2 * k + 1];
3303 while (i < n && src.at(i) != QLatin1Char(
'>'))
3308 }
else if (src.at(i + 1) == QLatin1Char(
'/') && src.at(i + 2) == QLatin1Char(
'@')) {
3310 bool handled =
false;
3311 for (
int k = 0; k != nTags; ++k) {
3312 const QLatin1String &tag = spanTags[2 * k];
3313 if (i + tag.size() <= src.size() && tag == QStringView(src).mid(i, tag.size())) {
3314 html += QLatin1String(
"</span>");
3322 while (i < n && src.at(i) != QLatin1Char(
'>'))
3341 if (match.hasMatch()) {
3343 qsizetype leftParenLoc = match.capturedStart(1);
3344 out() << protectEnc(atom->string().left(leftParenLoc));
3346 out() << protectEnc(atom->string().mid(leftParenLoc));
3350 out() << protectEnc(atom->string());
3355 return protect(string);
3360 if (string.isEmpty())
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.
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 logicalModuleVersion() const override
If the QML type's QML module pointer is set, return the QML module version from the QML module node.
QString logicalModuleName() const override
If the QML type's QML module pointer is set, return the QML module name from the QML module node.
static void subclasses(const Node *base, NodeList &subs)
Loads the list subs with the nodes of all the subclasses of base.
QmlTypeNode * qmlBaseNode() const override
If this Aggregate is a QmlTypeNode, this function returns a pointer to the QmlTypeNode that is its ba...
CollectionNode * logicalModule() const override
If this is a QmlTypeNode, a pointer to its QML module is returned, which is a pointer to a Collection...
A class for containing the elements of one documentation section.
const NodeVector & obsoleteMembers() const
void appendMembers(const NodeVector &nv)
ClassNodesList & classNodesList()
const Aggregate * aggregate() const
const NodeVector & members() const
A class for creating vectors of collections for documentation.
Aggregate * aggregate() const
Sections(Aggregate *aggregate)
This constructor builds the vectors of sections based on the type of the aggregate node.
SectionVector & stdCppClassSummarySections()
SectionVector & stdQmlTypeSummarySections()
SectionVector & stdDetailsSections()
SectionVector & stdCppClassDetailsSections()
SectionVector & stdQmlTypeDetailsSections()
SectionVector & sinceSections()
Sections(const NodeMultiMap &nsmap)
This constructor builds a vector of sections from the since node map, nsmap.
bool hasObsoleteMembers(SectionPtrVector *summary_spv, SectionPtrVector *details_spv) const
Returns true if any sections in this object contain obsolete members.
SectionVector & stdSummarySections()
static Section & allMembersSection()
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_USEALTTEXTASTITLE
#define CONFIG_CPPCLASSESTITLE
#define CONFIG_CODEPREFIX
#define CONFIG_QMLTYPESPAGE
#define CONFIG_HEADERSCRIPTS
#define CONFIG_DESCRIPTION
#define CONFIG_CODEINDENT
#define CONFIG_TRADEMARKSPAGE
#define CONFIG_CPPCLASSESPAGE
#define CONFIG_NATURALLANGUAGE
#define CONFIG_PRODUCTNAME
#define CONFIG_NAVIGATION
#define CONFIG_BUILDVERSION
#define CONFIG_LANDINGPAGE
#define CONFIG_CODESUFFIX
#define CONFIG_LANDINGTITLE
#define CONFIG_HEADERSTYLES
#define CONFIG_QMLTYPESTITLE
static const Atom closeCodeTag
static void addLink(const QString &linkTarget, QStringView nestedStuff, QString *res)
static const Atom openCodeTag
#define HTMLGENERATOR_PROLOGUE
#define HTMLGENERATOR_NONAVIGATIONBAR
#define HTMLGENERATOR_TOCDEPTH
#define HTMLGENERATOR_NAVIGATIONSEPARATOR
#define HTMLGENERATOR_POSTPOSTHEADER
#define HTMLGENERATOR_ADDRESS
#define HTMLGENERATOR_FOOTER
#define HTMLGENERATOR_POSTHEADER
QList< Node * > NodeVector
QMap< QString, Node * > NodeMap
QMap< QString, NodeMap > NodeMapMap
QMap< QString, CollectionNode * > CNMap
QT_BEGIN_NAMESPACE typedef QMultiMap< Text, const Node * > TextToNodeMap
std::pair< const QmlTypeNode *, NodeVector > ClassNodes
QList< const Section * > SectionPtrVector
QList< Section > SectionVector
QList< ClassNodes > ClassNodesList
Represents a file that is reachable by QDoc based on its current configuration.