33#include <QtCore/qlist.h>
34#include <QtCore/qmap.h>
35#include <QtCore/quuid.h>
36#include <QtCore/qurl.h>
37#include <QtCore/qregularexpression.h>
38#include <QtCore/qversionnumber.h>
44using namespace Qt::StringLiterals;
46static const char dbNamespace[] =
"http://docbook.org/ns/docbook";
54 m_writer->writeCharacters(
"\n");
62 m_writer->writeAttribute(
"xml:id", registerRef(id,
true));
75 QString id = Generator::cleanRef(refForNode(node),
true);
77 m_writer->writeAttribute(
"xml:id", id);
84 m_writer->writeStartElement(dbNamespace,
"section");
87 m_writer->writeStartElement(dbNamespace,
"title");
92 m_writer->writeStartElement(dbNamespace,
"section");
95 m_writer->writeStartElement(dbNamespace,
"title");
100 m_writer->writeEndElement();
106 startSectionBegin(id);
107 m_writer->writeCharacters(title);
113 startSectionBegin(node);
114 m_writer->writeCharacters(title);
121 startSection(
"", title);
126 m_writer->writeEndElement();
135 m_writer->writeEmptyElement(dbNamespace,
"anchor");
141
142
143
148 m_config = &Config::instance();
154 if (m_projectDescription.isEmpty() && !m_project.isEmpty())
155 m_projectDescription = m_project + QLatin1String(
" Reference Documentation");
158 if (m_naturalLanguage.isEmpty())
159 m_naturalLanguage = QLatin1String(
"en");
163 m_config->get(format() + Config::dot +
"usedocbookextensions").asBool();
164 m_useITS = m_config->get(format() + Config::dot +
"its").asBool();
173
174
181
182
183
184
199 QString rewritten = code;
200 static const QRegularExpression re(
"(<@[^>&]*>)|(<\\/@[^&>]*>)");
201 rewritten.replace(re,
"");
206
207
213 qsizetype skipAhead = 0;
214 Genus genus = Genus::DontCare;
222 if (!m_inLink && !m_inContents && !m_inSectionHeading) {
223 const Node *node =
nullptr;
224 QString link = getAutoLink(atom, relative, &node, genus);
229 if (link.isEmpty()) {
230 m_writer->writeCharacters(atom->string());
232 beginLink(link, node, relative);
237 m_writer->writeCharacters(atom->string());
247 m_writer->writeStartElement(dbNamespace,
"para");
253 m_writer->writeEndElement();
263 m_writer->writeCharacters(plainCode(atom->string()));
265 m_writer->writeTextElement(dbNamespace,
"code", plainCode(atom->string()));
267 case Atom::CaptionLeft:
268 m_writer->writeStartElement(dbNamespace,
"title");
272 m_writer->writeEndElement();
276 m_writer->writeStartElement(dbNamespace,
"programlisting");
277 m_writer->writeAttribute(
"language",
"qml");
279 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
280 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
281 m_writer->writeEndElement();
285 m_writer->writeStartElement(dbNamespace,
"programlisting");
287 if (atom->strings().count() == 2)
288 m_writer->writeAttribute(
"language", atom->string(1));
290 m_writer->writeAttribute(
"language",
"cpp");
292 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
293 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
294 m_writer->writeEndElement();
298 m_writer->writeStartElement(dbNamespace,
"programlisting");
299 m_writer->writeAttribute(
"language",
"cpp");
300 m_writer->writeAttribute(
"role",
"bad");
302 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
303 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
304 m_writer->writeEndElement();
311 qsizetype offset{ 0 };
320 case Atom::FootnoteLeft:
321 m_writer->writeStartElement(dbNamespace,
"footnote");
323 m_writer->writeStartElement(dbNamespace,
"para");
326 case Atom::FootnoteRight:
327 m_writer->writeEndElement();
330 m_writer->writeEndElement();
338 m_writer->writeStartElement(dbNamespace,
"emphasis");
339 m_writer->writeAttribute(
"role",
"bold");
341 m_writer->writeStartElement(dbNamespace,
"emphasis");
343 m_writer->writeStartElement(dbNamespace,
"emphasis");
344 m_writer->writeAttribute(
"role",
"underline");
346 m_writer->writeStartElement(dbNamespace,
"subscript");
348 m_writer->writeStartElement(dbNamespace,
"superscript");
351 m_writer->writeStartElement(dbNamespace,
"code");
353 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
356 m_writer->writeAttribute(
"role",
"parameter");
360 m_writer->writeStartElement(dbNamespace,
"guilabel");
362 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
364 m_writer->writeStartElement(dbNamespace,
365 appendTrademark(atom->find(Atom::FormattingRight)) ?
366 "trademark" :
"phrase");
368 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
370 m_writer->writeStartElement(dbNamespace,
"phrase");
372 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
374 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
387 m_writer->writeEndElement();
390 m_inTeletype =
false;
393 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
397 if (
const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group))
398 generateList(cn, atom->string(), Generator::sortOrder(atom->strings().last()));
401 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
402 bool hasGeneratedSomething =
false;
403 if (atom->string() == QLatin1String(
"annotatedclasses")
404 || atom->string() == QLatin1String(
"attributions")
405 || atom->string() == QLatin1String(
"namespaces")) {
406 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedclasses")
407 ? m_qdb->getCppClasses()
408 : atom->string() == QLatin1String(
"attributions") ? m_qdb->getAttributions()
409 : m_qdb->getNamespaces();
410 generateAnnotatedList(relative, things.values(), atom->string(), Auto, sortOrder);
411 hasGeneratedSomething = !things.isEmpty();
412 }
else if (atom->string() == QLatin1String(
"annotatedexamples")
413 || atom->string() == QLatin1String(
"annotatedattributions")) {
414 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedexamples")
415 ? m_qdb->getAttributions()
416 : m_qdb->getExamples();
417 generateAnnotatedLists(relative, things, atom->string());
418 hasGeneratedSomething = !things.isEmpty();
419 }
else if (atom->string() == QLatin1String(
"classes")
420 || atom->string() == QLatin1String(
"qmlbasictypes")
421 || atom->string() == QLatin1String(
"qmlvaluetypes")
422 || atom->string() == QLatin1String(
"qmltypes")) {
423 const NodeMultiMap things = atom->string() == QLatin1String(
"classes")
424 ? m_qdb->getCppClasses()
425 : (atom->string() == QLatin1String(
"qmlvaluetypes")
426 || atom->string() == QLatin1String(
"qmlbasictypes"))
427 ? m_qdb->getQmlValueTypes()
428 : m_qdb->getQmlTypes();
429 generateCompactList(relative, things,
true, QString(), atom->string());
430 hasGeneratedSomething = !things.isEmpty();
431 }
else if (atom->string().contains(
"classes ")) {
432 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
435 hasGeneratedSomething = !things.isEmpty();
436 generateCompactList(relative, things,
true, rootName, atom->string());
437 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
438 QString moduleName = atom->string().mid(idx + 8).trimmed();
441 if (
const CollectionNode *cn = qdb->getCollectionNode(moduleName, moduleType)) {
443 switch (moduleType) {
449 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
455 generateAnnotatedList(relative, cn->members(), atom->string(), Auto, sortOrder);
459 if (!map.isEmpty()) {
460 generateAnnotatedList(relative, map.values(), atom->string(), Auto, sortOrder);
461 hasGeneratedSomething =
true;
464 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
465 generateClassHierarchy(relative, m_qdb->getCppClasses());
466 hasGeneratedSomething = !m_qdb->getCppClasses().isEmpty();
467 }
else if (atom->string().startsWith(
"obsolete")) {
468 QString prefix = atom->string().contains(
"cpp") ? QStringLiteral(
"Q") : QString();
469 const NodeMultiMap &things = atom->string() == QLatin1String(
"obsoleteclasses")
470 ? m_qdb->getObsoleteClasses()
471 : atom->string() == QLatin1String(
"obsoleteqmltypes")
472 ? m_qdb->getObsoleteQmlTypes()
473 : atom->string() == QLatin1String(
"obsoletecppmembers")
474 ? m_qdb->getClassesWithObsoleteMembers()
475 : m_qdb->getQmlTypesWithObsoleteMembers();
476 generateCompactList(relative, things,
false, prefix, atom->string());
477 hasGeneratedSomething = !things.isEmpty();
478 }
else if (atom->string() == QLatin1String(
"functionindex")) {
479 generateFunctionIndex(relative);
480 hasGeneratedSomething = !m_qdb->getFunctionIndex().isEmpty();
481 }
else if (atom->string() == QLatin1String(
"legalese")) {
482 generateLegaleseList(relative);
483 hasGeneratedSomething = !m_qdb->getLegaleseTexts().isEmpty();
484 }
else if (atom->string() == QLatin1String(
"overviews")
485 || atom->string() == QLatin1String(
"cpp-modules")
486 || atom->string() == QLatin1String(
"qml-modules")
487 || atom->string() == QLatin1String(
"related")) {
488 generateList(relative, atom->string());
489 hasGeneratedSomething =
true;
491 }
else if (
const auto *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group); cn) {
492 generateAnnotatedList(cn, cn->members(), atom->string(), ItemizedList, sortOrder);
493 hasGeneratedSomething =
true;
498 if (!hasGeneratedSomething && !m_inPara) {
499 m_writer->writeEmptyElement(dbNamespace,
"para");
531 m_writer->writeStartElement(dbNamespace,
"figure");
538 generateAtom(current, relative,
nullptr);
543 generateAtom(current, relative,
nullptr);
549 generateAtom(current, relative,
nullptr);
553 m_closeFigureWrapper =
true;
564 m_writer->writeStartElement(dbNamespace,
"figure");
571 generateAtom(current, relative,
nullptr);
576 generateAtom(current, relative,
nullptr);
582 generateAtom(current, relative,
nullptr);
586 m_closeFigureWrapper =
true;
609 m_writer->writeStartElement(dbNamespace, tag);
612 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
613 if (!maybe_resolved_file) {
615 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
617 m_writer->writeStartElement(dbNamespace,
"textobject");
619 m_writer->writeStartElement(dbNamespace,
"para");
620 m_writer->writeTextElement(dbNamespace,
"emphasis",
621 "[Missing image " + atom->string() +
"]");
622 m_writer->writeEndElement();
624 m_writer->writeEndElement();
628 QString file_name{QFileInfo{file.get_path()}.fileName()};
632 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
636 m_writer->writeTextElement(dbNamespace,
"alt", atom->next()->string());
640 m_writer->writeStartElement(dbNamespace,
"imageobject");
642 m_writer->writeEmptyElement(dbNamespace,
"imagedata");
643 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
645 m_writer->writeAttribute(
"fileref", imgPath);
647 m_writer->writeEndElement();
651 setImageFileName(relative, imgPath);
654 m_writer->writeEndElement();
658 if (m_closeFigureWrapper) {
659 m_writer->writeEndElement();
661 m_closeFigureWrapper =
false;
669 QString admonType = atom->typeString().toLower();
672 m_writer->writeStartElement(dbNamespace, admonType);
674 m_writer->writeStartElement(dbNamespace,
"para");
677 case Atom::ImportantRight:
678 case Atom::NoteRight:
679 case Atom::WarningRight:
680 m_writer->writeEndElement();
683 m_writer->writeEndElement();
691 const Node *node =
nullptr;
692 QString link = getLink(atom, relative, &node);
693 beginLink(link, node, relative);
697 const Node *node =
static_cast<
const Node*>(Utilities::nodeForString(atom->string()));
698 beginLink(linkForNode(node, relative), node, relative);
708 m_writer->writeEndElement();
714 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
717 m_writer->writeStartElement(dbNamespace,
"variablelist");
720 m_writer->writeStartElement(dbNamespace,
"informaltable");
722 m_writer->writeStartElement(dbNamespace,
"thead");
724 m_writer->writeStartElement(dbNamespace,
"tr");
726 m_writer->writeTextElement(dbNamespace,
"th",
"Constant");
729 m_threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
730 if (m_threeColumnEnumValueTable && relative->isEnumType(Genus::CPP)) {
732 m_writer->writeTextElement(dbNamespace,
"th",
"Value");
737 m_writer->writeTextElement(dbNamespace,
"th",
"Description");
741 m_writer->writeEndElement();
743 m_writer->writeEndElement();
746 m_writer->writeStartElement(dbNamespace,
"orderedlist");
748 if (atom->next() !=
nullptr && atom->next()->string().toInt() != 1)
749 m_writer->writeAttribute(
"startingnumber", atom->next()->string());
752 m_writer->writeAttribute(
"numeration",
"upperalpha");
754 m_writer->writeAttribute(
"numeration",
"loweralpha");
756 m_writer->writeAttribute(
"numeration",
"upperroman");
758 m_writer->writeAttribute(
"numeration",
"lowerroman");
760 m_writer->writeAttribute(
"numeration",
"arabic");
770 m_writer->writeStartElement(dbNamespace,
"varlistentry");
772 m_writer->writeStartElement(dbNamespace,
"item");
774 std::pair<QString,
int> pair = getAtomListValue(atom);
775 skipAhead = pair.second;
777 m_writer->writeStartElement(dbNamespace,
"tr");
779 m_writer->writeStartElement(dbNamespace,
"td");
781 m_writer->writeStartElement(dbNamespace,
"para");
783 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
784 generateEnumValue(pair.first, relative);
785 m_writer->writeEndElement();
787 m_writer->writeEndElement();
791 const auto enume =
static_cast<
const EnumNode *>(relative);
792 QString itemValue = enume->itemValue(atom
->next()->string());
794 m_writer->writeStartElement(dbNamespace,
"td");
795 if (itemValue.isEmpty())
796 m_writer->writeCharacters(
"?");
798 m_writer->writeStartElement(dbNamespace,
"code");
800 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
801 m_writer->writeCharacters(itemValue);
802 m_writer->writeEndElement();
804 m_writer->writeEndElement();
812 m_writer->writeEndElement();
818 m_writer->writeEndElement();
825 m_inListItemLineOpen =
false;
827 m_writer->writeStartElement(dbNamespace,
"listitem");
829 m_writer->writeStartElement(dbNamespace,
"para");
832 if (m_threeColumnEnumValueTable) {
834 m_writer->writeEmptyElement(dbNamespace,
"td");
836 m_inListItemLineOpen =
false;
838 m_writer->writeStartElement(dbNamespace,
"td");
840 m_inListItemLineOpen =
true;
844 m_writer->writeStartElement(dbNamespace,
"listitem");
853 m_writer->writeEndElement();
856 m_writer->writeEndElement();
858 m_writer->writeEndElement();
861 if (m_inListItemLineOpen) {
862 m_writer->writeEndElement();
864 m_inListItemLineOpen =
false;
866 m_writer->writeEndElement();
869 m_writer->writeEndElement();
874 case Atom::ListRight:
880 m_writer->writeEndElement();
887 m_writer->writeStartElement(dbNamespace,
"para");
893 m_writer->writeEndElement();
898 case Atom::QuotationLeft:
899 m_writer->writeStartElement(dbNamespace,
"blockquote");
900 m_inBlockquote =
true;
902 case Atom::QuotationRight:
903 m_writer->writeEndElement();
905 m_inBlockquote =
false;
908 m_writer->device()->write(atom->string().toUtf8());
914 currentSectionLevel = atom->string().toInt() +
hOffset(relative
);
916 if (currentSectionLevel > 1) {
919 while (!sectionLevels.empty() && sectionLevels.top() >= currentSectionLevel) {
921 m_writer->writeEndElement();
925 sectionLevels.push(currentSectionLevel);
927 m_writer->writeStartElement(dbNamespace,
"section");
928 writeXmlId(Tree::refForAtom(atom));
941 generateAtom(atom->next(), relative,
nullptr);
942 generateAtom(atom->next()->next(), relative,
nullptr);
943 generateAtom(atom->next()->next()->next(), relative,
nullptr);
945 m_closeSectionAfterGeneratedList =
true;
952 m_writer->writeTextElement(dbNamespace,
"title",
"");
961 if (currentSectionLevel > 1) {
962 m_writer->writeStartElement(dbNamespace,
"title");
963 m_inSectionHeading =
true;
968 if (currentSectionLevel > 1) {
969 m_writer->writeEndElement();
971 m_inSectionHeading =
false;
974 case Atom::SidebarLeft:
975 m_writer->writeStartElement(dbNamespace,
"sidebar");
977 case Atom::SidebarRight:
978 m_writer->writeEndElement();
982 if (m_inLink && !m_inContents && !m_inSectionHeading)
985 m_writer->writeCharacters(atom->string());
988 std::pair<QString, QString> pair = getTableWidthAttr(atom);
989 QString attr = pair.second;
990 QString width = pair.first;
993 m_writer->writeEndElement();
998 m_tableHeaderAlreadyOutput =
false;
1000 m_writer->writeStartElement(dbNamespace,
"informaltable");
1001 m_writer->writeAttribute(
"style", attr);
1002 if (!width.isEmpty())
1003 m_writer->writeAttribute(
"width", width);
1006 case Atom::TableRight:
1007 m_tableWidthAttr = {
"",
""};
1008 m_writer->writeEndElement();
1017 if (m_tableHeaderAlreadyOutput) {
1020 m_writer->writeEndElement();
1023 const QString &attr = m_tableWidthAttr.second;
1024 const QString &width = m_tableWidthAttr.first;
1026 m_writer->writeStartElement(dbNamespace,
"informaltable");
1027 m_writer->writeAttribute(
"style", attr);
1028 if (!width.isEmpty())
1029 m_writer->writeAttribute(
"width", width);
1032 m_tableHeaderAlreadyOutput =
true;
1038 id = TextUtils::asAsciiPrintable(next->string());
1043 m_writer->writeStartElement(dbNamespace,
"thead");
1045 m_writer->writeStartElement(dbNamespace,
"tr");
1048 m_inTableHeader =
true;
1051 m_closeTableCell =
true;
1052 m_writer->writeStartElement(dbNamespace,
"td");
1058 if (m_closeTableCell) {
1059 m_closeTableCell =
false;
1060 m_writer->writeEndElement();
1064 m_writer->writeEndElement();
1068 m_writer->writeStartElement(dbNamespace,
"tr");
1071 m_writer->writeEndElement();
1073 m_inTableHeader =
false;
1083 bool hasTarget {
false};
1085 id = TextUtils::asAsciiPrintable(atom
->next()->string());
1090 m_writer->writeStartElement(dbNamespace,
"tr");
1093 if (atom->string().isEmpty()) {
1094 m_writer->writeAttribute(
"valign",
"top");
1099 QStringList args = atom->string().split(
"\"", Qt::SkipEmptyParts);
1102 const int nArgs = args.size();
1107 QStringLiteral(
"Error when parsing attributes for the table: got \"%1\"")
1108 .arg(atom->string()));
1110 for (
int i = 0; i + 1 < nArgs; i += 2) {
1113 const QString &attr = args.at(i).chopped(1);
1116 writeXmlId(args.at(i + 1));
1118 m_writer->writeAttribute(attr, args.at(i + 1));
1134 m_closeTableRow =
true;
1135 m_writer->writeEndElement();
1141 if (m_closeTableRow) {
1142 m_closeTableRow =
false;
1143 m_writer->writeEndElement();
1147 m_writer->writeEndElement();
1150 case Atom::TableItemLeft:
1151 m_writer->writeStartElement(dbNamespace, m_inTableHeader ?
"th" :
"td");
1153 for (
int i = 0; i < atom->count(); ++i) {
1154 const QString &p = atom->string(i);
1155 if (p.contains(
'=')) {
1156 QStringList lp = p.split(QLatin1Char(
'='));
1157 m_writer->writeAttribute(lp.at(0), lp.at(1));
1159 QStringList spans = p.split(QLatin1Char(
','));
1160 if (spans.size() == 2) {
1161 if (spans.at(0) !=
"1")
1162 m_writer->writeAttribute(
"colspan", spans.at(0).trimmed());
1163 if (spans.at(1) !=
"1")
1164 m_writer->writeAttribute(
"rowspan", spans.at(1).trimmed());
1171 case Atom::TableItemRight:
1172 m_writer->writeEndElement();
1184 QString nextId = TextUtils::asAsciiPrintable(
1186 QString ownId = TextUtils::asAsciiPrintable(atom->string());
1187 if (nextId == ownId)
1191 writeAnchor(TextUtils::asAsciiPrintable(atom->string()));
1193 case Atom::UnhandledFormat:
1194 m_writer->writeStartElement(dbNamespace,
"emphasis");
1195 m_writer->writeAttribute(
"role",
"bold");
1196 m_writer->writeCharacters(
"<Missing DocBook>");
1197 m_writer->writeEndElement();
1199 case Atom::UnknownCommand:
1200 m_writer->writeStartElement(dbNamespace,
"emphasis");
1201 m_writer->writeAttribute(
"role",
"bold");
1203 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1204 m_writer->writeCharacters(
"<Unknown command>");
1205 m_writer->writeStartElement(dbNamespace,
"code");
1206 m_writer->writeCharacters(atom->string());
1207 m_writer->writeEndElement();
1208 m_writer->writeEndElement();
1228 if (classMap.isEmpty())
1231 std::function<
void(
ClassNode *)> generateClassAndChildren
1232 = [
this, &relative, &generateClassAndChildren](ClassNode * classe) {
1233 m_writer->writeStartElement(dbNamespace,
"listitem");
1237 m_writer->writeStartElement(dbNamespace,
"para");
1238 generateFullName(classe, relative);
1239 m_writer->writeEndElement();
1243 bool hasChild =
false;
1244 for (
const RelatedClass &relatedClass : classe->derivedClasses()) {
1245 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1252 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1255 for (
const RelatedClass &relatedClass: classe->derivedClasses()) {
1256 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1257 generateClassAndChildren(relatedClass.m_node);
1261 m_writer->writeEndElement();
1266 m_writer->writeEndElement();
1270 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1273 for (
const auto &it : classMap) {
1274 auto *classe =
static_cast<ClassNode *>(it);
1275 if (classe->baseClasses().isEmpty())
1276 generateClassAndChildren(classe);
1279 m_writer->writeEndElement();
1288 if (m_linkNode && m_linkNode->isFunction()) {
1290 if (match.hasMatch()) {
1292 qsizetype leftParenLoc = match.capturedStart(1);
1293 m_writer->writeCharacters(atom->string().left(leftParenLoc));
1295 m_writer->writeCharacters(atom->string().mid(leftParenLoc));
1299 m_writer->writeCharacters(atom->string());
1303
1304
1305
1309 m_writer->writeStartElement(dbNamespace,
"link");
1310 m_writer->writeAttribute(xlinkNamespace,
"href", link);
1311 if (node && !(relative && node->status() == relative->status())
1312 && node->isDeprecated())
1313 m_writer->writeAttribute(
"role",
"deprecated");
1322 m_writer->writeEndElement();
1324 m_linkNode =
nullptr;
1328 Qt::SortOrder sortOrder)
1333 if (selector == QLatin1String(
"overviews"))
1335 else if (selector == QLatin1String(
"cpp-modules"))
1337 else if (selector == QLatin1String(
"qml-modules"))
1342 m_qdb->mergeCollections(type, cnm, relative);
1343 const QList<CollectionNode *> collectionList = cnm.values();
1344 nodeList.reserve(collectionList.size());
1345 for (
auto *collectionNode : collectionList)
1346 nodeList.append(collectionNode);
1347 generateAnnotatedList(relative, nodeList, selector, Auto, sortOrder);
1350
1351
1352
1353 Node *n =
const_cast<
Node *>(relative);
1354 auto *cn =
static_cast<CollectionNode *>(n);
1355 m_qdb->mergeCollections(cn);
1356 generateAnnotatedList(cn, cn->members(), selector, Auto, sortOrder);
1361
1362
1363
1365 const QString &selector, GeneratedListType type,
1366 Qt::SortOrder sortOrder)
1368 if (nodeList.isEmpty())
1372 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1373 if (
std::all_of(nodeList.cbegin(), nodeList.cend(), [&policy](
const Node *n) {
1375 return !InclusionFilter::isIncluded(policy, context) || n->isDeprecated();
1382 bool noItemsHaveTitle =
1383 type == ItemizedList ||
std::all_of(nodeList.begin(), nodeList.end(),
1384 [](
const Node* node) {
1385 return node->doc().briefText().toString().isEmpty();
1389 if (type == AutoSection && m_hasSection)
1390 startSection(
"",
"Contents");
1393 if (!nodeList.isEmpty()) {
1394 m_writer->writeStartElement(dbNamespace, noItemsHaveTitle ?
"itemizedlist" :
"variablelist");
1395 m_writer->writeAttribute(
"role", selector);
1399 if (sortOrder == Qt::DescendingOrder)
1403 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1404 for (
const auto &node : std::as_const(members)) {
1405 const NodeContext context = node->createContext();
1406 if (!InclusionFilter::isIncluded(policy, context) || node->isDeprecated())
1409 if (noItemsHaveTitle) {
1410 m_writer->writeStartElement(dbNamespace,
"listitem");
1412 m_writer->writeStartElement(dbNamespace,
"para");
1414 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1416 m_writer->writeStartElement(dbNamespace,
"term");
1418 generateFullName(node, relative);
1419 if (noItemsHaveTitle) {
1420 m_writer->writeEndElement();
1422 m_writer->writeEndElement();
1424 m_writer->writeEndElement();
1426 m_writer->writeStartElement(dbNamespace,
"listitem");
1428 m_writer->writeStartElement(dbNamespace,
"para");
1429 m_writer->writeCharacters(node->doc().briefText().toString());
1430 m_writer->writeEndElement();
1432 m_writer->writeEndElement();
1434 m_writer->writeEndElement();
1439 m_writer->writeEndElement();
1443 if (type == AutoSection && m_hasSection)
1448
1449
1450
1452 const QString &selector)
1455 for (
const QString &name : nmm.uniqueKeys()) {
1456 if (!name.isEmpty())
1457 startSection(name.toLower(), name);
1458 generateAnnotatedList(relative, nmm.values(name), selector);
1459 if (!name.isEmpty())
1465
1466
1467
1468
1469
1470
1471
1472
1473
1475 bool includeAlphabet,
const QString &commonPrefix,
1476 const QString &selector)
1486 const int NumParagraphs = 37;
1487 qsizetype commonPrefixLen = commonPrefix.size();
1490
1491
1492
1493
1494
1496 QString paragraphName[NumParagraphs + 1];
1497 QSet<
char> usedParagraphNames;
1499 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
1500 QStringList pieces = c.key().split(
"::");
1501 int idx = commonPrefixLen;
1502 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
1504 QString last = pieces.last().toLower();
1505 QString key = last.mid(idx);
1507 int paragraphNr = NumParagraphs - 1;
1509 if (key[0].digitValue() != -1) {
1510 paragraphNr = key[0].digitValue();
1511 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
1512 paragraphNr = 10 + key[0].unicode() -
'a';
1515 paragraphName[paragraphNr] = key[0].toUpper();
1516 usedParagraphNames.insert(key[0].toLower().cell());
1517 paragraph[paragraphNr].insert(last, c.value());
1521
1522
1523
1524
1525
1526
1527
1528 int paragraphOffset[NumParagraphs + 1];
1529 paragraphOffset[0] = 0;
1530 for (
int i = 0; i < NumParagraphs; i++)
1531 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
1534 if (includeAlphabet && !usedParagraphNames.isEmpty()) {
1535 m_writer->writeStartElement(dbNamespace,
"simplelist");
1538 for (
int i = 0; i < 26; i++) {
1540 if (usedParagraphNames.contains(
char(
'a' + i))) {
1541 m_writer->writeStartElement(dbNamespace,
"member");
1542 generateSimpleLink(ch, ch.toUpper());
1543 m_writer->writeEndElement();
1548 m_writer->writeEndElement();
1553 QHash<QString,
int> nameOccurrences;
1554 for (
const auto &[key, node] : nmm.asKeyValueRange()) {
1555 QStringList pieces{node->fullName(relative).split(
"::"_L1)};
1556 const QString &name{pieces.last()};
1557 nameOccurrences[name]++;
1562 int curParOffset = 0;
1564 m_writer->writeStartElement(dbNamespace,
"variablelist");
1565 m_writer->writeAttribute(
"role", selector);
1568 for (
int i = 0; i < nmm.size(); i++) {
1569 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
1576 if (curParOffset == 0) {
1578 m_writer->writeEndElement();
1580 m_writer->writeEndElement();
1582 m_writer->writeEndElement();
1586 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1587 if (includeAlphabet)
1588 writeXmlId(paragraphName[curParNr][0].toLower());
1591 m_writer->writeStartElement(dbNamespace,
"term");
1592 m_writer->writeStartElement(dbNamespace,
"emphasis");
1593 m_writer->writeAttribute(
"role",
"bold");
1594 m_writer->writeCharacters(paragraphName[curParNr]);
1595 m_writer->writeEndElement();
1596 m_writer->writeEndElement();
1599 m_writer->writeStartElement(dbNamespace,
"listitem");
1601 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1606 m_writer->writeStartElement(dbNamespace,
"listitem");
1608 m_writer->writeStartElement(dbNamespace,
"para");
1610 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
1611 NodeMultiMap::Iterator it;
1612 NodeMultiMap::Iterator next;
1613 it = paragraph[curParNr].begin();
1614 for (
int j = 0; j < curParOffset; j++)
1619 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
1620 const auto &name{pieces.last()};
1623 if (nameOccurrences[name] > 1) {
1624 const QString moduleName = it.value()->isQmlNode() ? it.value()->logicalModuleName()
1625 : it.value()->tree()->camelCaseModuleName();
1626 pieces.last().append(
": %1"_L1.arg(moduleName));
1630 m_writer->writeStartElement(dbNamespace,
"link");
1631 m_writer->writeAttribute(xlinkNamespace,
"href", linkForNode(*it, relative));
1632 if (
const QString type = targetType(it.value()); !type.isEmpty())
1633 m_writer->writeAttribute(
"role", type);
1634 m_writer->writeCharacters(pieces.last());
1635 m_writer->writeEndElement();
1638 if (pieces.size() > 1) {
1639 m_writer->writeCharacters(
" (");
1640 generateFullName(it.value()->parent(), relative);
1641 m_writer->writeCharacters(
")");
1645 m_writer->writeEndElement();
1647 m_writer->writeEndElement();
1652 m_writer->writeEndElement();
1654 m_writer->writeEndElement();
1656 m_writer->writeEndElement();
1659 m_writer->writeEndElement();
1668 m_writer->writeStartElement(dbNamespace,
"simplelist");
1669 m_writer->writeAttribute(
"role",
"functionIndex");
1671 for (
int i = 0; i < 26; i++) {
1673 m_writer->writeStartElement(dbNamespace,
"member");
1674 m_writer->writeAttribute(xlinkNamespace,
"href", QString(
"#") + ch);
1675 m_writer->writeCharacters(ch.toUpper());
1676 m_writer->writeEndElement();
1679 m_writer->writeEndElement();
1684 if (m_qdb->getFunctionIndex().isEmpty())
1686 char nextLetter =
'a';
1689 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1692 NodeMapMap &funcIndex = m_qdb->getFunctionIndex();
1693 QMap<QString, NodeMap>::ConstIterator f = funcIndex.constBegin();
1694 while (f != funcIndex.constEnd()) {
1695 m_writer->writeStartElement(dbNamespace,
"listitem");
1697 m_writer->writeStartElement(dbNamespace,
"para");
1698 m_writer->writeCharacters(f.key() +
": ");
1700 currentLetter = f.key()[0].unicode();
1701 while (islower(currentLetter) && currentLetter >= nextLetter) {
1702 writeAnchor(QString(nextLetter));
1706 NodeMap::ConstIterator s = (*f).constBegin();
1707 while (s != (*f).constEnd()) {
1708 m_writer->writeCharacters(
" ");
1709 generateFullName((*s)->parent(), relative);
1713 m_writer->writeEndElement();
1715 m_writer->writeEndElement();
1719 m_writer->writeEndElement();
1727 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
1728 Text text = it.key();
1730 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1733 m_writer->writeStartElement(dbNamespace,
"listitem");
1735 m_writer->writeStartElement(dbNamespace,
"para");
1736 generateFullName(it.value(), relative);
1737 m_writer->writeEndElement();
1739 m_writer->writeEndElement();
1742 }
while (it != legaleseTexts.constEnd() && it.key() == text);
1743 m_writer->writeEndElement();
1758 m_writer->writeStartElement(dbNamespace,
"para");
1760 m_writer->writeEndElement();
1768 if (!node->since().isEmpty()) {
1769 m_writer->writeStartElement(dbNamespace,
"para");
1771 const auto &collective =
static_cast<
const SharedCommentNode *>(node)->collective();
1772 QString typeStr = collective.size() > 1 ? typeString(collective.first()) +
"s" : typeString(node);
1773 m_writer->writeCharacters(
"These " + typeStr +
" were introduced in ");
1775 m_writer->writeCharacters(
"This " + typeString(node) +
" was introduced in ");
1777 m_writer->writeCharacters(formatSince(node) +
".");
1778 m_writer->writeEndElement();
1788
1789
1790
1796 if (!subTitle.isEmpty()) {
1797 m_writer->writeStartElement(dbNamespace,
"subtitle");
1798 if (isApiGenus(node->genus()) && m_useITS)
1799 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1800 m_writer->writeCharacters(subTitle);
1801 m_writer->writeEndElement();
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1824 m_writer->writeStartElement(dbNamespace,
"info");
1826 m_writer->writeStartElement(dbNamespace,
"title");
1827 if (isApiGenus(node->genus()) && m_useITS)
1828 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1830 m_writer->writeEndElement();
1835
1836
1837
1838
1839
1842 if (!m_productName.isEmpty() || !m_project.isEmpty()) {
1843 m_writer->writeTextElement(dbNamespace,
"productname", m_productName.isEmpty() ?
1844 m_project : m_productName);
1848 if (!m_buildVersion.isEmpty()) {
1849 m_writer->writeTextElement(dbNamespace,
"edition", m_buildVersion);
1853 if (!m_projectDescription.isEmpty()) {
1854 m_writer->writeTextElement(dbNamespace,
"titleabbrev", m_projectDescription);
1862 if (node && !node->links().empty()) {
1863 std::pair<QString, QString> linkPair;
1864 std::pair<QString, QString> anchorPair;
1865 const Node *linkNode;
1867 if (node->links().contains(Node::PreviousLink)) {
1868 linkPair = node->links()[Node::PreviousLink];
1869 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1870 if (!linkNode || linkNode == node)
1871 anchorPair = linkPair;
1873 anchorPair = anchorForNode(linkNode);
1875 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1876 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1877 m_writer->writeEmptyElement(dbNamespace,
"link");
1878 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1879 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1880 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"prev");
1881 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1882 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1884 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1885 m_writer->writeEndElement();
1888 if (node->links().contains(Node::NextLink)) {
1889 linkPair = node->links()[Node::NextLink];
1890 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1891 if (!linkNode || linkNode == node)
1892 anchorPair = linkPair;
1894 anchorPair = anchorForNode(linkNode);
1896 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1897 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1898 m_writer->writeEmptyElement(dbNamespace,
"link");
1899 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1900 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1901 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"next");
1902 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1903 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1905 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1906 m_writer->writeEndElement();
1909 if (node->links().contains(Node::StartLink)) {
1910 linkPair = node->links()[Node::StartLink];
1911 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1912 if (!linkNode || linkNode == node)
1913 anchorPair = linkPair;
1915 anchorPair = anchorForNode(linkNode);
1917 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1918 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1919 m_writer->writeEmptyElement(dbNamespace,
"link");
1920 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1921 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1922 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"start");
1923 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1924 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1926 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1927 m_writer->writeEndElement();
1939 m_writer->writeStartElement(dbNamespace,
"abstract");
1942 bool generatedSomething =
false;
1946 node->isNamespace() ?
static_cast<
const NamespaceNode *>(node) :
nullptr;
1949 brief <<
"The " << ns->name()
1950 <<
" namespace includes the following elements from module "
1951 << ns
->tree()->camelCaseModuleName() <<
". The full namespace is "
1952 <<
"documented in module " << NS
->tree()->camelCaseModuleName();
1953 addNodeLink(brief, fullDocumentLocation(NS),
" here.");
1962 m_writer->writeStartElement(dbNamespace,
"para");
1964 m_writer->writeEndElement();
1967 generatedSomething =
true;
1977 if (!generatedSomething)
1978 m_writer->writeTextElement(dbNamespace,
"para", m_projectDescription +
".");
1980 m_writer->writeEndElement();
1985 m_writer->writeEndElement();
1991 while (!sectionLevels.isEmpty()) {
1992 sectionLevels.pop();
1999 if (m_closeSectionAfterGeneratedList) {
2000 m_closeSectionAfterGeneratedList =
false;
2003 if (m_closeSectionAfterRawTitle) {
2004 m_closeSectionAfterRawTitle =
false;
2009 m_writer->writeEndElement();
2012void DocBookGenerator::generateSimpleLink(
const QString &href,
const QString &text)
2014 m_writer->writeStartElement(dbNamespace,
"link");
2015 m_writer->writeAttribute(xlinkNamespace,
"href", href);
2016 m_writer->writeCharacters(text);
2017 m_writer->writeEndElement();
2021
2022
2023
2026 static const QHash<QString, QString> extrefUrls = {
2027 {u"cpp-explicitly-defaulted"_s,
2028 u"https://en.cppreference.com/w/cpp/language/function#Defaulted_functions"_s},
2029 {u"cpp-deleted-functions"_s,
2030 u"https://en.cppreference.com/w/cpp/language/function#Deleted_functions"_s},
2033 static const QRegularExpression extrefRegex(
2034 u"<@extref target=\"([^\"]+)\">([^<]*)</@extref>"_s);
2037 auto it = extrefRegex.globalMatch(extra);
2038 while (it.hasNext()) {
2039 auto match = it.next();
2040 if (match.capturedStart() > pos)
2041 m_writer->writeCharacters(extra.mid(pos, match.capturedStart() - pos));
2043 QString target = match.captured(1);
2044 QString text = match.captured(2);
2045 QString url = extrefUrls.value(target);
2047 generateSimpleLink(url, text);
2049 m_writer->writeCharacters(text);
2051 pos = match.capturedEnd();
2053 if (pos < extra.size())
2054 m_writer->writeCharacters(extra.mid(pos));
2066 startSection(
"obsolete",
"Obsolete Members for " + aggregate->plainFullName());
2068 m_writer->writeStartElement(dbNamespace,
"para");
2069 m_writer->writeStartElement(dbNamespace,
"emphasis");
2070 m_writer->writeAttribute(
"role",
"bold");
2071 m_writer->writeCharacters(
"The following members of class ");
2072 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2073 m_writer->writeCharacters(
" are deprecated.");
2074 m_writer->writeEndElement();
2075 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2076 m_writer->writeEndElement();
2079 for (
const Section *section : details_spv) {
2080 const QString &title =
"Obsolete " + section->title();
2081 startSection(title.toLower(), title);
2083 const NodeVector &members = section->obsoleteMembers();
2084 NodeVector::ConstIterator m = members.constBegin();
2085 while (m != members.constEnd()) {
2086 if ((*m)->access() != Access::Private)
2087 generateDetailedMember(*m, aggregate);
2098
2099
2100
2101
2102
2103
2104
2114 startSection(
"obsolete",
"Obsolete Members for " + aggregate->name());
2116 m_writer->writeStartElement(dbNamespace,
"para");
2117 m_writer->writeStartElement(dbNamespace,
"emphasis");
2118 m_writer->writeAttribute(
"role",
"bold");
2119 m_writer->writeCharacters(
"The following members of QML type ");
2120 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2121 m_writer->writeCharacters(
" are deprecated.");
2122 m_writer->writeEndElement();
2123 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2124 m_writer->writeEndElement();
2127 for (
const auto *section : details_spv) {
2128 const QString &title =
"Obsolete " + section->title();
2129 startSection(title.toLower(), title);
2131 const NodeVector &members = section->obsoleteMembers();
2132 NodeVector::ConstIterator m = members.constBegin();
2133 while (m != members.constEnd()) {
2134 if ((*m)->access() != Access::Private)
2135 generateDetailedQmlMember(*m, aggregate);
2149 return QStringLiteral(
"classsynopsis");
2151 return QStringLiteral(
"packagesynopsis");
2157 return QStringLiteral(
"enumsynopsis");
2159 return QStringLiteral(
"typedefsynopsis");
2162 const auto fn =
static_cast<
const FunctionNode *>(node);
2163 if (fn->isCtor() || fn->isCCtor() || fn->isMCtor())
2164 return QStringLiteral(
"constructorsynopsis");
2166 return QStringLiteral(
"destructorsynopsis");
2167 return QStringLiteral(
"methodsynopsis");
2170 return QStringLiteral(
"fieldsynopsis");
2172 node
->doc().location().warning(QString(
"Unknown node tag %1").arg(node->nodeTypeString()));
2173 return QStringLiteral(
"synopsis");
2178 m_writer->writeStartElement(dbNamespace,
"varlistentry");
2180 m_writer->writeTextElement(dbNamespace,
"term", description);
2182 m_writer->writeStartElement(dbNamespace,
"listitem");
2184 m_writer->writeStartElement(dbNamespace,
"para");
2190 m_writer->writeEndElement();
2193 m_writer->writeEndElement();
2195 m_writer->writeEndElement();
2199void DocBookGenerator::generateRequisite(
const QString &description,
const QString &value)
2201 generateStartRequisite(description);
2202 m_writer->writeCharacters(value);
2203 generateEndRequisite();
2207
2208
2209
2210void DocBookGenerator::generateCMakeRequisite(
const QString &findPackage,
const QString &linkLibraries)
2212 const QString description(
"CMake");
2213 generateStartRequisite(description);
2214 m_writer->writeCharacters(findPackage);
2215 m_writer->writeEndElement();
2218 m_writer->writeStartElement(dbNamespace,
"para");
2219 m_writer->writeCharacters(linkLibraries);
2220 generateEndRequisite();
2226 QMap<QString, ClassNode *> classMap;
2227 QList<RelatedClass>::ConstIterator r = rc.constBegin();
2228 while (r != rc.constEnd()) {
2231 && !rcn
->doc().isEmpty()) {
2232 classMap[rcn->plainFullName(cn).toLower()] = rcn;
2237 QStringList classNames = classMap.keys();
2241 for (
const QString &className : classNames) {
2242 generateFullName(classMap.value(className), cn);
2243 m_writer->writeCharacters(TextUtils::comma(index++, classNames.size()));
2251 QMap<QString, Node *> classMap;
2252 QStringList typeNames(knownTypes);
2253 for (
const auto sub : subs)
2254 typeNames << sub->name();
2256 for (
auto sub : subs) {
2257 QString key{sub->plainFullName(base).toLower()};
2259 if (typeNames.count(sub->name()) > 1)
2260 key.append(
": (%1)"_L1.arg(sub->logicalModuleName()));
2261 classMap[key] = sub;
2264 QStringList names = classMap.keys();
2268 for (
const QString &name : names) {
2269 generateFullName(classMap.value(name), base);
2270 if (name.contains(
':'))
2271 m_writer->writeCharacters(name.section(
':', 1));
2272 m_writer->writeCharacters(TextUtils::comma(index++, names.size()));
2277
2278
2287 QXmlStreamWriter* oldWriter = m_writer;
2289 m_writer =
new QXmlStreamWriter(&output);
2292 if (aggregate->includeFile()) generateRequisite(
"Header", *aggregate->includeFile());
2295 if (!aggregate->since().isEmpty())
2296 generateRequisite(
"Since", formatSince(aggregate));
2301 m_qdb->getCollectionNode(aggregate->physicalModuleName(), NodeType::Module);
2303 if (
const auto result = cmakeRequisite(cn)) {
2304 generateCMakeRequisite(result->first, result->second);
2307 if (cn && !cn->qtVariable().isEmpty())
2308 generateRequisite(
"qmake",
"QT += " + cn->qtVariable());
2313 auto *classe =
const_cast<ClassNode *>(
static_cast<
const ClassNode *>(aggregate));
2314 if (classe && classe->isQmlNativeType() && !classe->isInternal()) {
2315 generateStartRequisite(
"In QML");
2318 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2321 for (
const auto &item : std::as_const(nativeTypes)) {
2322 generateFullName(item, classe);
2323 m_writer->writeCharacters(
2324 TextUtils::comma(idx++, nativeTypes.size()));
2326 generateEndRequisite();
2330 QList<RelatedClass>::ConstIterator r;
2331 const auto *metaTags = classe ? classe->doc().metaTagMap() :
nullptr;
2332 bool suppressInherits = metaTags && metaTags->contains(u"qdoc-suppress-inheritance"_s);
2333 if (classe && !suppressInherits && !classe->baseClasses().isEmpty()) {
2334 generateStartRequisite(
"Inherits");
2336 r = classe->baseClasses().constBegin();
2338 while (r != classe->baseClasses().constEnd()) {
2340 generateFullName((*r).m_node, classe);
2342 if ((*r).m_access == Access::Protected)
2343 m_writer->writeCharacters(
" (protected)");
2344 else if ((*r).m_access == Access::Private)
2345 m_writer->writeCharacters(
" (private)");
2346 m_writer->writeCharacters(
2347 TextUtils::comma(index++, classe->baseClasses().size()));
2352 generateEndRequisite();
2356 if (!classe->derivedClasses().isEmpty()) {
2357 generateStartRequisite(
"Inherited By");
2358 generateSortedNames(classe, classe->derivedClasses());
2359 generateEndRequisite();
2364 if (!aggregate->groupNames().empty()) {
2365 generateStartRequisite(
"Group");
2367 generateEndRequisite();
2371 if (
auto status = formatStatus(aggregate, m_qdb); status)
2372 generateRequisite(
"Status", status.value());
2376 m_writer = oldWriter;
2378 if (!output.isEmpty()) {
2381 static const QRegularExpression xmlTag(R"(<(/?)n\d+:)");
2382 static const QRegularExpression xmlnsDocBookDefinition(R"( xmlns:n\d+=")" + QString{dbNamespace} +
"\"");
2383 static const QRegularExpression xmlnsXLinkDefinition(R"( xmlns:n\d+=")" + QString{xlinkNamespace} +
"\"");
2384 static const QRegularExpression xmlAttr(R"( n\d+:)");
2386 const QString cleanOutput = output.replace(xmlTag, R"(<\1db:)")
2387 .replace(xmlnsDocBookDefinition,
"")
2388 .replace(xmlnsXLinkDefinition,
"")
2389 .replace(xmlAttr,
" xlink:");
2391 m_writer->writeStartElement(dbNamespace,
"variablelist");
2393 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2396 m_writer->device()->write(cleanOutput.toUtf8());
2398 m_writer->writeEndElement();
2404
2405
2413 const QString importText =
"Import Statement";
2414 const QString sinceText =
"Since";
2415 const QString inheritedByText =
"Inherited By";
2416 const QString inheritsText =
"Inherits";
2417 const QString nativeTypeText =
"In C++";
2418 const QString groupText =
"Group";
2419 const QString statusText =
"Status";
2427 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2436 bool generate_import_statement = !qcn->logicalModuleName().isEmpty();
2437 if (generate_import_statement && collection) {
2442 const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base;
2444 if (!generates_something)
2447 QStringList knownTypeNames{qcn->name()};
2449 knownTypeNames << base->name();
2452 m_writer->writeStartElement(dbNamespace,
"variablelist");
2454 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2457 if (generate_import_statement) {
2458 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2459 generateRequisite(importText, parts.join(
' ').trimmed());
2463 if (!qcn->since().isEmpty())
2464 generateRequisite(sinceText, formatSince(qcn));
2469 generateStartRequisite(nativeTypeText);
2470 generateSimpleLink(fullDocumentLocation(cn), cn->name());
2471 generateEndRequisite();
2476 generateStartRequisite(inheritsText);
2477 generateSimpleLink(fullDocumentLocation(base), base->name());
2479 for (
const auto sub : std::as_const(subs)) {
2480 if (knownTypeNames.contains(sub->name())) {
2481 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
2485 generateEndRequisite();
2489 if (!subs.isEmpty()) {
2490 generateStartRequisite(inheritedByText);
2491 generateSortedQmlNames(qcn, knownTypeNames, subs);
2492 generateEndRequisite();
2496 if (!qcn->groupNames().empty()) {
2497 generateStartRequisite(groupText);
2499 generateEndRequisite();
2503 if (
auto status = formatStatus(qcn, m_qdb); status)
2504 generateRequisite(statusText, status.value());
2506 m_writer->writeEndElement();
2517 const QString &state =
static_cast<
const CollectionNode*>(node)->state();
2518 if (!state.isEmpty()) {
2519 m_writer->writeStartElement(dbNamespace,
"para");
2520 m_writer->writeCharacters(
"This " + typeString(node) +
" is in ");
2521 m_writer->writeStartElement(dbNamespace,
"emphasis");
2522 m_writer->writeCharacters(state);
2523 m_writer->writeEndElement();
2524 m_writer->writeCharacters(
" state.");
2525 m_writer->writeEndElement();
2530 if (
const auto &version = node->deprecatedSince(); !version.isEmpty()) {
2531 m_writer->writeStartElement(dbNamespace,
"para");
2532 m_writer->writeCharacters(
"This " + typeString(node)
2533 +
" is scheduled for deprecation in version "
2535 m_writer->writeEndElement();
2540 case Status::Preliminary:
2541 m_writer->writeStartElement(dbNamespace,
"para");
2542 m_writer->writeStartElement(dbNamespace,
"emphasis");
2543 m_writer->writeAttribute(
"role",
"bold");
2544 m_writer->writeCharacters(
2548 .replace(
'\1'_L1, typeString(node)));
2549 m_writer->writeEndElement();
2550 m_writer->writeEndElement();
2553 case Status::Deprecated:
2554 m_writer->writeStartElement(dbNamespace,
"para");
2556 m_writer->writeStartElement(dbNamespace,
"emphasis");
2557 m_writer->writeAttribute(
"role",
"bold");
2559 m_writer->writeCharacters(
"This " + typeString(node) +
" is deprecated");
2560 if (
const QString &version = node->deprecatedSince(); !version.isEmpty()) {
2561 m_writer->writeCharacters(
" since ");
2562 if (node->isQmlNode() && !node->logicalModuleName().isEmpty())
2563 m_writer->writeCharacters(node->logicalModuleName() +
" ");
2564 m_writer->writeCharacters(version);
2566 m_writer->writeCharacters(
". We strongly advise against using it in new code.");
2567 if (node->isAggregate())
2568 m_writer->writeEndElement();
2569 m_writer->writeEndElement();
2580
2581
2582
2586 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2589 NodeList::ConstIterator n = nodes.constBegin();
2590 while (n != nodes.constEnd()) {
2591 m_writer->writeStartElement(dbNamespace,
"listitem");
2593 m_writer->writeStartElement(dbNamespace,
"para");
2595 generateSimpleLink(currentGenerator()->fullDocumentLocation(*n),
2596 (*n)->signature(Node::SignaturePlain));
2598 m_writer->writeEndElement();
2600 m_writer->writeEndElement();
2605 m_writer->writeEndElement();
2610
2611
2612
2619 const auto aggregate =
static_cast<
const Aggregate *>(node);
2621 const QStringList &groups_names{aggregate->groupNames()};
2622 if (!groups_names.empty()) {
2623 m_writer->writeCharacters(aggregate->name() +
" is part of ");
2624 m_writer->writeStartElement(dbNamespace,
"simplelist");
2626 for (qsizetype index{0}; index < groups_names.size(); ++index) {
2628 m_qdb->mergeCollections(group);
2630 m_writer->writeStartElement(dbNamespace,
"member");
2631 if (QString target{linkForNode(group,
nullptr)}; !target.isEmpty())
2632 generateSimpleLink(target, group->fullTitle());
2634 m_writer->writeCharacters(group->name());
2635 m_writer->writeEndElement();
2638 m_writer->writeEndElement();
2644
2645
2646
2652 const Node *reentrantNode;
2654 QString linkReentrant = getAutoLink(&reentrantAtom, node, &reentrantNode);
2655 const Node *threadSafeNode;
2657 QString linkThreadSafe = getAutoLink(&threadSafeAtom, node, &threadSafeNode);
2660 m_writer->writeStartElement(dbNamespace,
"warning");
2662 m_writer->writeStartElement(dbNamespace,
"para");
2663 m_writer->writeCharacters(
"This " + typeString(node) +
" is not ");
2664 generateSimpleLink(linkReentrant,
"reentrant");
2665 m_writer->writeCharacters(
".");
2666 m_writer->writeEndElement();
2668 m_writer->writeEndElement();
2672 m_writer->writeStartElement(dbNamespace,
"note");
2674 m_writer->writeStartElement(dbNamespace,
"para");
2677 m_writer->writeCharacters(
"All functions in this " + typeString(node) +
" are ");
2678 if (ts == Node::ThreadSafe)
2679 generateSimpleLink(linkThreadSafe,
"thread-safe");
2681 generateSimpleLink(linkReentrant,
"reentrant");
2686 bool exceptions = hasExceptions(node, reentrant, threadsafe, nonreentrant);
2687 if (!exceptions || (ts ==
Node::Reentrant && !threadsafe.isEmpty())) {
2688 m_writer->writeCharacters(
".");
2689 m_writer->writeEndElement();
2692 m_writer->writeCharacters(
" with the following exceptions:");
2693 m_writer->writeEndElement();
2695 m_writer->writeStartElement(dbNamespace,
"para");
2698 if (!nonreentrant.isEmpty()) {
2699 m_writer->writeCharacters(
"These functions are not ");
2700 generateSimpleLink(linkReentrant,
"reentrant");
2701 m_writer->writeCharacters(
":");
2702 m_writer->writeEndElement();
2704 generateSignatureList(nonreentrant);
2706 if (!threadsafe.isEmpty()) {
2707 m_writer->writeCharacters(
"These functions are also ");
2708 generateSimpleLink(linkThreadSafe,
"thread-safe");
2709 m_writer->writeCharacters(
":");
2710 m_writer->writeEndElement();
2712 generateSignatureList(threadsafe);
2715 if (!reentrant.isEmpty()) {
2716 m_writer->writeCharacters(
"These functions are only ");
2717 generateSimpleLink(linkReentrant,
"reentrant");
2718 m_writer->writeCharacters(
":");
2719 m_writer->writeEndElement();
2721 generateSignatureList(reentrant);
2723 if (!nonreentrant.isEmpty()) {
2724 m_writer->writeCharacters(
"These functions are not ");
2725 generateSimpleLink(linkReentrant,
"reentrant");
2726 m_writer->writeCharacters(
":");
2727 m_writer->writeEndElement();
2729 generateSignatureList(nonreentrant);
2734 m_writer->writeCharacters(
"This " + typeString(node) +
" is ");
2735 if (ts == Node::ThreadSafe)
2736 generateSimpleLink(linkThreadSafe,
"thread-safe");
2738 generateSimpleLink(linkReentrant,
"reentrant");
2739 m_writer->writeCharacters(
".");
2740 m_writer->writeEndElement();
2743 m_writer->writeEndElement();
2753
2754
2755
2759 const FunctionNode *fn = node->isFunction() ?
static_cast<
const FunctionNode *>(node) :
nullptr;
2763
2764
2765
2769 t =
"Destroys the instance of " + fn
->parent()->name() +
".";
2771 t +=
" The destructor is virtual.";
2773 t =
"Default constructs an instance of " + fn
->parent()->name() +
".";
2775 t =
"Copy constructor.";
2777 t =
"Move-copy constructor.";
2779 t =
"Copy-assignment constructor.";
2781 t =
"Move-assignment constructor.";
2785 m_writer->writeTextElement(dbNamespace,
"para", t);
2789 if (fn && !fn->overridesThis().isEmpty())
2790 generateReimplementsClause(fn);
2792 if (
static_cast<
const PropertyNode *>(node)->propertyType() != PropertyNode::PropertyType::StandardProperty)
2821 generateRequiredLinks(node);
2825
2826
2827
2828
2829
2836 const auto en =
static_cast<
const ExampleNode *>(node);
2839 if (exampleUrl.isEmpty()) {
2840 if (!en->noAutoList()) {
2841 generateFileList(en,
false);
2842 generateFileList(en,
true);
2845 generateLinkToExample(en, exampleUrl);
2850
2851
2852
2853
2854
2858 QString exampleUrl(baseUrl);
2860#ifndef QT_BOOTSTRAPPED
2861 link = QUrl(exampleUrl).host();
2863 if (!link.isEmpty())
2864 link.prepend(
" @ ");
2865 link.prepend(
"Example project");
2867 const QLatin1Char separator(
'/');
2868 const QLatin1Char placeholder(
'\1');
2869 if (!exampleUrl.contains(placeholder)) {
2870 if (!exampleUrl.endsWith(separator))
2871 exampleUrl += separator;
2872 exampleUrl += placeholder;
2876 QStringList path = QStringList()
2878 path.removeAll(QString());
2882 startSection(
"Example project");
2884 m_writer->writeStartElement(dbNamespace,
"para");
2885 generateSimpleLink(exampleUrl.replace(placeholder, path.join(separator)), link);
2886 m_writer->writeEndElement();
2895
2896
2897
2898
2899
2900
2916 paths = en->images();
2919 paths = en->files();
2922 std::sort(paths.begin(), paths.end(), Generator::comparePaths);
2924 if (paths.isEmpty())
2927 startSection(
"",
"List of Files");
2929 m_writer->writeStartElement(dbNamespace,
"para");
2930 m_writer->writeCharacters(tag);
2931 m_writer->writeEndElement();
2934 startSection(
"List of Files");
2936 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2939 for (
const auto &path : std::as_const(paths)) {
2940 auto maybe_resolved_file{file_resolver.resolve(path)};
2941 if (!maybe_resolved_file) {
2943 QString details = std::transform_reduce(
2944 file_resolver.get_search_directories().cbegin(),
2945 file_resolver.get_search_directories().cend(),
2946 u"Searched directories:"_s,
2948 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
2951 en->location().warning(u"Cannot find file to quote from: %1"_s.arg(path), details);
2956 const auto &file{*maybe_resolved_file};
2957 if (images) addImageToCopy(en, file);
2958 else generateExampleFilePage(en, file);
2960 m_writer->writeStartElement(dbNamespace,
"listitem");
2962 m_writer->writeStartElement(dbNamespace,
"para");
2963 generateSimpleLink(file.get_query(), file.get_query());
2964 m_writer->writeEndElement();
2965 m_writer->writeEndElement();
2969 m_writer->writeEndElement();
2976
2977
2987 const auto en =
static_cast<
const ExampleNode *>(node);
2990 QXmlStreamWriter *currentWriter = m_writer;
2991 m_writer = startDocument(en, resolved_file.get_query());
2997 QString code = quoter.quoteTo(en->location(), QString(), QString());
2998 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
3004 m_writer = currentWriter;
3010 if (fn->overridesThis().isEmpty() || !fn
->parent()->isClassNode())
3015 if (
const FunctionNode *overrides = cn->findOverriddenFunction(fn);
3018 m_writer->writeStartElement(dbNamespace,
"para");
3019 m_writer->writeCharacters(
"Reimplements: ");
3022 generateFullName(overrides
->parent(), fullName, overrides);
3023 m_writer->writeCharacters(
".");
3024 m_writer->writeEndElement();
3030 if (
const PropertyNode *sameName = cn->findOverriddenProperty(fn); sameName && sameName
->hasDoc()) {
3031 m_writer->writeStartElement(dbNamespace,
"para");
3032 m_writer->writeCharacters(
"Reimplements an access function for property: ");
3033 QString fullName = sameName
->parent()->name() +
"::" + sameName->name();
3034 generateFullName(sameName
->parent(), fullName, sameName);
3035 m_writer->writeCharacters(
".");
3036 m_writer->writeEndElement();
3045 QList<Text> alsoList = node
->doc().alsoList();
3046 supplementAlsoList(node, alsoList);
3048 if (!alsoList.isEmpty()) {
3049 startSection(
"See Also");
3051 m_writer->writeStartElement(dbNamespace,
"para");
3052 m_writer->writeStartElement(dbNamespace,
"emphasis");
3053 m_writer->writeCharacters(
"See also ");
3054 m_writer->writeEndElement();
3057 m_writer->writeStartElement(dbNamespace,
"simplelist");
3058 m_writer->writeAttribute(
"type",
"vert");
3059 m_writer->writeAttribute(
"role",
"see-also");
3062 for (
const Text &text : alsoList) {
3063 m_writer->writeStartElement(dbNamespace,
"member");
3064 generateText(text, node);
3065 m_writer->writeEndElement();
3069 m_writer->writeEndElement();
3072 m_writer->writeEndElement();
3080
3081
3082
3083QXmlStreamWriter *
DocBookGenerator::startGenericDocument(
const Node *node,
const QString &fileName)
3086 QFile *outFile = openSubPageFile(
static_cast<
const PageNode*>(node), fileName);
3087 m_writer =
new QXmlStreamWriter(outFile);
3088 m_writer->setAutoFormatting(
false);
3090 m_writer->writeStartDocument();
3092 m_writer->writeNamespace(dbNamespace,
"db");
3093 m_writer->writeNamespace(xlinkNamespace,
"xlink");
3095 m_writer->writeNamespace(itsNamespace,
"its");
3096 m_writer->writeStartElement(dbNamespace,
"article");
3097 m_writer->writeAttribute(
"version",
"5.2");
3098 if (!m_naturalLanguage.isEmpty())
3099 m_writer->writeAttribute(
"xml:lang", m_naturalLanguage);
3103 sectionLevels.resize(0);
3112 m_hasSection =
false;
3115 QString fileName = Generator::fileName(node, fileExtension());
3116 return startGenericDocument(node, fileName);
3121 m_hasSection =
false;
3123 QString fileName = linkForExampleFile(file);
3124 return startGenericDocument(en, fileName);
3129 m_writer->writeEndElement();
3130 m_writer->writeEndDocument();
3132 m_writer->device()->close();
3133 delete m_writer->device();
3139
3140
3141
3146 const auto aggregate =
static_cast<
const Aggregate *>(node);
3150 const QString typeWord{aggregate->typeWord(
true)};
3151 if (aggregate->isNamespace()) {
3152 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3153 }
else if (aggregate->isClass()) {
3154 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3155 }
else if (aggregate->isHeader()) {
3156 title = aggregate->fullTitle();
3157 if (!aggregate->doc().title().isEmpty())
3158 titleText << aggregate->name() <<
" - "_L1 << aggregate->doc().title();
3162 m_writer = startDocument(node);
3168 if (aggregate->isClass()) {
3169 if (
auto templateDecl = node->templateDecl()) {
3175 m_writer->writeStartElement(dbNamespace,
"subtitle");
3176 if (isApiGenus(aggregate->genus()) && m_useITS)
3177 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
3178 generateTemplateDecl(&*templateDecl, aggregate);
3179 m_writer->writeCharacters(
" "_L1 + aggregate->typeWord(
false) +
" "_L1
3180 + aggregate->plainFullName());
3181 m_writer->writeEndElement();
3205 if (!aggregate->doc().isEmpty()) {
3206 startSection(
"details",
"Detailed Description");
3208 generateBody(aggregate);
3216 for (
const Section §ion : sectionVector) {
3217 if (section.members().isEmpty())
3220 startSection(section.title().toLower(), section.title());
3222 for (
const Node *member : section.members()) {
3223 if (member->nodeType() != NodeType::Class) {
3225 generateDetailedMember(member, aggregate);
3227 startSectionBegin();
3228 m_writer->writeCharacters(
"class ");
3229 generateFullName(member, aggregate);
3232 generateBrief(member);
3241 generateObsoleteMembers(sections);
3246void DocBookGenerator::generateSynopsisInfo(
const QString &key,
const QString &value)
3248 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3249 m_writer->writeAttribute(
"role", key);
3250 m_writer->writeCharacters(value);
3251 m_writer->writeEndElement();
3257 m_writer->writeTextElement(dbNamespace,
"modifier", value);
3262
3263
3273 if (!m_useDocBook52)
3283 node->isAggregate() ?
static_cast<
const Aggregate *>(node) :
nullptr;
3284 const ClassNode *classNode = node->isClass() ?
static_cast<
const ClassNode *>(node) :
nullptr;
3286 node->isFunction() ?
static_cast<
const FunctionNode *>(node) :
nullptr;
3288 node->isProperty() ?
static_cast<
const PropertyNode *>(node) :
nullptr;
3290 node->isVariable() ?
static_cast<
const VariableNode *>(node) :
nullptr;
3291 const EnumNode *enumNode = node->isEnumType() ?
static_cast<
const EnumNode *>(node) :
nullptr;
3293 node->isQmlProperty() ?
static_cast<
const QmlPropertyNode *>(node) :
nullptr;
3294 const QmlTypeNode *qcn = node->isQmlType() ?
static_cast<
const QmlTypeNode *>(node) :
nullptr;
3300 QString synopsisTag = nodeToSynopsisTag(node);
3301 m_writer->writeStartElement(dbNamespace, synopsisTag);
3306 m_writer->writeStartElement(dbNamespace,
"ooclass");
3307 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3308 m_writer->writeEndElement();
3311 m_writer->writeTextElement(dbNamespace,
"namespacename", node->plainName());
3314 m_writer->writeStartElement(dbNamespace,
"ooclass");
3315 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3316 m_writer->writeEndElement();
3318 if (!qcn->groupNames().isEmpty())
3319 m_writer->writeAttribute(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3321 m_writer->writeTextElement(dbNamespace,
"modifier",
"(Qt property)");
3323 m_writer->writeTextElement(dbNamespace,
"type", propertyNode->dataType());
3325 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3329 m_writer->writeTextElement(dbNamespace,
"modifier",
"static");
3332 m_writer->writeTextElement(dbNamespace,
"type", variableNode->dataType());
3334 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3338 m_writer->writeTextElement(dbNamespace,
"enumname", node->plainName());
3342 QString name = node->name();
3344 name.prepend(qpn->element() + QLatin1Char(
'.'));
3346 m_writer->writeTextElement(dbNamespace,
"type", qpn->dataType());
3348 m_writer->writeTextElement(dbNamespace,
"varname", name);
3356 m_writer->writeTextElement(dbNamespace,
"modifier",
"attached");
3360 m_writer->writeTextElement(dbNamespace,
"modifier",
"writable");
3364 m_writer->writeTextElement(dbNamespace,
"modifier",
"required");
3369 generateModifier(
"[read-only]");
3373 generateModifier(
"[default]");
3377 if (functionNode->virtualness() !=
"non")
3378 generateModifier(
"virtual");
3379 if (functionNode->isConst())
3380 generateModifier(
"const");
3381 if (functionNode->isStatic())
3382 generateModifier(
"static");
3387 if (functionNode->returnType() ==
"void")
3388 m_writer->writeEmptyElement(dbNamespace,
"void");
3390 m_writer->writeTextElement(dbNamespace,
"type", functionNode->returnTypeString());
3395 QString name = node->plainName();
3396 if (name.endsWith(
"()"))
3398 m_writer->writeTextElement(dbNamespace,
"methodname", name);
3402 m_writer->writeEmptyElement(dbNamespace,
"void");
3407 for (
int i = 0; i < lp
.count(); ++i) {
3409 m_writer->writeStartElement(dbNamespace,
"methodparam");
3411 m_writer->writeTextElement(dbNamespace,
"type", parameter.type());
3413 m_writer->writeTextElement(dbNamespace,
"parameter", parameter.name());
3415 if (!parameter.defaultValue().isEmpty()) {
3416 m_writer->writeTextElement(dbNamespace,
"initializer", parameter.defaultValue());
3419 m_writer->writeEndElement();
3423 if (functionNode->isImplicitlyGenerated())
3424 generateModifier(
"implicit");
3425 else if (functionNode->isExplicitlyDefaulted())
3426 generateModifier(
"default");
3427 else if (functionNode->isDeletedAsWritten())
3428 generateModifier(
"delete");
3429 if (functionNode->isFinal())
3430 generateModifier(
"final");
3431 if (functionNode->isOverride())
3432 generateModifier(
"override");
3434 m_writer->writeTextElement(dbNamespace,
"typedefname", node->plainName());
3438 QStringLiteral(
"Unexpected node type in generateDocBookSynopsis: %1")
3439 .arg(node->nodeTypeString()));
3445 for (
const EnumItem &item : enumNode->items()) {
3446 m_writer->writeStartElement(dbNamespace,
"enumitem");
3448 m_writer->writeTextElement(dbNamespace,
"enumidentifier", item.name());
3450 m_writer->writeTextElement(dbNamespace,
"enumvalue", item.value());
3452 m_writer->writeEndElement();
3456 if (enumNode->items().isEmpty()) {
3459 m_writer->writeStartElement(dbNamespace,
"enumitem");
3461 m_writer->writeEmptyElement(dbNamespace,
"enumidentifier");
3463 m_writer->writeEndElement();
3474 generateSynopsisInfo(
"meta", functionNode->metanessString());
3477 generateSynopsisInfo(
"overload",
"overload");
3478 generateSynopsisInfo(
"overload-number",
3479 QString::number(functionNode->overloadNumber()));
3482 if (functionNode->isRef())
3483 generateSynopsisInfo(
"refness", QString::number(1));
3484 else if (functionNode->isRefRef())
3485 generateSynopsisInfo(
"refness", QString::number(2));
3488 QStringList associatedProperties;
3489 const auto &nodes = functionNode->associatedProperties();
3490 for (
const Node *n : nodes) {
3491 const auto pn =
static_cast<
const PropertyNode *>(n);
3492 associatedProperties << pn->name();
3494 associatedProperties.sort();
3495 generateSynopsisInfo(
"associated-property",
3496 associatedProperties.join(QLatin1Char(
',')));
3502 signature +=
" final";
3504 signature +=
" override";
3506 signature +=
" = 0";
3508 signature +=
" = default";
3510 signature +=
" = delete";
3511 if (
const auto &req = functionNode->trailingRequiresClause(); req && !req->isEmpty())
3512 signature +=
" requires " + *req;
3513 generateSynopsisInfo(
"signature", signature);
3519 case Access::Public:
3520 generateSynopsisInfo(
"access",
"public");
3522 case Access::Protected:
3523 generateSynopsisInfo(
"access",
"protected");
3525 case Access::Private:
3526 generateSynopsisInfo(
"access",
"private");
3531 if (node->isAbstract())
3532 generateSynopsisInfo(
"abstract",
"true");
3537 case Status::Active:
3538 generateSynopsisInfo(
"status",
"active");
3540 case Status::Preliminary:
3541 generateSynopsisInfo(
"status",
3544 case Status::Deprecated:
3545 generateSynopsisInfo(
"status",
"deprecated");
3547 case Status::Internal:
3548 case Status::InternalAuto:
3549 generateSynopsisInfo(
"status",
"internal");
3552 generateSynopsisInfo(
"status",
"main");
3559 if (aggregate->includeFile()) generateSynopsisInfo(
"headers", *aggregate->includeFile());
3562 if (!aggregate->since().isEmpty())
3563 generateSynopsisInfo(
"since", formatSince(aggregate));
3567 if (!aggregate->physicalModuleName().isEmpty()) {
3569 m_qdb->getCollectionNode(aggregate->physicalModuleName(), NodeType::Module);
3571 if (
const auto result = cmakeRequisite(cn)) {
3572 generateSynopsisInfo(
"cmake-find-package", result->first);
3573 generateSynopsisInfo(
"cmake-target-link-libraries", result->second);
3576 if (cn && !cn->qtVariable().isEmpty())
3577 generateSynopsisInfo(
"qmake",
"QT += " + cn->qtVariable());
3583 auto *classe =
const_cast<ClassNode *>(
static_cast<
const ClassNode *>(aggregate));
3584 if (classe && classe->isQmlNativeType() && !classe->isInternal()) {
3585 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3586 m_writer->writeAttribute(
"role",
"nativeTypeFor");
3588 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
3591 for (
auto item : std::as_const(nativeTypes)) {
3592 const Node *otherNode{
nullptr};
3593 Atom a = Atom(Atom::LinkNode, Utilities::stringForNode(item));
3594 const QString &link = getAutoLink(&a, aggregate, &otherNode);
3595 generateSimpleLink(link, item->name());
3598 m_writer->writeEndElement();
3602 QList<RelatedClass>::ConstIterator r;
3603 if (!classe->baseClasses().isEmpty()) {
3604 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3605 m_writer->writeAttribute(
"role",
"inherits");
3607 r = classe->baseClasses().constBegin();
3609 while (r != classe->baseClasses().constEnd()) {
3611 generateFullName((*r).m_node, classe);
3613 if ((*r).m_access == Access::Protected) {
3614 m_writer->writeCharacters(
" (protected)");
3615 }
else if ((*r).m_access == Access::Private) {
3616 m_writer->writeCharacters(
" (private)");
3618 m_writer->writeCharacters(
3619 TextUtils::comma(index++, classe->baseClasses().size()));
3624 m_writer->writeEndElement();
3629 if (!classe->derivedClasses().isEmpty()) {
3630 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3631 m_writer->writeAttribute(
"role",
"inheritedBy");
3632 generateSortedNames(classe, classe->derivedClasses());
3633 m_writer->writeEndElement();
3642 QString logicalModuleVersion;
3644 m_qdb->getCollectionNode(qcn->logicalModuleName(), qcn->nodeType());
3646 logicalModuleVersion = collection->logicalModuleVersion();
3648 logicalModuleVersion = qcn->logicalModuleVersion();
3650 QStringList importText;
3651 importText <<
"import " + qcn->logicalModuleName();
3652 if (!logicalModuleVersion.isEmpty())
3653 importText << logicalModuleVersion;
3654 generateSynopsisInfo(
"import", importText.join(
' '));
3657 if (!qcn->since().isEmpty())
3658 generateSynopsisInfo(
"since", formatSince(qcn));
3661 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
3669 QStringList knownTypeNames{qcn->name()};
3671 knownTypeNames << base->name();
3676 if (!subs.isEmpty()) {
3677 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3678 m_writer->writeAttribute(
"role",
"inheritedBy");
3679 generateSortedQmlNames(qcn, knownTypeNames, subs);
3680 m_writer->writeEndElement();
3686 const Node *otherNode =
nullptr;
3688 QString link = getAutoLink(&a, base, &otherNode);
3690 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3691 m_writer->writeAttribute(
"role",
"inherits");
3692 generateSimpleLink(link, base->name());
3694 for (
const auto sub : std::as_const(subs)) {
3695 if (knownTypeNames.contains(sub->name())) {
3696 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
3700 m_writer->writeEndElement();
3708 const Node *otherNode =
nullptr;
3710 QString link = getAutoLink(&a, cn, &otherNode);
3712 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3713 m_writer->writeAttribute(
"role",
"nativeType");
3714 generateSimpleLink(link, cn->name());
3715 m_writer->writeEndElement();
3722 case Node::UnspecifiedSafeness:
3723 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3725 case Node::NonReentrant:
3726 generateSynopsisInfo(
"threadsafeness",
"non-reentrant");
3728 case Node::Reentrant:
3729 generateSynopsisInfo(
"threadsafeness",
"reentrant");
3731 case Node::ThreadSafe:
3732 generateSynopsisInfo(
"threadsafeness",
"thread safe");
3735 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3740 if (!node->physicalModuleName().isEmpty())
3741 generateSynopsisInfo(
"module", node->physicalModuleName());
3744 if (classNode && !classNode->groupNames().isEmpty()) {
3745 generateSynopsisInfo(
"groups", classNode->groupNames().join(QLatin1Char(
',')));
3746 }
else if (qcn && !qcn->groupNames().isEmpty()) {
3747 generateSynopsisInfo(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3752 for (
const Node *fnNode : propertyNode->getters()) {
3754 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3755 generateSynopsisInfo(
"getter", funcNode->name());
3758 for (
const Node *fnNode : propertyNode->setters()) {
3760 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3761 generateSynopsisInfo(
"setter", funcNode->name());
3764 for (
const Node *fnNode : propertyNode->resetters()) {
3766 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3767 generateSynopsisInfo(
"resetter", funcNode->name());
3770 for (
const Node *fnNode : propertyNode->notifiers()) {
3772 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3773 generateSynopsisInfo(
"notifier", funcNode->name());
3778 m_writer->writeEndElement();
3784 m_writer->writeStartElement(dbNamespace,
"typedefsynopsis");
3787 m_writer->writeTextElement(dbNamespace,
"typedefname",
3788 enumNode->flagsType()->fullDocumentName());
3791 m_writer->writeEndElement();
3802 return node->name().mid(4);
3803 return node->name();
3807
3808
3809
3810void DocBookGenerator::typified(
const QString &string,
const Node *relative,
bool trailingSpace,
3815 QString pendingWord;
3817 for (
int i = 0; i <= string.size(); ++i) {
3819 if (i != string.size())
3822 QChar lower = ch.toLower();
3823 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
3824 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
3827 if (!pendingWord.isEmpty()) {
3828 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
3829 if (generateType && isProbablyType) {
3831 m_writer->writeCharacters(result);
3835 const Node *n = m_qdb->findTypeNode(pendingWord, relative, Genus::DontCare);
3840 href = linkForNode(n, relative);
3843 m_writer->writeStartElement(dbNamespace,
"type");
3845 m_writer->writeCharacters(pendingWord);
3847 generateSimpleLink(href, pendingWord);
3848 m_writer->writeEndElement();
3850 result += pendingWord;
3853 pendingWord.clear();
3855 if (ch.unicode() !=
'\0')
3860 if (trailingSpace && string.size()) {
3861 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
3862 result += QLatin1Char(
' ');
3865 m_writer->writeCharacters(result);
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3885 const QStringList &concepts,
3886 const Node *relative)
3888 if (concepts.isEmpty()) {
3889 m_writer->writeCharacters(text);
3893 QStringList sorted = concepts;
3894 std::sort(sorted.begin(), sorted.end(),
3895 [](
const QString &a,
const QString &b) {
return a.size() > b.size(); });
3901 struct Match { qsizetype offset; qsizetype length; QString name; QString target; };
3902 QList<Match> matches;
3903 QList<
bool> occupied(text.size(),
false);
3905 for (
const QString &concept_name : sorted) {
3906 const QString unqualified = concept_name.section(
"::"_L1, -1);
3907 const QRegularExpression re(
"\\b"_L1
3908 + QRegularExpression::escape(unqualified) +
"\\b"_L1);
3909 auto it = re.globalMatch(text);
3910 while (it.hasNext()) {
3911 const auto m = it.next();
3912 const qsizetype start = m.capturedStart();
3913 const qsizetype len = m.capturedLength();
3915 for (qsizetype i = start; i < start + len; ++i) {
3923 for (qsizetype i = start; i < start + len; ++i)
3925 matches.append({start, len, unqualified, concept_name});
3929 std::sort(matches.begin(), matches.end(),
3930 [](
const Match &a,
const Match &b) {
return a.offset < b.offset; });
3933 for (
const auto &m : matches) {
3935 m_writer->writeCharacters(text.mid(pos, m.offset - pos));
3936 const Node *n = m_qdb->findConceptNode(m.target);
3938 generateSimpleLink(linkForNode(n, relative), m.name);
3940 m_writer->writeCharacters(m.name);
3941 pos = m.offset + m.length;
3943 if (pos < text.size())
3944 m_writer->writeCharacters(text.mid(pos));
3948
3949
3950
3951
3952
3953
3954
3955
3956
3958 const Node *relative)
3962 if (param.template_declaration) {
3967 m_writer->writeCharacters(
"template <"_L1);
3969 for (
const auto &sub : param.template_declaration->parameters) {
3970 if (sub.sfinae_constraint)
3973 m_writer->writeCharacters(
", "_L1);
3974 generateTemplateParameter(sub, relative);
3977 m_writer->writeCharacters(
"> "_L1);
3980 switch (param
.kind) {
3982 if (param.concept_name) {
3983 const QString fq = QString::fromStdString(*param.concept_name);
3984 const QString unqualified = fq.section(
"::"_L1, -1);
3985 const Node *n = m_qdb->findConceptNode(fq);
3987 generateSimpleLink(linkForNode(n, relative), unqualified);
3991 m_writer->writeCharacters(fq);
3993 m_writer->writeCharacters(
"typename"_L1);
3996 case RelaxedTemplateParameter::Kind::NonTypeTemplateParameter:
3997 if (!decl.type.empty())
3998 typified(QString::fromStdString(decl.type), relative,
false,
true);
4000 case RelaxedTemplateParameter::Kind::TemplateTemplateParameter:
4001 m_writer->writeCharacters(
"typename"_L1);
4005 if (param.is_parameter_pack)
4006 m_writer->writeCharacters(
"..."_L1);
4008 if (!decl
.name.empty()) {
4009 m_writer->writeCharacters(
" "_L1);
4010 m_writer->writeCharacters(QString::fromStdString(decl.name));
4014 m_writer->writeCharacters(
" = "_L1);
4017 typified(QString::fromStdString(decl.initializer), relative,
false,
true);
4019 m_writer->writeCharacters(QString::fromStdString(decl.initializer));
4025
4026
4027
4028
4029
4030
4031
4032
4033
4035 const Node *relative)
4043 m_writer->writeCharacters(
"template <"_L1);
4045 m_writer->writeCharacters(
"\n"_L1);
4048 for (
const auto ¶m : templateDecl->parameters) {
4049 if (param.sfinae_constraint)
4052 m_writer->writeCharacters(multiline ?
",\n"_L1 :
", "_L1);
4054 m_writer->writeCharacters(
" "_L1);
4055 generateTemplateParameter(param, relative);
4060 m_writer->writeCharacters(
"\n"_L1);
4061 m_writer->writeCharacters(
">"_L1);
4063 if (templateDecl->requires_clause && !templateDecl->requires_clause->empty()) {
4064 m_writer->writeCharacters(
" requires "_L1);
4065 QStringList concepts;
4066 concepts.reserve(
int(templateDecl->referenced_concepts.size()));
4067 for (
const auto &s : templateDecl->referenced_concepts)
4068 concepts.append(QString::fromStdString(s));
4069 generateRequiresClauseText(QString::fromStdString(*templateDecl->requires_clause),
4070 concepts, relative);
4075 bool generateNameLink)
4079 QString name = taggedNode(node);
4081 if (!generateNameLink) {
4082 m_writer->writeCharacters(name);
4086 m_writer->writeStartElement(dbNamespace,
"emphasis");
4087 m_writer->writeAttribute(
"role",
"bold");
4088 generateSimpleLink(linkForNode(node, relative), name);
4089 m_writer->writeEndElement();
4093 bool generateExtra,
bool generateType)
4095 const QString &pname = parameter.name();
4096 const QString &ptype = parameter.type();
4098 qsizetype insertPos = !pname.isEmpty() ? parameter.nameInsertionPoint() : -1;
4099 if (!pname.isEmpty()) {
4100 if (insertPos >= 0) {
4102 typified(ptype.left(insertPos), relative,
false, generateType);
4104 typified(ptype, relative,
true, generateType);
4111 if (generateExtra || pname.isEmpty()) {
4112 m_writer->writeStartElement(dbNamespace,
"emphasis");
4113 m_writer->writeCharacters(paramName);
4114 m_writer->writeEndElement();
4118 typified(ptype.mid(insertPos), relative,
false, generateType);
4120 const QString &pvalue = parameter.defaultValue();
4121 if (generateExtra && !pvalue.isEmpty())
4122 m_writer->writeCharacters(
" = " + pvalue);
4134 const int MaxEnumValues = 6;
4136 if (generateExtra) {
4137 if (
auto extra = CodeMarker::extraSynopsis(node, style); !extra.isEmpty()) {
4138 generateExtraSynopsis(extra);
4139 m_writer->writeCharacters(u" "_s);
4144 QString namePrefix {};
4148 namePrefix = taggedNode(node->parent()) +
"::";
4153 case NodeType::Namespace:
4154 m_writer->writeCharacters(
"namespace ");
4155 m_writer->writeCharacters(namePrefix);
4156 generateSynopsisName(node, relative, generateNameLink);
4158 case NodeType::Class:
4159 m_writer->writeCharacters(
"class ");
4160 m_writer->writeCharacters(namePrefix);
4161 generateSynopsisName(node, relative, generateNameLink);
4167 if (
auto templateDecl = func->templateDecl()) {
4168 generateTemplateDecl(&*templateDecl, relative);
4169 if (templateDecl->visibleParameterCount() > QDoc::MultilineTemplateParamThreshold)
4170 m_writer->writeCharacters(
"\n"_L1);
4172 m_writer->writeCharacters(
" "_L1);
4178 if (!func->isNonvirtual())
4179 m_writer->writeCharacters(QStringLiteral(
"virtual "));
4183 if (style != Section::AllMembers && !func->returnType().isEmpty())
4184 typified(func->returnTypeString(), relative,
true, generateType);
4185 m_writer->writeCharacters(namePrefix);
4186 generateSynopsisName(node, relative, generateNameLink);
4189 m_writer->writeCharacters(QStringLiteral(
"("));
4192 for (
int i = 0; i < parameters
.count(); i++) {
4194 m_writer->writeCharacters(QStringLiteral(
", "));
4195 generateParameter(parameters
.at(i
), relative, generateExtra, generateType);
4198 m_writer->writeCharacters(QStringLiteral(
")"));
4201 if (func->isConst())
4202 m_writer->writeCharacters(QStringLiteral(
" const"));
4208 synopsis += QStringLiteral(
" final");
4210 synopsis += QStringLiteral(
" override");
4212 synopsis += QStringLiteral(
" = 0");
4214 synopsis += QStringLiteral(
" &");
4216 synopsis += QStringLiteral(
" &&");
4217 m_writer->writeCharacters(synopsis);
4219 if (!func->returnType().isEmpty() && func->returnType() !=
"void") {
4220 m_writer->writeCharacters(QStringLiteral(
" : "));
4221 typified(func->returnTypeString(), relative,
false, generateType);
4226 synopsis +=
" &"_L1;
4227 else if (func->isRefRef())
4228 synopsis +=
" &&"_L1;
4229 m_writer->writeCharacters(synopsis);
4231 if (
const auto &req = func->trailingRequiresClause(); req && !req->isEmpty()) {
4232 m_writer->writeCharacters(
" requires "_L1);
4233 generateRequiresClauseText(*req, func->referencedConcepts(), relative);
4238 const auto enume =
static_cast<
const EnumNode *>(node);
4239 if (!enume->isAnonymous()) {
4240 m_writer->writeCharacters(
"enum "_L1);
4241 m_writer->writeCharacters(namePrefix);
4242 generateSynopsisName(node, relative, generateNameLink);
4243 }
else if (generateNameLink) {
4244 m_writer->writeStartElement(dbNamespace,
"emphasis");
4245 m_writer->writeAttribute(
"role",
"bold");
4246 generateSimpleLink(linkForNode(node, relative),
"enum");
4247 m_writer->writeEndElement();
4249 m_writer->writeCharacters(
"enum"_L1);
4256 QStringList documentedItems = enume->doc().enumItemNames();
4257 if (documentedItems.isEmpty()) {
4258 const auto &enumItems = enume->items();
4259 for (
const auto &item : enumItems)
4260 documentedItems << item.name();
4262 const QStringList omitItems = enume->doc().omitEnumItemNames();
4263 for (
const auto &item : omitItems)
4264 documentedItems.removeAll(item);
4266 if (documentedItems.size() > MaxEnumValues) {
4268 const QString last = documentedItems.last();
4269 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
4270 documentedItems +=
"…";
4271 documentedItems += last;
4273 synopsis += documentedItems.join(QLatin1String(
", "));
4275 if (!documentedItems.isEmpty())
4276 synopsis += QLatin1Char(
' ');
4277 synopsis += QLatin1Char(
'}');
4279 m_writer->writeCharacters(synopsis);
4283 if (
auto templateDecl = node->templateDecl()) {
4284 generateTemplateDecl(&*templateDecl, relative);
4285 if (templateDecl->visibleParameterCount() > QDoc::MultilineTemplateParamThreshold)
4286 m_writer->writeCharacters(
"\n"_L1);
4288 m_writer->writeCharacters(
" "_L1);
4291 m_writer->writeCharacters(namePrefix);
4292 generateSynopsisName(node, relative, generateNameLink);
4295 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
4296 m_writer->writeCharacters(
"flags ");
4297 m_writer->writeCharacters(namePrefix);
4298 generateSynopsisName(node, relative, generateNameLink);
4301 const auto property =
static_cast<
const PropertyNode *>(node);
4302 m_writer->writeCharacters(namePrefix);
4303 generateSynopsisName(node, relative, generateNameLink);
4304 m_writer->writeCharacters(
" : ");
4305 typified(property->qualifiedDataType(), relative,
false, generateType);
4308 const auto variable =
static_cast<
const VariableNode *>(node);
4310 generateSynopsisName(node, relative, generateNameLink);
4311 m_writer->writeCharacters(
" : ");
4312 typified(variable->dataType(), relative,
false, generateType);
4314 typified(variable->leftType(), relative,
false, generateType);
4315 m_writer->writeCharacters(
" ");
4316 m_writer->writeCharacters(namePrefix);
4317 generateSynopsisName(node, relative, generateNameLink);
4318 m_writer->writeCharacters(variable->rightType());
4322 m_writer->writeCharacters(namePrefix);
4323 generateSynopsisName(node, relative, generateNameLink);
4338 if (nativeEnum && nativeEnum
->enumNode() && !enumValue.startsWith(
"%1."_L1.arg(nativeEnum->prefix()))) {
4339 m_writer->writeCharacters(
"%1.%2"_L1.arg(nativeEnum->prefix(), enumValue));
4345 && enumValue.section(
' ', 0, 0).contains(
'.'_L1))) {
4346 m_writer->writeCharacters(enumValue);
4350 QList<
const Node *> parents;
4352 parents.prepend(node);
4357 if (
static_cast<
const EnumNode *>(relative)->isScoped())
4358 parents << relative;
4360 m_writer->writeStartElement(dbNamespace,
"code");
4361 for (
auto parent : parents) {
4362 generateSynopsisName(parent, relative,
true);
4363 m_writer->writeCharacters((relative->genus() == Genus::QML) ?
"."_L1 :
"::"_L1);
4366 m_writer->writeCharacters(enumValue);
4367 m_writer->writeEndElement();
4371
4372
4373
4378 Q_ASSERT(node && !node->name().isEmpty());
4384 m_writer->writeStartElement(dbNamespace,
"note");
4391 m_writer->writeStartElement(dbNamespace,
"para");
4392 m_writer->writeCharacters(
4393 "This function can be invoked via the meta-object system and from QML. See ");
4394 generateSimpleLink(node->url(),
"Q_INVOKABLE");
4395 m_writer->writeCharacters(
".");
4396 m_writer->writeEndElement();
4400 m_writer->writeTextElement(
4401 dbNamespace,
"para",
4402 "This is a private signal. It can be used in signal connections but "
4403 "cannot be emitted by the user.");
4407 QString handler(node->name());
4408 int prefixLocation = handler.lastIndexOf(
'.', -2) + 1;
4409 handler[prefixLocation] = handler[prefixLocation].toTitleCase();
4410 handler.insert(prefixLocation, QLatin1String(
"on"));
4411 m_writer->writeStartElement(dbNamespace,
"para");
4412 m_writer->writeCharacters(
"The corresponding handler is ");
4413 m_writer->writeTextElement(dbNamespace,
"code", handler);
4414 m_writer->writeCharacters(
".");
4415 m_writer->writeEndElement();
4423 const auto *fn =
static_cast<
const FunctionNode *>(node);
4424 auto nodes = fn->associatedProperties();
4425 if (nodes.isEmpty())
4430 QMap<PropertyNode::FunctionRole, QList<
const PropertyNode *>> roleGroups;
4431 for (
const auto *n : std::as_const(nodes)) {
4432 const auto *pn =
static_cast<
const PropertyNode *>(n);
4433 PropertyNode::FunctionRole role = pn->role(fn);
4434 roleGroups[role].append(pn);
4446 for (
auto role : roleOrder) {
4447 const auto it = roleGroups.constFind(role);
4448 if (it == roleGroups.cend())
4451 const auto &properties = it.value();
4456 msg = QStringLiteral(
"Getter function");
4459 msg = QStringLiteral(
"Setter function");
4462 msg = QStringLiteral(
"Resetter function");
4465 msg = QStringLiteral(
"Notifier signal");
4468 msg = QStringLiteral(
"Bindable function");
4474 m_writer->writeStartElement(dbNamespace,
"para");
4475 if (properties.size() == 1) {
4476 const auto *pn = properties.first();
4477 m_writer->writeCharacters(msg +
" for property ");
4478 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4479 m_writer->writeCharacters(
". ");
4481 m_writer->writeCharacters(msg +
" for properties ");
4482 for (qsizetype i = 0; i < properties.size(); ++i) {
4483 const auto *pn = properties.at(i);
4484 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4485 m_writer->writeCharacters(TextUtils::separator(i, properties.size()));
4487 m_writer->writeCharacters(
" ");
4489 m_writer->writeEndElement();
4496 const Node *linkNode;
4498 QString link = getAutoLink(&linkAtom, node, &linkNode);
4499 m_writer->writeStartElement(dbNamespace,
"para");
4500 m_writer->writeCharacters(
"This property supports ");
4501 generateSimpleLink(link,
"QProperty");
4502 m_writer->writeCharacters(
" bindings.");
4503 m_writer->writeEndElement();
4508 const auto *func =
static_cast<
const FunctionNode *>(node);
4511 if (func->isPrimaryOverload())
4514 m_writer->writeStartElement(dbNamespace,
"para");
4516 if (func->isSignal() || func->isSlot()) {
4517 auto writeDocBookLink = [&](
const QString &target,
const QString &label) {
4518 const Node *linkNode =
nullptr;
4520 const QString &link = getAutoLink(&linkAtom, node, &linkNode);
4522 m_writer->writeStartElement(dbNamespace,
"link");
4523 if (!link.isEmpty() && linkNode) {
4524 m_writer->writeAttribute(xlinkNamespace,
"href", link);
4526 m_writer->writeAttribute(dbNamespace,
"linkend", target);
4528 m_writer->writeCharacters(label);
4529 m_writer->writeEndElement();
4532 const QString &functionType = func->isSignal() ?
"signal" :
"slot";
4533 const QString &configKey = func->isSignal() ?
"overloadedsignalstarget" :
"overloadedslotstarget";
4534 const QString &defaultTarget = func->isSignal() ?
"connecting-overloaded-signals" :
"connecting-overloaded-slots";
4535 const QString &linkTarget = Config::instance().get(configKey).asString(defaultTarget);
4537 m_writer->writeCharacters(
"This " + functionType +
" is overloaded. ");
4539 QString snippet = generateOverloadSnippet(func);
4540 if (!snippet.isEmpty()) {
4541 m_writer->writeCharacters(
"To connect to this " + functionType +
":");
4542 m_writer->writeEndElement();
4544 m_writer->writeStartElement(dbNamespace,
"programlisting");
4545 m_writer->writeCharacters(snippet);
4546 m_writer->writeEndElement();
4551 m_writer->writeStartElement(dbNamespace,
"para");
4552 if (!linkTarget.isEmpty()) {
4553 m_writer->writeCharacters(
"For more examples and approaches, see ");
4554 writeDocBookLink(linkTarget,
"connecting to overloaded " + functionType +
"s");
4555 m_writer->writeCharacters(
".");
4557 }
else if (!linkTarget.isEmpty()) {
4558 m_writer->writeCharacters(
"For more examples and approaches, see ");
4559 writeDocBookLink(linkTarget,
"connecting to overloaded " + functionType +
"s");
4560 m_writer->writeCharacters(
".");
4564 const auto &args = node
->doc().overloadList();
4565 if (args.first().first.isEmpty()) {
4566 m_writer->writeCharacters(
"This is an overloaded function.");
4568 QString target = args.first().first;
4571 if (!target.contains(
"::")) {
4574 target = parent->name() +
"::" + target;
4577 m_writer->writeCharacters(
"This function overloads ");
4579 const Node *linkNode =
nullptr;
4581 QString link = getAutoLink(&linkAtom, node, &linkNode);
4582 if (!link.isEmpty() && linkNode)
4583 generateSimpleLink(link, target);
4585 m_writer->writeCharacters(target);
4586 m_writer->writeCharacters(
".");
4590 m_writer->writeEndElement();
4599 m_writer->writeEndElement();
4607 bool closeSupplementarySection =
false;
4611 const QList<Node *> &collective = scn->collective();
4613 bool firstFunction =
true;
4614 for (
const auto *sharedNode : collective) {
4615 if (firstFunction) {
4616 startSectionBegin(sharedNode);
4618 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4619 m_writer->writeAttribute(
"renderas",
"sect2");
4620 writeXmlId(sharedNode);
4623 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4625 generateSynopsis(sharedNode, relative, Section::Details);
4627 if (firstFunction) {
4629 firstFunction =
false;
4631 m_writer->writeEndElement();
4637 if (node->isEnumType(Genus::CPP) && (etn =
static_cast<
const EnumNode *>(node))->flagsType()) {
4638 startSectionBegin(node);
4640 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4644 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4645 m_writer->writeAttribute(
"renderas",
"sect2");
4647 m_writer->writeEndElement();
4650 startSectionBegin(node);
4652 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4657 Q_ASSERT(m_hasSection);
4666 closeSupplementarySection =
true;
4667 startSection(
"",
"Notes");
4671 const auto *func =
static_cast<
const FunctionNode *>(node);
4672 if (func->hasOverloads() && (func->isSignal() || func->isSlot()))
4680 const auto property =
static_cast<
const PropertyNode *>(node);
4689 m_writer->writeStartElement(dbNamespace,
"para");
4691 m_writer->writeStartElement(dbNamespace,
"emphasis");
4692 m_writer->writeAttribute(
"role",
"bold");
4693 m_writer->writeCharacters(
"Access functions:");
4695 m_writer->writeEndElement();
4697 m_writer->writeEndElement();
4699 generateSectionList(section, node);
4706 m_writer->writeStartElement(dbNamespace,
"para");
4708 m_writer->writeStartElement(dbNamespace,
"emphasis");
4709 m_writer->writeAttribute(
"role",
"bold");
4710 m_writer->writeCharacters(
"Notifier signal:");
4712 m_writer->writeEndElement();
4714 m_writer->writeEndElement();
4716 generateSectionList(notifiers, node);
4720 const auto en =
static_cast<
const EnumNode *>(node);
4722 if (m_qflagsHref.isEmpty()) {
4723 Node *qflags = m_qdb->findClassNode(QStringList(
"QFlags"));
4725 m_qflagsHref = linkForNode(qflags,
nullptr);
4728 if (en->flagsType()) {
4729 m_writer->writeStartElement(dbNamespace,
"para");
4730 m_writer->writeCharacters(
"The ");
4731 m_writer->writeStartElement(dbNamespace,
"code");
4732 m_writer->writeCharacters(en->flagsType()->name());
4733 m_writer->writeEndElement();
4734 m_writer->writeCharacters(
" type is a typedef for ");
4735 m_writer->writeStartElement(dbNamespace,
"code");
4736 generateSimpleLink(m_qflagsHref,
"QFlags");
4737 m_writer->writeCharacters(
"<" + en->name() +
">. ");
4738 m_writer->writeEndElement();
4739 m_writer->writeCharacters(
"It stores an OR combination of ");
4740 m_writer->writeStartElement(dbNamespace,
"code");
4741 m_writer->writeCharacters(en->name());
4742 m_writer->writeEndElement();
4743 m_writer->writeCharacters(
" values.");
4744 m_writer->writeEndElement();
4749 if (closeSupplementarySection)
4760 bool useObsoleteMembers)
4765 if (!members.isEmpty()) {
4766 bool hasPrivateSignals =
false;
4767 bool isInvokable =
false;
4769 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4771 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4774 NodeVector::ConstIterator m = members.constBegin();
4775 while (m != members.constEnd()) {
4776 if ((*m)->access() == Access::Private) {
4781 m_writer->writeStartElement(dbNamespace,
"listitem");
4783 m_writer->writeStartElement(dbNamespace,
"para");
4786 generateSynopsis(*m, relative, section
.style());
4787 if ((*m)->isFunction()) {
4789 if (fn->isPrivateSignal())
4790 hasPrivateSignals =
true;
4791 else if (fn->isInvokable())
4795 m_writer->writeEndElement();
4797 m_writer->writeEndElement();
4803 m_writer->writeEndElement();
4806 if (hasPrivateSignals)
4813 && !section.inheritedMembers().isEmpty()) {
4814 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4816 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4819 generateSectionInheritedList(section, relative);
4821 m_writer->writeEndElement();
4829 QList<std::pair<
const Aggregate *,
int>>::ConstIterator p = section.inheritedMembers().constBegin();
4830 while (p != section.inheritedMembers().constEnd()) {
4831 m_writer->writeStartElement(dbNamespace,
"listitem");
4832 m_writer->writeCharacters(QString::number((*p).second) + u' ');
4833 if ((*p).second == 1)
4834 m_writer->writeCharacters(section.singular());
4836 m_writer->writeCharacters(section.plural());
4837 m_writer->writeCharacters(
" inherited from ");
4838 generateSimpleLink(fileName((*p).first) +
'#'
4839 + Generator::cleanRef(section.title().toLower()),
4840 (*p).first->plainFullName(relative));
4846
4847
4848
4852 Q_ASSERT(m_writer ==
nullptr);
4853 m_writer = startDocument(pn);
4864
4865
4870 Q_ASSERT(m_writer ==
nullptr);
4871 m_writer = startDocument(qcn);
4874 QString title = qcn->name();
4876 title.append(
" QML Value Type");
4878 title.append(
" QML Type");
4881 title.append(
" (Singleton)");
4883 title.append(
" (Uncreatable)");
4894 m_writer->writeStartElement(dbNamespace,
"note");
4895 m_writer->writeStartElement(dbNamespace,
"para");
4896 m_writer->writeStartElement(dbNamespace,
"emphasis");
4897 m_writer->writeAttribute(
"role",
"bold");
4898 m_writer->writeCharacters(
"Note: ");
4899 m_writer->writeEndElement();
4900 if (qcn->isSingleton())
4901 m_writer->writeCharacters(
"This type is a QML singleton. "
4902 "There is only one instance of this type in the QML engine.");
4904 m_writer->writeCharacters(
"This is an uncreatable type. "
4905 "It cannot be instantiated in QML.");
4906 m_writer->writeEndElement();
4907 m_writer->writeEndElement();
4910 startSection(
"details",
"Detailed Description");
4918 for (
const auto §ion : sections.detailsSections()) {
4919 if (!section.isEmpty()) {
4920 startSection(section.title().toLower(), section.title());
4922 for (
const auto &member : section.members())
4923 generateDetailedQmlMember(member, qcn);
4929 generateObsoleteQmlMembers(sections);
4938
4939
4940
4947 if (!title.isEmpty())
4951 title += n->element() + QLatin1Char(
'.');
4952 title += n->name() +
" : " + n->dataType();
4957 auto generateQmlMethodTitle = [&](
Node *node) {
4962 const auto *scn =
static_cast<
const SharedCommentNode *>(node);
4965 if (!scn->name().isEmpty())
4966 heading = scn->name() +
" group";
4968 heading = node->name();
4969 startSection(scn, heading);
4974 const QList<Node *> sharedNodes = scn->collective();
4975 for (
const auto &sharedNode : sharedNodes) {
4976 if (sharedNode->isQmlProperty()) {
4977 auto *qpn =
static_cast<QmlPropertyNode *>(sharedNode);
4979 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4980 m_writer->writeAttribute(
"renderas",
"sect2");
4982 m_writer->writeCharacters(getQmlPropertyTitle(qpn));
4983 m_writer->writeEndElement();
4986 generateDocBookSynopsis(qpn);
4990 auto qpn =
static_cast<QmlPropertyNode *>(node);
4991 startSection(qpn, getQmlPropertyTitle(qpn));
4995 const QList<Node *> &sharedNodes = scn->collective();
5000 for (
const auto &sharedNode : sharedNodes) {
5002 if (!sharedNode->isFunction(Genus::QML) && !sharedNode->isQmlProperty()) {
5008 startSectionBegin(sharedNode);
5010 m_writer->writeStartElement(dbNamespace,
"bridgehead");
5011 m_writer->writeAttribute(
"renderas",
"sect2");
5015 if (sharedNode->isFunction(Genus::QML))
5016 generateQmlMethodTitle(sharedNode);
5017 else if (sharedNode->isQmlProperty())
5018 m_writer->writeCharacters(
5019 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(sharedNode)));
5025 m_writer->writeEndElement();
5026 generateDocBookSynopsis(sharedNode);
5032 startSectionBegin(refForNode(node));
5035 generateQmlMethodTitle(node);
5036 else if (node->isQmlProperty())
5037 m_writer->writeCharacters(
5038 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(node)));
5043 startSectionBegin(node);
5047 startSectionBegin(node);
5048 generateQmlMethodTitle(node);
5062
5063
5070 if (!node->url().isNull())
5074 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102 auto cn =
static_cast<CollectionNode *>(node);
5103 if (cn->wasSeen()) {
5104 m_qdb->mergeCollections(cn);
5105 generateCollectionNode(cn);
5106 }
else if (cn->isGenericCollection()) {
5110 generateGenericCollectionPage(cn);
5113 generatePageNode(
static_cast<PageNode *>(node));
5117 generateCppReferencePage(
static_cast<Aggregate *>(node));
5119 generateQmlTypePage(
static_cast<QmlTypeNode *>(node));
5121 generateProxyPage(
static_cast<Aggregate *>(node));
5127 auto *aggregate =
static_cast<Aggregate *>(node);
5128 for (
auto c : aggregate->childNodes()) {
5129 if (node->isPageNode())
5130 generateDocumentation(c);
5141 Q_ASSERT(m_writer ==
nullptr);
5142 m_writer = startDocument(aggregate);
5150 if (!aggregate
->doc().isEmpty()) {
5151 startSection(
"details",
"Detailed Description");
5153 generateBody(aggregate);
5162 for (
const auto §ion : detailsSections) {
5163 if (section.isEmpty())
5166 startSection(section.title().toLower(), section.title());
5168 const QList<Node *> &members = section.members();
5169 for (
const auto &member : members) {
5170 if (!member->isClassNode()) {
5171 generateDetailedMember(member, aggregate);
5173 startSectionBegin();
5174 generateFullName(member, aggregate);
5177 generateBrief(member);
5191
5192
5197 Q_ASSERT(m_writer ==
nullptr);
5198 m_writer = startDocument(cn);
5207 if (cn
->genus() != Genus::DOC && cn
->genus() != Genus::DontCare) {
5218 if (!nmm.isEmpty()) {
5219 startSection(
"namespaces",
"Namespaces");
5220 generateAnnotatedList(cn, nmm.values(),
"namespaces");
5224 if (!nmm.isEmpty()) {
5225 startSection(
"classes",
"Classes");
5226 generateAnnotatedList(cn, nmm.values(),
"classes");
5232 bool generatedTitle =
false;
5234 startSection(
"details",
"Detailed Description");
5235 generatedTitle =
true;
5240 !cn
->doc().body().isEmpty() ||
5242 !cn
->doc().alsoList().empty() ||
5245 writeAnchor(
"details");
5251 if (!cn->noAutoList() && (cn->isGroup() || cn->isQmlModule()))
5252 generateAnnotatedList(cn, cn->members(),
"members", AutoSection);
5263
5264
5265
5266
5271 QString name = cn->name().toLower();
5272 name.replace(QChar(
' '), QString(
"-"));
5273 QString filename = cn->tree()->physicalModuleName() +
"-" + name +
"." + fileExtension();
5276 Q_ASSERT(m_writer ==
nullptr);
5277 m_writer = startGenericDocument(cn, filename);
5286 m_writer->writeStartElement(dbNamespace,
"para");
5287 m_writer->writeCharacters(
"Each function or type documented here is related to a class or "
5288 "namespace that is documented in a different module. The reference "
5289 "page for that class or namespace will link to the function or type "
5291 m_writer->writeEndElement();
5295 for (
const auto &member : members)
5296 generateDetailedMember(member, cnc);
5309 m_writer->writeStartElement(dbNamespace,
"link");
5310 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(node));
5311 m_writer->writeAttribute(xlinkNamespace,
"role", targetType(node));
5312 m_writer->writeCharacters(node->fullName(relative));
5313 m_writer->writeEndElement();
5317 const Node *actualNode)
5319 Q_ASSERT(apparentNode);
5320 Q_ASSERT(actualNode);
5323 m_writer->writeStartElement(dbNamespace,
"link");
5324 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(actualNode));
5325 m_writer->writeAttribute(
"role", targetType(actualNode));
5326 m_writer->writeCharacters(fullName);
5327 m_writer->writeEndElement();
#define ATOM_FORMATTING_TELETYPE
#define ATOM_LIST_LOWERALPHA
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_LIST_UPPERALPHA
#define ATOM_FORMATTING_NOTRANSLATE
#define ATOM_LIST_LOWERROMAN
#define ATOM_FORMATTING_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_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.
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(NodeType type) const
void generatePageNode(PageNode *pn)
Generate the DocBook page for an entity that doesn't map to any underlying parsable C++ or QML elemen...
void generateQmlTypePage(QmlTypeNode *qcn)
Generate the DocBook page for a QML type.
void generateAlsoList(const Node *node) override
void generateQmlRequisites(const QmlTypeNode *qcn)
Lists the required imports and includes.
void generateAddendum(const Node *node, Generator::Addendum type, CodeMarker *marker, AdmonitionPrefix prefix) override
Generates an addendum note of type type for node.
void generateHeader(const Text &title, const Node *node)
Generates the opening portion of the DocBook header — {<db:info>} and the title element.
void initializeGenerator() override
Initializes the DocBook output generator's data structures from the configuration (Config).
bool generateText(const Text &text, const Node *relative) override
Generate the documentation for relative.
void finishHeader(const Node *node)
Emits the tail of the DocBook header — product, edition, titleabbrev, navigation links,...
void generateCppReferencePage(Node *node)
Generate a reference page for the C++ class, namespace, or header file documented in node.
void generateSortedQmlNames(const Node *base, const QStringList &knownTypes, const NodeList &subs)
DocBookGenerator(FileResolver &file_resolver)
bool generateThreadSafeness(const Node *node)
Generates text that explains how threadsafe and/or reentrant node is.
void generateCollectionNode(CollectionNode *cn)
Generate the HTML page for a group, module, or QML module.
void generateHeader(const Text &title, const QString &subtitle, const Node *node)
void generateDocBookSynopsis(const Node *node)
Generate the metadata for the given node in DocBook.
void generateGenericCollectionPage(CollectionNode *cn)
Generate the HTML page for a generic collection.
void generateList(const Node *relative, const QString &selector, Qt::SortOrder sortOrder=Qt::AscendingOrder)
void generateBody(const Node *node)
Generate the body of the documentation from the qdoc comment found with the entity represented by the...
qsizetype generateAtom(const Atom *atom, const Node *relative, CodeMarker *) override
Generate DocBook from an instance of Atom.
void generateProxyPage(Aggregate *aggregate)
bool generateStatus(const Node *node)
void generateRequisites(const Aggregate *inner)
Lists the required imports and includes.
void generateSortedNames(const ClassNode *cn, const QList< RelatedClass > &rc)
void generateDocumentation(Node *node) override
Recursive writing of DocBook files from the root node.
void generateGroupReferenceText(const Node *node)
Return a string representing a text that exposes information about the groups that the node is part o...
QString format() const override
Returns the format identifier for this producer (e.g., "HTML", "DocBook", "template").
void generateExampleFilePage(const PageNode *en, ResolvedFile resolved_file, CodeMarker *=nullptr) override
Generate a file with the contents of a C++ or QML source file.
QString fileExtension() const override
Returns "xml" for this subclass of Generator.
bool generateSince(const Node *node)
const Location & location() const
Returns the starting location of a qdoc comment.
static void quoteFromFile(const Location &location, Quoter "er, ResolvedFile resolved_file, CodeMarker *marker=nullptr)
const Text & body() 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 isMacroWithoutParams() const
bool isPrivateSignal() const
const Parameters & parameters() const
bool isPureVirtual() const override
bool hasOverloads() const
Returns true if this function has overloads.
bool isMacro() const override
returns true if either FunctionNode::isMacroWithParams() or FunctionNode::isMacroWithoutParams() retu...
bool isDeletedAsWritten() const
bool isExplicitlyDefaulted() const
bool hasAssociatedProperties() const
bool generateComparisonCategory(const Node *node, CodeMarker *marker=nullptr)
static void setQmlTypeContext(QmlTypeNode *t)
const Atom * generateAtomList(const Atom *atom, const Node *relative, CodeMarker *marker, bool generate, int &numGeneratedAtoms)
void unknownAtom(const Atom *atom)
static bool matchAhead(const Atom *atom, Atom::AtomType expectedAtomType)
void generateEnumValuesForQmlReference(const Node *node, CodeMarker *marker)
virtual int skipAtoms(const Atom *atom, Atom::AtomType type) const
bool generateComparisonTable(const Node *node)
Generates a table of comparison categories for node, combining both self-comparison (from \compares) ...
virtual void initializeGenerator()
No-op base implementation.
void initializeTextOutput()
Resets the variables used during text output.
static bool isIncluded(const InclusionPolicy &policy, const NodeContext &context)
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.
Interface implemented by Node subclasses that can refer to a C++ enum.
virtual const NativeEnum * nativeEnum() const =0
Encapsulates information about native (C++) enum values.
const EnumNode * enumNode() const
A PageNode is a Node that generates a documentation page.
bool noAutoList() const
Returns the value of the no auto-list flag.
The Parameter class describes one function parameter.
This class describes one instance of using the Q_PROPERTY macro.
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
static QDocDatabase * qdocDB()
Creates the singleton.
Status
Specifies the status of the QQmlIncubator.
bool isDefault() const override
Returns true if the QML property node is marked as default.
bool isReadOnly() const
Returns true if this QML property node is marked as a read-only property.
bool isRequired() const
Const overloads that delegate to the resolving non-const versions when the attribute hasn't been cach...
bool isAttached() const override
Returns true if the QML property or QML method node is marked as attached.
ClassNode * classNode() const override
If this is a QmlTypeNode, this function returns the pointer to the C++ ClassNode that this QML type r...
bool isUncreatable() const
static void subclasses(const Node *base, NodeList &subs, bool recurse=false)
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)
const NodeVector & members() const
A class for creating vectors of collections for documentation.
const Aggregate * aggregate() const
Sections(const Aggregate *aggregate)
This constructor builds the section vectors based on the type of the aggregate node.
bool hasObsoleteMembers(SectionPtrVector *summary_spv, SectionPtrVector *details_spv) const
Returns true if any sections in this object contain obsolete members.
SectionVector & detailsSections()
static Text sectionHeading(const Atom *sectionBegin)
const Atom * firstAtom() const
Text & operator=(const Text &text)
const Atom * lastAtom() const
bool isStatic() const override
Returns true if the FunctionNode represents a static function.
static bool isOneColumnValueTable(const Atom *atom)
Determines whether the list atom should be shown with just one column (value).
static void rewritePropertyBrief(const Atom *atom, const Node *relative)
Rewrites the brief of this node depending on its first word.
static int hOffset(const Node *node)
Header offset depending on the type of the node.
static bool hasBrief(const Node *node)
Do not display.
XmlGenerator(FileResolver &file_resolver)
static const QRegularExpression m_funcLeftParen
static NodeType typeFromString(const Atom *atom)
Returns the type of this atom as an enumeration.
#define CONFIG_DOCBOOKEXTENSIONS
#define CONFIG_PRELIMINARY
#define CONFIG_DESCRIPTION
#define CONFIG_EXAMPLESINSTALLPATH
#define CONFIG_NATURALLANGUAGE
#define CONFIG_PRODUCTNAME
#define CONFIG_BUILDVERSION
static const char xlinkNamespace[]
static QString nodeToSynopsisTag(const Node *node)
QString removeCodeMarkers(const QString &code)
static const char dbNamespace[]
QString taggedNode(const Node *node)
static const char itsNamespace[]
constexpr std::size_t MultilineTemplateParamThreshold
Combined button and popup list for selecting options.
QList< Node * > NodeVector
QMap< QString, Node * > NodeMap
QMap< QString, NodeMap > NodeMapMap
QMap< QString, CollectionNode * > CNMap
QT_BEGIN_NAMESPACE typedef QMultiMap< Text, const Node * > TextToNodeMap
QList< const Section * > SectionPtrVector
QList< Section > SectionVector
The Node class is the base class for all the nodes in QDoc's parse tree.
bool isExternalPage() const
Returns true if the node type is ExternalPage.
const Doc & doc() const
Returns a reference to the node's Doc data member.
bool isQmlNode() const
Returns true if this node's Genus value is QML.
bool isEnumType(Genus g) const
bool isGroup() const
Returns true if the node type is Group.
virtual bool docMustBeGenerated() const
This function is called to perform a test to decide if the node must have documentation generated.
bool isPrivate() const
Returns true if this node's access is Private.
bool isNamespace() const
Returns true if the node type is Namespace.
bool isTypedef() const
Returns true if the node type is Typedef.
bool isQmlBasicType() const
Returns true if the node type is QmlBasicType.
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
bool isSharedCommentNode() const
Returns true if the node type is SharedComment.
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.
NodeType nodeType() const override
Returns this node's type.
Genus genus() const override
Returns this node's Genus.
virtual bool isPageNode() const
Returns true if this node represents something that generates a documentation page.
bool isEnumType() const
Returns true if the node type is Enum.
virtual Status status() const
Returns the node's status value.
virtual bool isTextPageNode() const
Returns true if the node is a PageNode but not an Aggregate.
Aggregate * parent() const
Returns the node's parent pointer.
bool isVariable() const
Returns true if the node type is Variable.
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.
Access access() const
Returns the node's Access setting, which can be Public, Protected, or Private.
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
ThreadSafeness threadSafeness() const
Returns the thread safeness value for whatever this node represents.
virtual bool isMarkedReimp() const
Returns true if the FunctionNode is marked as a reimplemented function.
bool isProperty() const
Returns true if the node type is Property.
NodeContext createContext() const
bool isModule() const
Returns true if the node type is Module.
bool isClass() const
Returns true if the node type is Class.
virtual bool isPropertyGroup() const
Returns true if the node is a SharedCommentNode for documenting multiple C++ properties or multiple Q...
ThreadSafeness
An unsigned char that specifies the degree of thread-safeness of the element.
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...
bool isRelatedNonmember() const
Returns true if this is a related nonmember of something.
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 isQmlModule() const
Returns true if the node type is QmlModule.
bool isExample() const
Returns true if the node type is Example.
bool isIndexNode() const
Returns true if this node was created from something in an index file.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.
A class for parsing and managing a function parameter list.
const Parameter & at(int i) const
std::size_t visibleParameterCount() const
Returns the number of template parameters that are visible in rendered output — SFINAE-annotated para...
ValuedDeclaration valued_declaration
@ TemplateTemplateParameter
Represents a file that is reachable by QDoc based on its current configuration.