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>
46using namespace Qt::StringLiterals;
48static const char dbNamespace[] =
"http://docbook.org/ns/docbook";
56 m_writer->writeCharacters(
"\n");
64 m_writer->writeAttribute(
"xml:id", registerRef(id,
true));
77 QString id = Generator::cleanRef(refForNode(node),
true);
79 m_writer->writeAttribute(
"xml:id", id);
86 m_writer->writeStartElement(dbNamespace,
"section");
89 m_writer->writeStartElement(dbNamespace,
"title");
94 m_writer->writeStartElement(dbNamespace,
"section");
97 m_writer->writeStartElement(dbNamespace,
"title");
102 m_writer->writeEndElement();
108 startSectionBegin(id);
109 m_writer->writeCharacters(title);
115 startSectionBegin(node);
116 m_writer->writeCharacters(title);
123 startSection(
"", title);
128 m_writer->writeEndElement();
137 m_writer->writeEmptyElement(dbNamespace,
"anchor");
143
144
145
150 m_config = &Config::instance();
156 if (m_projectDescription.isEmpty() && !m_project.isEmpty())
157 m_projectDescription = m_project + QLatin1String(
" Reference Documentation");
160 if (m_naturalLanguage.isEmpty())
161 m_naturalLanguage = QLatin1String(
"en");
165 m_config->get(format() + Config::dot +
"usedocbookextensions").asBool();
166 m_useITS = m_config->get(format() + Config::dot +
"its").asBool();
175
176
183
184
185
186
201 QString rewritten = code;
202 static const QRegularExpression re(
"(<@[^>&]*>)|(<\\/@[^&>]*>)");
203 rewritten.replace(re,
"");
208
209
215 qsizetype skipAhead = 0;
216 Genus genus = Genus::DontCare;
224 if (!m_inLink && !m_inContents && !m_inSectionHeading) {
225 const Node *node =
nullptr;
226 QString link = getAutoLink(atom, relative, &node, genus);
231 if (link.isEmpty()) {
232 m_writer->writeCharacters(atom->string());
234 beginLink(link, node, relative);
239 m_writer->writeCharacters(atom->string());
249 m_writer->writeStartElement(dbNamespace,
"para");
255 m_writer->writeEndElement();
265 m_writer->writeCharacters(plainCode(atom->string()));
267 m_writer->writeTextElement(dbNamespace,
"code", plainCode(atom->string()));
269 case Atom::CaptionLeft:
270 m_writer->writeStartElement(dbNamespace,
"title");
274 m_writer->writeEndElement();
278 m_writer->writeStartElement(dbNamespace,
"programlisting");
279 m_writer->writeAttribute(
"language",
"qml");
281 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
282 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
283 m_writer->writeEndElement();
287 m_writer->writeStartElement(dbNamespace,
"programlisting");
289 if (atom->strings().count() == 2)
290 m_writer->writeAttribute(
"language", atom->string(1));
292 m_writer->writeAttribute(
"language",
"cpp");
294 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
295 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
296 m_writer->writeEndElement();
300 m_writer->writeStartElement(dbNamespace,
"programlisting");
301 m_writer->writeAttribute(
"language",
"cpp");
302 m_writer->writeAttribute(
"role",
"bad");
304 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
305 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
306 m_writer->writeEndElement();
313 qsizetype offset{ 0 };
322 case Atom::FootnoteLeft:
323 m_writer->writeStartElement(dbNamespace,
"footnote");
325 m_writer->writeStartElement(dbNamespace,
"para");
328 case Atom::FootnoteRight:
329 m_writer->writeEndElement();
332 m_writer->writeEndElement();
340 m_writer->writeStartElement(dbNamespace,
"emphasis");
341 m_writer->writeAttribute(
"role",
"bold");
343 m_writer->writeStartElement(dbNamespace,
"emphasis");
345 m_writer->writeStartElement(dbNamespace,
"emphasis");
346 m_writer->writeAttribute(
"role",
"underline");
348 m_writer->writeStartElement(dbNamespace,
"subscript");
350 m_writer->writeStartElement(dbNamespace,
"superscript");
353 m_writer->writeStartElement(dbNamespace,
"code");
355 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
358 m_writer->writeAttribute(
"role",
"parameter");
362 m_writer->writeStartElement(dbNamespace,
"guilabel");
364 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
366 m_writer->writeStartElement(dbNamespace,
367 appendTrademark(atom->find(Atom::FormattingRight)) ?
368 "trademark" :
"phrase");
370 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
372 m_writer->writeStartElement(dbNamespace,
"phrase");
374 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
376 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
389 m_writer->writeEndElement();
392 m_inTeletype =
false;
395 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
399 if (
const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group))
400 generateList(cn, atom->string(), Generator::sortOrder(atom->strings().last()));
403 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
404 bool hasGeneratedSomething =
false;
405 if (atom->string() == QLatin1String(
"annotatedclasses")
406 || atom->string() == QLatin1String(
"attributions")
407 || atom->string() == QLatin1String(
"namespaces")) {
408 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedclasses")
409 ? m_qdb->getCppClasses()
410 : atom->string() == QLatin1String(
"attributions") ? m_qdb->getAttributions()
411 : m_qdb->getNamespaces();
412 generateAnnotatedList(relative, things.values(), atom->string(), Auto, sortOrder);
413 hasGeneratedSomething = !things.isEmpty();
414 }
else if (atom->string() == QLatin1String(
"annotatedexamples")
415 || atom->string() == QLatin1String(
"annotatedattributions")) {
416 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedexamples")
417 ? m_qdb->getAttributions()
418 : m_qdb->getExamples();
419 generateAnnotatedLists(relative, things, atom->string());
420 hasGeneratedSomething = !things.isEmpty();
421 }
else if (atom->string() == QLatin1String(
"classes")
422 || atom->string() == QLatin1String(
"qmlbasictypes")
423 || atom->string() == QLatin1String(
"qmlvaluetypes")
424 || atom->string() == QLatin1String(
"qmltypes")) {
425 const NodeMultiMap things = atom->string() == QLatin1String(
"classes")
426 ? m_qdb->getCppClasses()
427 : (atom->string() == QLatin1String(
"qmlvaluetypes")
428 || atom->string() == QLatin1String(
"qmlbasictypes"))
429 ? m_qdb->getQmlValueTypes()
430 : m_qdb->getQmlTypes();
431 generateCompactList(relative, things,
true, QString(), atom->string());
432 hasGeneratedSomething = !things.isEmpty();
433 }
else if (atom->string().contains(
"classes ")) {
434 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
437 hasGeneratedSomething = !things.isEmpty();
438 generateCompactList(relative, things,
true, rootName, atom->string());
439 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
440 QString moduleName = atom->string().mid(idx + 8).trimmed();
443 if (
const CollectionNode *cn = qdb->getCollectionNode(moduleName, moduleType)) {
445 switch (moduleType) {
451 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
457 generateAnnotatedList(relative, cn->members(), atom->string(), Auto, sortOrder);
461 if (!map.isEmpty()) {
462 generateAnnotatedList(relative, map.values(), atom->string(), Auto, sortOrder);
463 hasGeneratedSomething =
true;
466 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
467 generateClassHierarchy(relative, m_qdb->getCppClasses());
468 hasGeneratedSomething = !m_qdb->getCppClasses().isEmpty();
469 }
else if (atom->string().startsWith(
"obsolete")) {
470 QString prefix = atom->string().contains(
"cpp") ? QStringLiteral(
"Q") : QString();
471 const NodeMultiMap &things = atom->string() == QLatin1String(
"obsoleteclasses")
472 ? m_qdb->getObsoleteClasses()
473 : atom->string() == QLatin1String(
"obsoleteqmltypes")
474 ? m_qdb->getObsoleteQmlTypes()
475 : atom->string() == QLatin1String(
"obsoletecppmembers")
476 ? m_qdb->getClassesWithObsoleteMembers()
477 : m_qdb->getQmlTypesWithObsoleteMembers();
478 generateCompactList(relative, things,
false, prefix, atom->string());
479 hasGeneratedSomething = !things.isEmpty();
480 }
else if (atom->string() == QLatin1String(
"functionindex")) {
481 generateFunctionIndex(relative);
482 hasGeneratedSomething = !m_qdb->getFunctionIndex().isEmpty();
483 }
else if (atom->string() == QLatin1String(
"legalese")) {
484 generateLegaleseList(relative);
485 hasGeneratedSomething = !m_qdb->getLegaleseTexts().isEmpty();
486 }
else if (atom->string() == QLatin1String(
"overviews")
487 || atom->string() == QLatin1String(
"cpp-modules")
488 || atom->string() == QLatin1String(
"qml-modules")
489 || atom->string() == QLatin1String(
"related")) {
490 generateList(relative, atom->string());
491 hasGeneratedSomething =
true;
493 }
else if (
const auto *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group); cn) {
494 generateAnnotatedList(cn, cn->members(), atom->string(), ItemizedList, sortOrder);
495 hasGeneratedSomething =
true;
500 if (!hasGeneratedSomething && !m_inPara) {
501 m_writer->writeEmptyElement(dbNamespace,
"para");
533 m_writer->writeStartElement(dbNamespace,
"figure");
540 generateAtom(current, relative,
nullptr);
545 generateAtom(current, relative,
nullptr);
551 generateAtom(current, relative,
nullptr);
555 m_closeFigureWrapper =
true;
566 m_writer->writeStartElement(dbNamespace,
"figure");
573 generateAtom(current, relative,
nullptr);
578 generateAtom(current, relative,
nullptr);
584 generateAtom(current, relative,
nullptr);
588 m_closeFigureWrapper =
true;
611 m_writer->writeStartElement(dbNamespace, tag);
614 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
615 if (!maybe_resolved_file) {
617 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
619 m_writer->writeStartElement(dbNamespace,
"textobject");
621 m_writer->writeStartElement(dbNamespace,
"para");
622 m_writer->writeTextElement(dbNamespace,
"emphasis",
623 "[Missing image " + atom->string() +
"]");
624 m_writer->writeEndElement();
626 m_writer->writeEndElement();
630 QString file_name{QFileInfo{file.get_path()}.fileName()};
634 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
638 m_writer->writeTextElement(dbNamespace,
"alt", atom->next()->string());
642 m_writer->writeStartElement(dbNamespace,
"imageobject");
644 m_writer->writeEmptyElement(dbNamespace,
"imagedata");
645 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
647 m_writer->writeAttribute(
"fileref", imgPath);
649 m_writer->writeEndElement();
653 setImageFileName(relative, imgPath);
656 m_writer->writeEndElement();
660 if (m_closeFigureWrapper) {
661 m_writer->writeEndElement();
663 m_closeFigureWrapper =
false;
671 QString admonType = atom->typeString().toLower();
674 m_writer->writeStartElement(dbNamespace, admonType);
676 m_writer->writeStartElement(dbNamespace,
"para");
679 case Atom::ImportantRight:
680 case Atom::NoteRight:
681 case Atom::WarningRight:
682 m_writer->writeEndElement();
685 m_writer->writeEndElement();
693 const Node *node =
nullptr;
694 QString link = getLink(atom, relative, &node);
695 beginLink(link, node, relative);
699 const Node *node =
static_cast<
const Node*>(Utilities::nodeForString(atom->string()));
700 beginLink(linkForNode(node, relative), node, relative);
710 m_writer->writeEndElement();
716 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
719 m_writer->writeStartElement(dbNamespace,
"variablelist");
722 m_writer->writeStartElement(dbNamespace,
"informaltable");
724 m_writer->writeStartElement(dbNamespace,
"thead");
726 m_writer->writeStartElement(dbNamespace,
"tr");
728 m_writer->writeTextElement(dbNamespace,
"th",
"Constant");
731 m_threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
732 if (m_threeColumnEnumValueTable && relative->isEnumType(Genus::CPP)) {
734 m_writer->writeTextElement(dbNamespace,
"th",
"Value");
739 m_writer->writeTextElement(dbNamespace,
"th",
"Description");
743 m_writer->writeEndElement();
745 m_writer->writeEndElement();
748 m_writer->writeStartElement(dbNamespace,
"orderedlist");
750 if (atom->next() !=
nullptr && atom->next()->string().toInt() != 1)
751 m_writer->writeAttribute(
"startingnumber", atom->next()->string());
754 m_writer->writeAttribute(
"numeration",
"upperalpha");
756 m_writer->writeAttribute(
"numeration",
"loweralpha");
758 m_writer->writeAttribute(
"numeration",
"upperroman");
760 m_writer->writeAttribute(
"numeration",
"lowerroman");
762 m_writer->writeAttribute(
"numeration",
"arabic");
772 m_writer->writeStartElement(dbNamespace,
"varlistentry");
774 m_writer->writeStartElement(dbNamespace,
"item");
776 std::pair<QString,
int> pair = getAtomListValue(atom);
777 skipAhead = pair.second;
779 m_writer->writeStartElement(dbNamespace,
"tr");
781 m_writer->writeStartElement(dbNamespace,
"td");
783 m_writer->writeStartElement(dbNamespace,
"para");
785 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
786 generateEnumValue(pair.first, relative);
787 m_writer->writeEndElement();
789 m_writer->writeEndElement();
793 const auto enume =
static_cast<
const EnumNode *>(relative);
794 QString itemValue = enume->itemValue(atom
->next()->string());
796 m_writer->writeStartElement(dbNamespace,
"td");
797 if (itemValue.isEmpty())
798 m_writer->writeCharacters(
"?");
800 m_writer->writeStartElement(dbNamespace,
"code");
802 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
803 m_writer->writeCharacters(itemValue);
804 m_writer->writeEndElement();
806 m_writer->writeEndElement();
814 m_writer->writeEndElement();
820 m_writer->writeEndElement();
827 m_inListItemLineOpen =
false;
829 m_writer->writeStartElement(dbNamespace,
"listitem");
831 m_writer->writeStartElement(dbNamespace,
"para");
834 if (m_threeColumnEnumValueTable) {
836 m_writer->writeEmptyElement(dbNamespace,
"td");
838 m_inListItemLineOpen =
false;
840 m_writer->writeStartElement(dbNamespace,
"td");
842 m_inListItemLineOpen =
true;
846 m_writer->writeStartElement(dbNamespace,
"listitem");
855 m_writer->writeEndElement();
858 m_writer->writeEndElement();
860 m_writer->writeEndElement();
863 if (m_inListItemLineOpen) {
864 m_writer->writeEndElement();
866 m_inListItemLineOpen =
false;
868 m_writer->writeEndElement();
871 m_writer->writeEndElement();
876 case Atom::ListRight:
882 m_writer->writeEndElement();
889 m_writer->writeStartElement(dbNamespace,
"para");
895 m_writer->writeEndElement();
900 case Atom::QuotationLeft:
901 m_writer->writeStartElement(dbNamespace,
"blockquote");
902 m_inBlockquote =
true;
904 case Atom::QuotationRight:
905 m_writer->writeEndElement();
907 m_inBlockquote =
false;
910 m_writer->device()->write(atom->string().toUtf8());
916 currentSectionLevel = atom->string().toInt() +
hOffset(relative
);
918 if (currentSectionLevel > 1) {
921 while (!sectionLevels.empty() && sectionLevels.top() >= currentSectionLevel) {
923 m_writer->writeEndElement();
927 sectionLevels.push(currentSectionLevel);
929 m_writer->writeStartElement(dbNamespace,
"section");
930 writeXmlId(Tree::refForAtom(atom));
943 generateAtom(atom->next(), relative,
nullptr);
944 generateAtom(atom->next()->next(), relative,
nullptr);
945 generateAtom(atom->next()->next()->next(), relative,
nullptr);
947 m_closeSectionAfterGeneratedList =
true;
954 m_writer->writeTextElement(dbNamespace,
"title",
"");
963 if (currentSectionLevel > 1) {
964 m_writer->writeStartElement(dbNamespace,
"title");
965 m_inSectionHeading =
true;
970 if (currentSectionLevel > 1) {
971 m_writer->writeEndElement();
973 m_inSectionHeading =
false;
976 case Atom::SidebarLeft:
977 m_writer->writeStartElement(dbNamespace,
"sidebar");
979 case Atom::SidebarRight:
980 m_writer->writeEndElement();
984 if (m_inLink && !m_inContents && !m_inSectionHeading)
987 m_writer->writeCharacters(atom->string());
990 std::pair<QString, QString> pair = getTableWidthAttr(atom);
991 QString attr = pair.second;
992 QString width = pair.first;
995 m_writer->writeEndElement();
1000 m_tableHeaderAlreadyOutput =
false;
1002 m_writer->writeStartElement(dbNamespace,
"informaltable");
1003 m_writer->writeAttribute(
"style", attr);
1004 if (!width.isEmpty())
1005 m_writer->writeAttribute(
"width", width);
1008 case Atom::TableRight:
1009 m_tableWidthAttr = {
"",
""};
1010 m_writer->writeEndElement();
1019 if (m_tableHeaderAlreadyOutput) {
1022 m_writer->writeEndElement();
1025 const QString &attr = m_tableWidthAttr.second;
1026 const QString &width = m_tableWidthAttr.first;
1028 m_writer->writeStartElement(dbNamespace,
"informaltable");
1029 m_writer->writeAttribute(
"style", attr);
1030 if (!width.isEmpty())
1031 m_writer->writeAttribute(
"width", width);
1034 m_tableHeaderAlreadyOutput =
true;
1040 id = TextUtils::asAsciiPrintable(next->string());
1045 m_writer->writeStartElement(dbNamespace,
"thead");
1047 m_writer->writeStartElement(dbNamespace,
"tr");
1050 m_inTableHeader =
true;
1053 m_closeTableCell =
true;
1054 m_writer->writeStartElement(dbNamespace,
"td");
1060 if (m_closeTableCell) {
1061 m_closeTableCell =
false;
1062 m_writer->writeEndElement();
1066 m_writer->writeEndElement();
1070 m_writer->writeStartElement(dbNamespace,
"tr");
1073 m_writer->writeEndElement();
1075 m_inTableHeader =
false;
1085 bool hasTarget {
false};
1087 id = TextUtils::asAsciiPrintable(atom
->next()->string());
1092 m_writer->writeStartElement(dbNamespace,
"tr");
1095 if (atom->string().isEmpty()) {
1096 m_writer->writeAttribute(
"valign",
"top");
1101 QStringList args = atom->string().split(
"\"", Qt::SkipEmptyParts);
1104 const int nArgs = args.size();
1109 QStringLiteral(
"Error when parsing attributes for the table: got \"%1\"")
1110 .arg(atom->string()));
1112 for (
int i = 0; i + 1 < nArgs; i += 2) {
1115 const QString &attr = args.at(i).chopped(1);
1118 writeXmlId(args.at(i + 1));
1120 m_writer->writeAttribute(attr, args.at(i + 1));
1136 m_closeTableRow =
true;
1137 m_writer->writeEndElement();
1143 if (m_closeTableRow) {
1144 m_closeTableRow =
false;
1145 m_writer->writeEndElement();
1149 m_writer->writeEndElement();
1152 case Atom::TableItemLeft:
1153 m_writer->writeStartElement(dbNamespace, m_inTableHeader ?
"th" :
"td");
1155 for (
int i = 0; i < atom->count(); ++i) {
1156 const QString &p = atom->string(i);
1157 if (p.contains(
'=')) {
1158 QStringList lp = p.split(QLatin1Char(
'='));
1159 m_writer->writeAttribute(lp.at(0), lp.at(1));
1161 QStringList spans = p.split(QLatin1Char(
','));
1162 if (spans.size() == 2) {
1163 if (spans.at(0) !=
"1")
1164 m_writer->writeAttribute(
"colspan", spans.at(0).trimmed());
1165 if (spans.at(1) !=
"1")
1166 m_writer->writeAttribute(
"rowspan", spans.at(1).trimmed());
1173 case Atom::TableItemRight:
1174 m_writer->writeEndElement();
1186 QString nextId = TextUtils::asAsciiPrintable(
1188 QString ownId = TextUtils::asAsciiPrintable(atom->string());
1189 if (nextId == ownId)
1193 writeAnchor(TextUtils::asAsciiPrintable(atom->string()));
1195 case Atom::UnhandledFormat:
1196 m_writer->writeStartElement(dbNamespace,
"emphasis");
1197 m_writer->writeAttribute(
"role",
"bold");
1198 m_writer->writeCharacters(
"<Missing DocBook>");
1199 m_writer->writeEndElement();
1201 case Atom::UnknownCommand:
1202 m_writer->writeStartElement(dbNamespace,
"emphasis");
1203 m_writer->writeAttribute(
"role",
"bold");
1205 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1206 m_writer->writeCharacters(
"<Unknown command>");
1207 m_writer->writeStartElement(dbNamespace,
"code");
1208 m_writer->writeCharacters(atom->string());
1209 m_writer->writeEndElement();
1210 m_writer->writeEndElement();
1230 if (classMap.isEmpty())
1233 std::function<
void(
ClassNode *)> generateClassAndChildren
1234 = [
this, &relative, &generateClassAndChildren](ClassNode * classe) {
1235 m_writer->writeStartElement(dbNamespace,
"listitem");
1239 m_writer->writeStartElement(dbNamespace,
"para");
1240 generateFullName(classe, relative);
1241 m_writer->writeEndElement();
1245 bool hasChild =
false;
1246 for (
const RelatedClass &relatedClass : classe->derivedClasses()) {
1247 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1254 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1257 for (
const RelatedClass &relatedClass: classe->derivedClasses()) {
1258 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1259 generateClassAndChildren(relatedClass.m_node);
1263 m_writer->writeEndElement();
1268 m_writer->writeEndElement();
1272 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1275 for (
const auto &it : classMap) {
1276 auto *classe =
static_cast<ClassNode *>(it);
1277 if (classe->baseClasses().isEmpty())
1278 generateClassAndChildren(classe);
1281 m_writer->writeEndElement();
1290 if (m_linkNode && m_linkNode->isFunction()) {
1292 if (match.hasMatch()) {
1294 qsizetype leftParenLoc = match.capturedStart(1);
1295 m_writer->writeCharacters(atom->string().left(leftParenLoc));
1297 m_writer->writeCharacters(atom->string().mid(leftParenLoc));
1301 m_writer->writeCharacters(atom->string());
1305
1306
1307
1311 m_writer->writeStartElement(dbNamespace,
"link");
1312 m_writer->writeAttribute(xlinkNamespace,
"href", link);
1313 if (node && !(relative && node->status() == relative->status())
1314 && node->isDeprecated())
1315 m_writer->writeAttribute(
"role",
"deprecated");
1324 m_writer->writeEndElement();
1326 m_linkNode =
nullptr;
1330 Qt::SortOrder sortOrder)
1335 if (selector == QLatin1String(
"overviews"))
1337 else if (selector == QLatin1String(
"cpp-modules"))
1339 else if (selector == QLatin1String(
"qml-modules"))
1344 m_qdb->mergeCollections(type, cnm, relative);
1345 const QList<CollectionNode *> collectionList = cnm.values();
1346 nodeList.reserve(collectionList.size());
1347 for (
auto *collectionNode : collectionList)
1348 nodeList.append(collectionNode);
1349 generateAnnotatedList(relative, nodeList, selector, Auto, sortOrder);
1352
1353
1354
1355 Node *n =
const_cast<
Node *>(relative);
1356 auto *cn =
static_cast<CollectionNode *>(n);
1357 m_qdb->mergeCollections(cn);
1358 generateAnnotatedList(cn, cn->members(), selector, Auto, sortOrder);
1363
1364
1365
1367 const QString &selector, GeneratedListType type,
1368 Qt::SortOrder sortOrder)
1370 if (nodeList.isEmpty())
1374 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1375 if (
std::all_of(nodeList.cbegin(), nodeList.cend(), [&policy](
const Node *n) {
1377 return !InclusionFilter::isIncluded(policy, context) || n->isDeprecated();
1384 bool noItemsHaveTitle =
1385 type == ItemizedList ||
std::all_of(nodeList.begin(), nodeList.end(),
1386 [](
const Node* node) {
1387 return node->doc().briefText().toString().isEmpty();
1391 if (type == AutoSection && m_hasSection)
1392 startSection(
"",
"Contents");
1395 if (!nodeList.isEmpty()) {
1396 m_writer->writeStartElement(dbNamespace, noItemsHaveTitle ?
"itemizedlist" :
"variablelist");
1397 m_writer->writeAttribute(
"role", selector);
1401 members.reserve(nodeList.size());
1402 std::copy_if(nodeList.cbegin(), nodeList.cend(),
std::back_inserter(members),
1403 [&policy](
const Node *n) {
1405 return InclusionFilter::isIncluded(policy, context) && !n->isDeprecated();
1408 if (sortOrder == Qt::DescendingOrder)
1414 auto sameLocation = [
this](
const Node *a,
const Node *b) {
1415 return fullDocumentLocation(a) == fullDocumentLocation(b);
1417 members.erase(
std::unique(members.begin(), members.end(), sameLocation), members.end());
1419 for (
const auto &node : std::as_const(members)) {
1420 if (noItemsHaveTitle) {
1421 m_writer->writeStartElement(dbNamespace,
"listitem");
1423 m_writer->writeStartElement(dbNamespace,
"para");
1425 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1427 m_writer->writeStartElement(dbNamespace,
"term");
1429 generateFullName(node, relative);
1430 if (noItemsHaveTitle) {
1431 m_writer->writeEndElement();
1433 m_writer->writeEndElement();
1435 m_writer->writeEndElement();
1437 m_writer->writeStartElement(dbNamespace,
"listitem");
1439 m_writer->writeStartElement(dbNamespace,
"para");
1440 m_writer->writeCharacters(node->doc().briefText().toString());
1441 m_writer->writeEndElement();
1443 m_writer->writeEndElement();
1445 m_writer->writeEndElement();
1450 m_writer->writeEndElement();
1454 if (type == AutoSection && m_hasSection)
1459
1460
1461
1463 const QString &selector)
1466 for (
const QString &name : nmm.uniqueKeys()) {
1467 if (!name.isEmpty())
1468 startSection(name.toLower(), name);
1469 generateAnnotatedList(relative, nmm.values(name), selector);
1470 if (!name.isEmpty())
1476
1477
1478
1479
1480
1481
1482
1483
1484
1486 bool includeAlphabet,
const QString &commonPrefix,
1487 const QString &selector)
1497 const int NumParagraphs = 37;
1498 qsizetype commonPrefixLen = commonPrefix.size();
1501
1502
1503
1504
1505
1507 QString paragraphName[NumParagraphs + 1];
1508 QSet<
char> usedParagraphNames;
1510 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
1511 QStringList pieces = c.key().split(
"::");
1512 int idx = commonPrefixLen;
1513 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
1515 QString last = pieces.last().toLower();
1516 QString key = last.mid(idx);
1518 int paragraphNr = NumParagraphs - 1;
1520 if (key[0].digitValue() != -1) {
1521 paragraphNr = key[0].digitValue();
1522 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
1523 paragraphNr = 10 + key[0].unicode() -
'a';
1526 paragraphName[paragraphNr] = key[0].toUpper();
1527 usedParagraphNames.insert(key[0].toLower().cell());
1528 paragraph[paragraphNr].insert(last, c.value());
1532
1533
1534
1535
1536
1537
1538
1539 int paragraphOffset[NumParagraphs + 1];
1540 paragraphOffset[0] = 0;
1541 for (
int i = 0; i < NumParagraphs; i++)
1542 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
1545 if (includeAlphabet && !usedParagraphNames.isEmpty()) {
1546 m_writer->writeStartElement(dbNamespace,
"simplelist");
1549 for (
int i = 0; i < 26; i++) {
1551 if (usedParagraphNames.contains(
char(
'a' + i))) {
1552 m_writer->writeStartElement(dbNamespace,
"member");
1553 generateSimpleLink(ch, ch.toUpper());
1554 m_writer->writeEndElement();
1559 m_writer->writeEndElement();
1564 QHash<QString,
int> nameOccurrences;
1565 for (
const auto &[key, node] : nmm.asKeyValueRange()) {
1566 QStringList pieces{node->fullName(relative).split(
"::"_L1)};
1567 const QString &name{pieces.last()};
1568 nameOccurrences[name]++;
1573 int curParOffset = 0;
1575 m_writer->writeStartElement(dbNamespace,
"variablelist");
1576 m_writer->writeAttribute(
"role", selector);
1579 for (
int i = 0; i < nmm.size(); i++) {
1580 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
1587 if (curParOffset == 0) {
1589 m_writer->writeEndElement();
1591 m_writer->writeEndElement();
1593 m_writer->writeEndElement();
1597 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1598 if (includeAlphabet)
1599 writeXmlId(paragraphName[curParNr][0].toLower());
1602 m_writer->writeStartElement(dbNamespace,
"term");
1603 m_writer->writeStartElement(dbNamespace,
"emphasis");
1604 m_writer->writeAttribute(
"role",
"bold");
1605 m_writer->writeCharacters(paragraphName[curParNr]);
1606 m_writer->writeEndElement();
1607 m_writer->writeEndElement();
1610 m_writer->writeStartElement(dbNamespace,
"listitem");
1612 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1617 m_writer->writeStartElement(dbNamespace,
"listitem");
1619 m_writer->writeStartElement(dbNamespace,
"para");
1621 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
1622 NodeMultiMap::Iterator it;
1623 NodeMultiMap::Iterator next;
1624 it = paragraph[curParNr].begin();
1625 for (
int j = 0; j < curParOffset; j++)
1630 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
1631 const auto &name{pieces.last()};
1634 if (nameOccurrences[name] > 1) {
1635 const QString moduleName = it.value()->isQmlNode() ? it.value()->logicalModuleName()
1636 : it.value()->tree()->camelCaseModuleName();
1637 pieces.last().append(
": %1"_L1.arg(moduleName));
1641 m_writer->writeStartElement(dbNamespace,
"link");
1642 m_writer->writeAttribute(xlinkNamespace,
"href", linkForNode(*it, relative));
1643 if (
const QString type = targetType(it.value()); !type.isEmpty())
1644 m_writer->writeAttribute(
"role", type);
1645 m_writer->writeCharacters(pieces.last());
1646 m_writer->writeEndElement();
1649 if (pieces.size() > 1) {
1650 m_writer->writeCharacters(
" (");
1651 generateFullName(it.value()->parent(), relative);
1652 m_writer->writeCharacters(
")");
1656 m_writer->writeEndElement();
1658 m_writer->writeEndElement();
1663 m_writer->writeEndElement();
1665 m_writer->writeEndElement();
1667 m_writer->writeEndElement();
1670 m_writer->writeEndElement();
1679 m_writer->writeStartElement(dbNamespace,
"simplelist");
1680 m_writer->writeAttribute(
"role",
"functionIndex");
1682 for (
int i = 0; i < 26; i++) {
1684 m_writer->writeStartElement(dbNamespace,
"member");
1685 m_writer->writeAttribute(xlinkNamespace,
"href", QString(
"#") + ch);
1686 m_writer->writeCharacters(ch.toUpper());
1687 m_writer->writeEndElement();
1690 m_writer->writeEndElement();
1695 if (m_qdb->getFunctionIndex().isEmpty())
1697 char nextLetter =
'a';
1700 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1703 NodeMapMap &funcIndex = m_qdb->getFunctionIndex();
1704 QMap<QString, NodeMap>::ConstIterator f = funcIndex.constBegin();
1705 while (f != funcIndex.constEnd()) {
1706 m_writer->writeStartElement(dbNamespace,
"listitem");
1708 m_writer->writeStartElement(dbNamespace,
"para");
1709 m_writer->writeCharacters(f.key() +
": ");
1711 currentLetter = f.key()[0].unicode();
1712 while (islower(currentLetter) && currentLetter >= nextLetter) {
1713 writeAnchor(QString(nextLetter));
1717 NodeMap::ConstIterator s = (*f).constBegin();
1718 while (s != (*f).constEnd()) {
1719 m_writer->writeCharacters(
" ");
1720 generateFullName((*s)->parent(), relative);
1724 m_writer->writeEndElement();
1726 m_writer->writeEndElement();
1730 m_writer->writeEndElement();
1738 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
1739 Text text = it.key();
1741 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1744 m_writer->writeStartElement(dbNamespace,
"listitem");
1746 m_writer->writeStartElement(dbNamespace,
"para");
1747 generateFullName(it.value(), relative);
1748 m_writer->writeEndElement();
1750 m_writer->writeEndElement();
1753 }
while (it != legaleseTexts.constEnd() && it.key() == text);
1754 m_writer->writeEndElement();
1769 m_writer->writeStartElement(dbNamespace,
"para");
1771 m_writer->writeEndElement();
1779 if (!node->since().isEmpty()) {
1780 m_writer->writeStartElement(dbNamespace,
"para");
1782 const auto &collective =
static_cast<
const SharedCommentNode *>(node)->collective();
1783 QString typeStr = collective.size() > 1 ? typeString(collective.first()) +
"s" : typeString(node);
1784 m_writer->writeCharacters(
"These " + typeStr +
" were introduced in ");
1786 m_writer->writeCharacters(
"This " + typeString(node) +
" was introduced in ");
1788 m_writer->writeCharacters(formatSince(node) +
".");
1789 m_writer->writeEndElement();
1799
1800
1801
1807 if (!subTitle.isEmpty()) {
1808 m_writer->writeStartElement(dbNamespace,
"subtitle");
1809 if (isApiGenus(node->genus()) && m_useITS)
1810 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1811 m_writer->writeCharacters(subTitle);
1812 m_writer->writeEndElement();
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1835 m_writer->writeStartElement(dbNamespace,
"info");
1837 m_writer->writeStartElement(dbNamespace,
"title");
1838 if (isApiGenus(node->genus()) && m_useITS)
1839 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1841 m_writer->writeEndElement();
1846
1847
1848
1849
1850
1853 if (!m_productName.isEmpty() || !m_project.isEmpty()) {
1854 m_writer->writeTextElement(dbNamespace,
"productname", m_productName.isEmpty() ?
1855 m_project : m_productName);
1859 if (!m_buildVersion.isEmpty()) {
1860 m_writer->writeTextElement(dbNamespace,
"edition", m_buildVersion);
1864 if (!m_projectDescription.isEmpty()) {
1865 m_writer->writeTextElement(dbNamespace,
"titleabbrev", m_projectDescription);
1873 if (node && !node->links().empty()) {
1874 std::pair<QString, QString> linkPair;
1875 std::pair<QString, QString> anchorPair;
1876 const Node *linkNode;
1878 if (node->links().contains(Node::PreviousLink)) {
1879 linkPair = node->links()[Node::PreviousLink];
1880 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1881 if (!linkNode || linkNode == node)
1882 anchorPair = linkPair;
1884 anchorPair = anchorForNode(linkNode);
1886 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1887 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1888 m_writer->writeEmptyElement(dbNamespace,
"link");
1889 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1890 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1891 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"prev");
1892 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1893 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1895 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1896 m_writer->writeEndElement();
1899 if (node->links().contains(Node::NextLink)) {
1900 linkPair = node->links()[Node::NextLink];
1901 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1902 if (!linkNode || linkNode == node)
1903 anchorPair = linkPair;
1905 anchorPair = anchorForNode(linkNode);
1907 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1908 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1909 m_writer->writeEmptyElement(dbNamespace,
"link");
1910 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1911 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1912 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"next");
1913 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1914 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1916 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1917 m_writer->writeEndElement();
1920 if (node->links().contains(Node::StartLink)) {
1921 linkPair = node->links()[Node::StartLink];
1922 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1923 if (!linkNode || linkNode == node)
1924 anchorPair = linkPair;
1926 anchorPair = anchorForNode(linkNode);
1928 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1929 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1930 m_writer->writeEmptyElement(dbNamespace,
"link");
1931 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1932 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1933 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"start");
1934 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1935 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1937 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1938 m_writer->writeEndElement();
1950 m_writer->writeStartElement(dbNamespace,
"abstract");
1953 bool generatedSomething =
false;
1957 node->isNamespace() ?
static_cast<
const NamespaceNode *>(node) :
nullptr;
1960 brief <<
"The " << ns->name()
1961 <<
" namespace includes the following elements from module "
1962 << ns
->tree()->camelCaseModuleName() <<
". The full namespace is "
1963 <<
"documented in module " << NS
->tree()->camelCaseModuleName();
1964 addNodeLink(brief, fullDocumentLocation(NS),
" here.");
1973 m_writer->writeStartElement(dbNamespace,
"para");
1975 m_writer->writeEndElement();
1978 generatedSomething =
true;
1988 if (!generatedSomething)
1989 m_writer->writeTextElement(dbNamespace,
"para", m_projectDescription +
".");
1991 m_writer->writeEndElement();
1996 m_writer->writeEndElement();
2002 while (!sectionLevels.isEmpty()) {
2003 sectionLevels.pop();
2010 if (m_closeSectionAfterGeneratedList) {
2011 m_closeSectionAfterGeneratedList =
false;
2014 if (m_closeSectionAfterRawTitle) {
2015 m_closeSectionAfterRawTitle =
false;
2020 m_writer->writeEndElement();
2023void DocBookGenerator::generateSimpleLink(
const QString &href,
const QString &text)
2025 m_writer->writeStartElement(dbNamespace,
"link");
2026 m_writer->writeAttribute(xlinkNamespace,
"href", href);
2027 m_writer->writeCharacters(text);
2028 m_writer->writeEndElement();
2032
2033
2034
2037 static const QHash<QString, QString> extrefUrls = {
2038 {u"cpp-explicitly-defaulted"_s,
2039 u"https://en.cppreference.com/w/cpp/language/function#Defaulted_functions"_s},
2040 {u"cpp-deleted-functions"_s,
2041 u"https://en.cppreference.com/w/cpp/language/function#Deleted_functions"_s},
2044 static const QRegularExpression extrefRegex(
2045 u"<@extref target=\"([^\"]+)\">([^<]*)</@extref>"_s);
2048 auto it = extrefRegex.globalMatch(extra);
2049 while (it.hasNext()) {
2050 auto match = it.next();
2051 if (match.capturedStart() > pos)
2052 m_writer->writeCharacters(extra.mid(pos, match.capturedStart() - pos));
2054 QString target = match.captured(1);
2055 QString text = match.captured(2);
2056 QString url = extrefUrls.value(target);
2058 generateSimpleLink(url, text);
2060 m_writer->writeCharacters(text);
2062 pos = match.capturedEnd();
2064 if (pos < extra.size())
2065 m_writer->writeCharacters(extra.mid(pos));
2077 startSection(
"obsolete",
"Obsolete Members for " + aggregate->plainFullName());
2079 m_writer->writeStartElement(dbNamespace,
"para");
2080 m_writer->writeStartElement(dbNamespace,
"emphasis");
2081 m_writer->writeAttribute(
"role",
"bold");
2082 m_writer->writeCharacters(
"The following members of class ");
2083 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2084 m_writer->writeCharacters(
" are deprecated.");
2085 m_writer->writeEndElement();
2086 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2087 m_writer->writeEndElement();
2090 for (
const Section *section : details_spv) {
2091 const QString &title =
"Obsolete " + section->title();
2092 startSection(title.toLower(), title);
2094 const NodeVector &members = section->obsoleteMembers();
2095 NodeVector::ConstIterator m = members.constBegin();
2096 while (m != members.constEnd()) {
2097 if ((*m)->access() != Access::Private)
2098 generateDetailedMember(*m, aggregate);
2109
2110
2111
2112
2113
2114
2115
2125 startSection(
"obsolete",
"Obsolete Members for " + aggregate->name());
2127 m_writer->writeStartElement(dbNamespace,
"para");
2128 m_writer->writeStartElement(dbNamespace,
"emphasis");
2129 m_writer->writeAttribute(
"role",
"bold");
2130 m_writer->writeCharacters(
"The following members of QML type ");
2131 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2132 m_writer->writeCharacters(
" are deprecated.");
2133 m_writer->writeEndElement();
2134 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2135 m_writer->writeEndElement();
2138 for (
const auto *section : details_spv) {
2139 const QString &title =
"Obsolete " + section->title();
2140 startSection(title.toLower(), title);
2142 const NodeVector &members = section->obsoleteMembers();
2143 NodeVector::ConstIterator m = members.constBegin();
2144 while (m != members.constEnd()) {
2145 if ((*m)->access() != Access::Private)
2146 generateDetailedQmlMember(*m, aggregate);
2160 return QStringLiteral(
"classsynopsis");
2162 return QStringLiteral(
"packagesynopsis");
2168 return QStringLiteral(
"enumsynopsis");
2170 return QStringLiteral(
"typedefsynopsis");
2173 const auto fn =
static_cast<
const FunctionNode *>(node);
2174 if (fn->isCtor() || fn->isCCtor() || fn->isMCtor())
2175 return QStringLiteral(
"constructorsynopsis");
2177 return QStringLiteral(
"destructorsynopsis");
2178 return QStringLiteral(
"methodsynopsis");
2181 return QStringLiteral(
"fieldsynopsis");
2183 node
->doc().location().warning(QString(
"Unknown node tag %1").arg(node->nodeTypeString()));
2184 return QStringLiteral(
"synopsis");
2189 m_writer->writeStartElement(dbNamespace,
"varlistentry");
2191 m_writer->writeTextElement(dbNamespace,
"term", description);
2193 m_writer->writeStartElement(dbNamespace,
"listitem");
2195 m_writer->writeStartElement(dbNamespace,
"para");
2201 m_writer->writeEndElement();
2204 m_writer->writeEndElement();
2206 m_writer->writeEndElement();
2210void DocBookGenerator::generateRequisite(
const QString &description,
const QString &value)
2212 generateStartRequisite(description);
2213 m_writer->writeCharacters(value);
2214 generateEndRequisite();
2218
2219
2220
2221void DocBookGenerator::generateCMakeRequisite(
const QString &findPackage,
const QString &linkLibraries)
2223 const QString description(
"CMake");
2224 generateStartRequisite(description);
2225 m_writer->writeCharacters(findPackage);
2226 m_writer->writeEndElement();
2229 m_writer->writeStartElement(dbNamespace,
"para");
2230 m_writer->writeCharacters(linkLibraries);
2231 generateEndRequisite();
2237 QMap<QString, ClassNode *> classMap;
2238 QList<RelatedClass>::ConstIterator r = rc.constBegin();
2239 while (r != rc.constEnd()) {
2242 && !rcn
->doc().isEmpty()) {
2243 classMap[rcn->plainFullName(cn).toLower()] = rcn;
2248 QStringList classNames = classMap.keys();
2252 for (
const QString &className : classNames) {
2253 generateFullName(classMap.value(className), cn);
2254 m_writer->writeCharacters(TextUtils::comma(index++, classNames.size()));
2262 QMap<QString, Node *> classMap;
2263 QStringList typeNames(knownTypes);
2264 for (
const auto sub : subs)
2265 typeNames << sub->name();
2267 for (
auto sub : subs) {
2268 QString key{sub->plainFullName(base).toLower()};
2270 if (typeNames.count(sub->name()) > 1)
2271 key.append(
": (%1)"_L1.arg(sub->logicalModuleName()));
2272 classMap[key] = sub;
2275 QStringList names = classMap.keys();
2279 for (
const QString &name : names) {
2280 generateFullName(classMap.value(name), base);
2281 if (name.contains(
':'))
2282 m_writer->writeCharacters(name.section(
':', 1));
2283 m_writer->writeCharacters(TextUtils::comma(index++, names.size()));
2288
2289
2298 QXmlStreamWriter* oldWriter = m_writer;
2300 m_writer =
new QXmlStreamWriter(&output);
2303 if (aggregate->includeFile()) generateRequisite(
"Header", *aggregate->includeFile());
2306 if (!aggregate->since().isEmpty())
2307 generateRequisite(
"Since", formatSince(aggregate));
2312 m_qdb->getCollectionNode(aggregate->physicalModuleName(), NodeType::Module);
2314 if (
const auto result = cmakeRequisite(cn)) {
2315 generateCMakeRequisite(result->first, result->second);
2318 if (cn && !cn->qtVariable().isEmpty())
2319 generateRequisite(
"qmake",
"QT += " + cn->qtVariable());
2324 auto *classe =
const_cast<ClassNode *>(
static_cast<
const ClassNode *>(aggregate));
2325 if (classe && classe->isQmlNativeType() && !classe->isInternal()) {
2326 generateStartRequisite(
"In QML");
2329 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2332 for (
const auto &item : std::as_const(nativeTypes)) {
2333 generateFullName(item, classe);
2334 m_writer->writeCharacters(
2335 TextUtils::comma(idx++, nativeTypes.size()));
2337 generateEndRequisite();
2341 QList<RelatedClass>::ConstIterator r;
2342 const auto *metaTags = classe ? classe->doc().metaTagMap() :
nullptr;
2343 bool suppressInherits = metaTags && metaTags->contains(u"qdoc-suppress-inheritance"_s);
2344 if (classe && !suppressInherits && !classe->baseClasses().isEmpty()) {
2345 generateStartRequisite(
"Inherits");
2347 r = classe->baseClasses().constBegin();
2349 while (r != classe->baseClasses().constEnd()) {
2351 generateFullName((*r).m_node, classe);
2353 if ((*r).m_access == Access::Protected)
2354 m_writer->writeCharacters(
" (protected)");
2355 else if ((*r).m_access == Access::Private)
2356 m_writer->writeCharacters(
" (private)");
2357 m_writer->writeCharacters(
2358 TextUtils::comma(index++, classe->baseClasses().size()));
2363 generateEndRequisite();
2367 if (!classe->derivedClasses().isEmpty()) {
2368 generateStartRequisite(
"Inherited By");
2369 generateSortedNames(classe, classe->derivedClasses());
2370 generateEndRequisite();
2375 if (!aggregate->groupNames().empty()) {
2376 generateStartRequisite(
"Group");
2378 generateEndRequisite();
2382 if (
auto status = formatStatus(aggregate, m_qdb); status)
2383 generateRequisite(
"Status", status.value());
2387 m_writer = oldWriter;
2389 if (!output.isEmpty()) {
2392 static const QRegularExpression xmlTag(R"(<(/?)n\d+:)");
2393 static const QRegularExpression xmlnsDocBookDefinition(R"( xmlns:n\d+=")" + QString{dbNamespace} +
"\"");
2394 static const QRegularExpression xmlnsXLinkDefinition(R"( xmlns:n\d+=")" + QString{xlinkNamespace} +
"\"");
2395 static const QRegularExpression xmlAttr(R"( n\d+:)");
2397 const QString cleanOutput = output.replace(xmlTag, R"(<\1db:)")
2398 .replace(xmlnsDocBookDefinition,
"")
2399 .replace(xmlnsXLinkDefinition,
"")
2400 .replace(xmlAttr,
" xlink:");
2402 m_writer->writeStartElement(dbNamespace,
"variablelist");
2404 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2407 m_writer->device()->write(cleanOutput.toUtf8());
2409 m_writer->writeEndElement();
2415
2416
2424 const QString importText =
"Import Statement";
2425 const QString sinceText =
"Since";
2426 const QString inheritedByText =
"Inherited By";
2427 const QString inheritsText =
"Inherits";
2428 const QString nativeTypeText =
"In C++";
2429 const QString groupText =
"Group";
2430 const QString statusText =
"Status";
2438 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2447 bool generate_import_statement = !qcn->logicalModuleName().isEmpty();
2448 if (generate_import_statement && collection) {
2453 const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base;
2455 if (!generates_something)
2458 QStringList knownTypeNames{qcn->name()};
2460 knownTypeNames << base->name();
2463 m_writer->writeStartElement(dbNamespace,
"variablelist");
2465 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2468 if (generate_import_statement) {
2469 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2470 generateRequisite(importText, parts.join(
' ').trimmed());
2474 if (!qcn->since().isEmpty())
2475 generateRequisite(sinceText, formatSince(qcn));
2480 generateStartRequisite(nativeTypeText);
2481 generateSimpleLink(fullDocumentLocation(cn), cn->name());
2482 generateEndRequisite();
2487 generateStartRequisite(inheritsText);
2488 generateSimpleLink(fullDocumentLocation(base), base->name());
2490 for (
const auto sub : std::as_const(subs)) {
2491 if (knownTypeNames.contains(sub->name())) {
2492 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
2496 generateEndRequisite();
2500 if (!subs.isEmpty()) {
2501 generateStartRequisite(inheritedByText);
2502 generateSortedQmlNames(qcn, knownTypeNames, subs);
2503 generateEndRequisite();
2507 if (!qcn->groupNames().empty()) {
2508 generateStartRequisite(groupText);
2510 generateEndRequisite();
2514 if (
auto status = formatStatus(qcn, m_qdb); status)
2515 generateRequisite(statusText, status.value());
2517 m_writer->writeEndElement();
2528 const QString &state =
static_cast<
const CollectionNode*>(node)->state();
2529 if (!state.isEmpty()) {
2530 m_writer->writeStartElement(dbNamespace,
"para");
2531 m_writer->writeCharacters(
"This " + typeString(node) +
" is in ");
2532 m_writer->writeStartElement(dbNamespace,
"emphasis");
2533 m_writer->writeCharacters(state);
2534 m_writer->writeEndElement();
2535 m_writer->writeCharacters(
" state.");
2536 m_writer->writeEndElement();
2541 if (
const auto &version = node->deprecatedSince(); !version.isEmpty()) {
2542 m_writer->writeStartElement(dbNamespace,
"para");
2543 m_writer->writeCharacters(
"This " + typeString(node)
2544 +
" is scheduled for deprecation in version "
2546 m_writer->writeEndElement();
2551 case Status::Preliminary:
2552 m_writer->writeStartElement(dbNamespace,
"para");
2553 m_writer->writeStartElement(dbNamespace,
"emphasis");
2554 m_writer->writeAttribute(
"role",
"bold");
2555 m_writer->writeCharacters(
2559 .replace(
'\1'_L1, typeString(node)));
2560 m_writer->writeEndElement();
2561 m_writer->writeEndElement();
2564 case Status::Deprecated:
2565 m_writer->writeStartElement(dbNamespace,
"para");
2567 m_writer->writeStartElement(dbNamespace,
"emphasis");
2568 m_writer->writeAttribute(
"role",
"bold");
2570 m_writer->writeCharacters(
"This " + typeString(node) +
" is deprecated");
2571 if (
const QString &version = node->deprecatedSince(); !version.isEmpty()) {
2572 m_writer->writeCharacters(
" since ");
2573 if (node->isQmlNode() && !node->logicalModuleName().isEmpty())
2574 m_writer->writeCharacters(node->logicalModuleName() +
" ");
2575 m_writer->writeCharacters(version);
2577 m_writer->writeCharacters(
". We strongly advise against using it in new code.");
2578 if (node->isAggregate())
2579 m_writer->writeEndElement();
2580 m_writer->writeEndElement();
2591
2592
2593
2597 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2600 NodeList::ConstIterator n = nodes.constBegin();
2601 while (n != nodes.constEnd()) {
2602 m_writer->writeStartElement(dbNamespace,
"listitem");
2604 m_writer->writeStartElement(dbNamespace,
"para");
2606 generateSimpleLink(currentGenerator()->fullDocumentLocation(*n),
2607 (*n)->signature(Node::SignaturePlain));
2609 m_writer->writeEndElement();
2611 m_writer->writeEndElement();
2616 m_writer->writeEndElement();
2621
2622
2623
2630 const auto aggregate =
static_cast<
const Aggregate *>(node);
2632 const QStringList &groups_names{aggregate->groupNames()};
2633 if (!groups_names.empty()) {
2634 m_writer->writeCharacters(aggregate->name() +
" is part of ");
2635 m_writer->writeStartElement(dbNamespace,
"simplelist");
2637 for (qsizetype index{0}; index < groups_names.size(); ++index) {
2639 m_qdb->mergeCollections(group);
2641 m_writer->writeStartElement(dbNamespace,
"member");
2642 if (QString target{linkForNode(group,
nullptr)}; !target.isEmpty())
2643 generateSimpleLink(target, group->fullTitle());
2645 m_writer->writeCharacters(group->name());
2646 m_writer->writeEndElement();
2649 m_writer->writeEndElement();
2655
2656
2657
2663 const Node *reentrantNode;
2665 QString linkReentrant = getAutoLink(&reentrantAtom, node, &reentrantNode);
2666 const Node *threadSafeNode;
2668 QString linkThreadSafe = getAutoLink(&threadSafeAtom, node, &threadSafeNode);
2671 m_writer->writeStartElement(dbNamespace,
"warning");
2673 m_writer->writeStartElement(dbNamespace,
"para");
2674 m_writer->writeCharacters(
"This " + typeString(node) +
" is not ");
2675 generateSimpleLink(linkReentrant,
"reentrant");
2676 m_writer->writeCharacters(
".");
2677 m_writer->writeEndElement();
2679 m_writer->writeEndElement();
2683 m_writer->writeStartElement(dbNamespace,
"note");
2685 m_writer->writeStartElement(dbNamespace,
"para");
2688 m_writer->writeCharacters(
"All functions in this " + typeString(node) +
" are ");
2689 if (ts == Node::ThreadSafe)
2690 generateSimpleLink(linkThreadSafe,
"thread-safe");
2692 generateSimpleLink(linkReentrant,
"reentrant");
2697 bool exceptions = hasExceptions(node, reentrant, threadsafe, nonreentrant);
2698 if (!exceptions || (ts ==
Node::Reentrant && !threadsafe.isEmpty())) {
2699 m_writer->writeCharacters(
".");
2700 m_writer->writeEndElement();
2703 m_writer->writeCharacters(
" with the following exceptions:");
2704 m_writer->writeEndElement();
2706 m_writer->writeStartElement(dbNamespace,
"para");
2709 if (!nonreentrant.isEmpty()) {
2710 m_writer->writeCharacters(
"These functions are not ");
2711 generateSimpleLink(linkReentrant,
"reentrant");
2712 m_writer->writeCharacters(
":");
2713 m_writer->writeEndElement();
2715 generateSignatureList(nonreentrant);
2717 if (!threadsafe.isEmpty()) {
2718 m_writer->writeCharacters(
"These functions are also ");
2719 generateSimpleLink(linkThreadSafe,
"thread-safe");
2720 m_writer->writeCharacters(
":");
2721 m_writer->writeEndElement();
2723 generateSignatureList(threadsafe);
2726 if (!reentrant.isEmpty()) {
2727 m_writer->writeCharacters(
"These functions are only ");
2728 generateSimpleLink(linkReentrant,
"reentrant");
2729 m_writer->writeCharacters(
":");
2730 m_writer->writeEndElement();
2732 generateSignatureList(reentrant);
2734 if (!nonreentrant.isEmpty()) {
2735 m_writer->writeCharacters(
"These functions are not ");
2736 generateSimpleLink(linkReentrant,
"reentrant");
2737 m_writer->writeCharacters(
":");
2738 m_writer->writeEndElement();
2740 generateSignatureList(nonreentrant);
2745 m_writer->writeCharacters(
"This " + typeString(node) +
" is ");
2746 if (ts == Node::ThreadSafe)
2747 generateSimpleLink(linkThreadSafe,
"thread-safe");
2749 generateSimpleLink(linkReentrant,
"reentrant");
2750 m_writer->writeCharacters(
".");
2751 m_writer->writeEndElement();
2754 m_writer->writeEndElement();
2764
2765
2766
2770 const FunctionNode *fn = node->isFunction() ?
static_cast<
const FunctionNode *>(node) :
nullptr;
2774
2775
2776
2780 t =
"Destroys the instance of " + fn
->parent()->name() +
".";
2782 t +=
" The destructor is virtual.";
2784 t =
"Default constructs an instance of " + fn
->parent()->name() +
".";
2786 t =
"Copy constructor.";
2788 t =
"Move-copy constructor.";
2790 t =
"Copy-assignment constructor.";
2792 t =
"Move-assignment constructor.";
2796 m_writer->writeTextElement(dbNamespace,
"para", t);
2800 if (fn && !fn->overridesThis().isEmpty())
2801 generateReimplementsClause(fn);
2803 if (
static_cast<
const PropertyNode *>(node)->propertyType() != PropertyNode::PropertyType::StandardProperty)
2832 generateRequiredLinks(node);
2836
2837
2838
2839
2840
2847 const auto en =
static_cast<
const ExampleNode *>(node);
2850 if (exampleUrl.isEmpty()) {
2851 if (!en->noAutoList()) {
2852 generateFileList(en,
false);
2853 generateFileList(en,
true);
2856 generateLinkToExample(en, exampleUrl);
2861
2862
2863
2864
2865
2869 QString exampleUrl(baseUrl);
2871#ifndef QT_BOOTSTRAPPED
2872 link = QUrl(exampleUrl).host();
2874 if (!link.isEmpty())
2875 link.prepend(
" @ ");
2876 link.prepend(
"Example project");
2878 const QLatin1Char separator(
'/');
2879 const QLatin1Char placeholder(
'\1');
2880 if (!exampleUrl.contains(placeholder)) {
2881 if (!exampleUrl.endsWith(separator))
2882 exampleUrl += separator;
2883 exampleUrl += placeholder;
2887 QStringList path = QStringList()
2889 path.removeAll(QString());
2893 startSection(
"Example project");
2895 m_writer->writeStartElement(dbNamespace,
"para");
2896 generateSimpleLink(exampleUrl.replace(placeholder, path.join(separator)), link);
2897 m_writer->writeEndElement();
2906
2907
2908
2909
2910
2911
2927 paths = en->images();
2930 paths = en->files();
2933 std::sort(paths.begin(), paths.end(), Generator::comparePaths);
2935 if (paths.isEmpty())
2938 startSection(
"",
"List of Files");
2940 m_writer->writeStartElement(dbNamespace,
"para");
2941 m_writer->writeCharacters(tag);
2942 m_writer->writeEndElement();
2945 startSection(
"List of Files");
2947 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2950 for (
const auto &path : std::as_const(paths)) {
2951 auto maybe_resolved_file{file_resolver.resolve(path)};
2952 if (!maybe_resolved_file) {
2954 QString details = std::transform_reduce(
2955 file_resolver.get_search_directories().cbegin(),
2956 file_resolver.get_search_directories().cend(),
2957 u"Searched directories:"_s,
2959 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
2962 en->location().warning(u"Cannot find file to quote from: %1"_s.arg(path), details);
2967 const auto &file{*maybe_resolved_file};
2968 if (images) addImageToCopy(en, file);
2969 else generateExampleFilePage(en, file);
2971 m_writer->writeStartElement(dbNamespace,
"listitem");
2973 m_writer->writeStartElement(dbNamespace,
"para");
2974 generateSimpleLink(file.get_query(), file.get_query());
2975 m_writer->writeEndElement();
2976 m_writer->writeEndElement();
2980 m_writer->writeEndElement();
2987
2988
2998 const auto en =
static_cast<
const ExampleNode *>(node);
3001 QXmlStreamWriter *currentWriter = m_writer;
3002 m_writer = startDocument(en, resolved_file.get_query());
3008 QString code = quoter.quoteTo(en->location(), QString(), QString());
3009 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
3015 m_writer = currentWriter;
3021 if (fn->overridesThis().isEmpty() || !fn
->parent()->isClassNode())
3026 if (
const FunctionNode *overrides = cn->findOverriddenFunction(fn);
3029 m_writer->writeStartElement(dbNamespace,
"para");
3030 m_writer->writeCharacters(
"Reimplements: ");
3033 generateFullName(overrides
->parent(), fullName, overrides);
3034 m_writer->writeCharacters(
".");
3035 m_writer->writeEndElement();
3041 if (
const PropertyNode *sameName = cn->findOverriddenProperty(fn); sameName && sameName
->hasDoc()) {
3042 m_writer->writeStartElement(dbNamespace,
"para");
3043 m_writer->writeCharacters(
"Reimplements an access function for property: ");
3044 QString fullName = sameName
->parent()->name() +
"::" + sameName->name();
3045 generateFullName(sameName
->parent(), fullName, sameName);
3046 m_writer->writeCharacters(
".");
3047 m_writer->writeEndElement();
3056 QList<Text> alsoList = node
->doc().alsoList();
3057 supplementAlsoList(node, alsoList);
3059 if (!alsoList.isEmpty()) {
3060 startSection(
"See Also");
3062 m_writer->writeStartElement(dbNamespace,
"para");
3063 m_writer->writeStartElement(dbNamespace,
"emphasis");
3064 m_writer->writeCharacters(
"See also ");
3065 m_writer->writeEndElement();
3068 m_writer->writeStartElement(dbNamespace,
"simplelist");
3069 m_writer->writeAttribute(
"type",
"vert");
3070 m_writer->writeAttribute(
"role",
"see-also");
3073 for (
const Text &text : alsoList) {
3074 m_writer->writeStartElement(dbNamespace,
"member");
3075 generateText(text, node);
3076 m_writer->writeEndElement();
3080 m_writer->writeEndElement();
3083 m_writer->writeEndElement();
3091
3092
3093
3094QXmlStreamWriter *
DocBookGenerator::startGenericDocument(
const Node *node,
const QString &fileName)
3097 QFile *outFile = openSubPageFile(
static_cast<
const PageNode*>(node), fileName);
3098 m_writer =
new QXmlStreamWriter(outFile);
3099 m_writer->setAutoFormatting(
false);
3101 m_writer->writeStartDocument();
3103 m_writer->writeNamespace(dbNamespace,
"db");
3104 m_writer->writeNamespace(xlinkNamespace,
"xlink");
3106 m_writer->writeNamespace(itsNamespace,
"its");
3107 m_writer->writeStartElement(dbNamespace,
"article");
3108 m_writer->writeAttribute(
"version",
"5.2");
3109 if (!m_naturalLanguage.isEmpty())
3110 m_writer->writeAttribute(
"xml:lang", m_naturalLanguage);
3114 sectionLevels.resize(0);
3123 m_hasSection =
false;
3126 QString fileName = Generator::fileName(node, fileExtension());
3127 return startGenericDocument(node, fileName);
3132 m_hasSection =
false;
3134 QString fileName = linkForExampleFile(file);
3135 return startGenericDocument(en, fileName);
3140 m_writer->writeEndElement();
3141 m_writer->writeEndDocument();
3143 m_writer->device()->close();
3144 delete m_writer->device();
3150
3151
3152
3157 const auto aggregate =
static_cast<
const Aggregate *>(node);
3161 const QString typeWord{aggregate->typeWord(
true)};
3162 if (aggregate->isNamespace()) {
3163 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3164 }
else if (aggregate->isClass()) {
3165 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3166 }
else if (aggregate->isHeader()) {
3167 title = aggregate->fullTitle();
3168 if (!aggregate->doc().title().isEmpty())
3169 titleText << aggregate->name() <<
" - "_L1 << aggregate->doc().title();
3173 m_writer = startDocument(node);
3179 if (aggregate->isClass()) {
3180 if (
auto templateDecl = node->templateDecl()) {
3186 m_writer->writeStartElement(dbNamespace,
"subtitle");
3187 if (isApiGenus(aggregate->genus()) && m_useITS)
3188 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
3189 generateTemplateDecl(&*templateDecl, aggregate);
3190 m_writer->writeCharacters(
" "_L1 + aggregate->typeWord(
false) +
" "_L1
3191 + aggregate->plainFullName());
3192 m_writer->writeEndElement();
3216 if (!aggregate->doc().isEmpty()) {
3217 startSection(
"details",
"Detailed Description");
3219 generateBody(aggregate);
3227 for (
const Section §ion : sectionVector) {
3228 if (section.members().isEmpty())
3231 startSection(section.title().toLower(), section.title());
3233 for (
const Node *member : section.members()) {
3234 if (member->nodeType() != NodeType::Class) {
3236 generateDetailedMember(member, aggregate);
3238 startSectionBegin();
3239 m_writer->writeCharacters(
"class ");
3240 generateFullName(member, aggregate);
3243 generateBrief(member);
3252 generateObsoleteMembers(sections);
3257void DocBookGenerator::generateSynopsisInfo(
const QString &key,
const QString &value)
3259 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3260 m_writer->writeAttribute(
"role", key);
3261 m_writer->writeCharacters(value);
3262 m_writer->writeEndElement();
3268 m_writer->writeTextElement(dbNamespace,
"modifier", value);
3273
3274
3284 if (!m_useDocBook52)
3294 node->isAggregate() ?
static_cast<
const Aggregate *>(node) :
nullptr;
3295 const ClassNode *classNode = node->isClass() ?
static_cast<
const ClassNode *>(node) :
nullptr;
3297 node->isFunction() ?
static_cast<
const FunctionNode *>(node) :
nullptr;
3299 node->isProperty() ?
static_cast<
const PropertyNode *>(node) :
nullptr;
3301 node->isVariable() ?
static_cast<
const VariableNode *>(node) :
nullptr;
3302 const EnumNode *enumNode = node->isEnumType() ?
static_cast<
const EnumNode *>(node) :
nullptr;
3304 node->isQmlProperty() ?
static_cast<
const QmlPropertyNode *>(node) :
nullptr;
3305 const QmlTypeNode *qcn = node->isQmlType() ?
static_cast<
const QmlTypeNode *>(node) :
nullptr;
3311 QString synopsisTag = nodeToSynopsisTag(node);
3312 m_writer->writeStartElement(dbNamespace, synopsisTag);
3317 m_writer->writeStartElement(dbNamespace,
"ooclass");
3318 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3319 m_writer->writeEndElement();
3322 m_writer->writeTextElement(dbNamespace,
"namespacename", node->plainName());
3325 m_writer->writeStartElement(dbNamespace,
"ooclass");
3326 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3327 m_writer->writeEndElement();
3329 if (!qcn->groupNames().isEmpty())
3330 m_writer->writeAttribute(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3332 m_writer->writeTextElement(dbNamespace,
"modifier",
"(Qt property)");
3334 m_writer->writeTextElement(dbNamespace,
"type", propertyNode->dataType());
3336 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3340 m_writer->writeTextElement(dbNamespace,
"modifier",
"static");
3343 m_writer->writeTextElement(dbNamespace,
"type", variableNode->dataType());
3345 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3349 m_writer->writeTextElement(dbNamespace,
"enumname", node->plainName());
3353 QString name = node->name();
3355 name.prepend(qpn->element() + QLatin1Char(
'.'));
3357 m_writer->writeTextElement(dbNamespace,
"type", qpn->dataType());
3359 m_writer->writeTextElement(dbNamespace,
"varname", name);
3367 m_writer->writeTextElement(dbNamespace,
"modifier",
"attached");
3371 m_writer->writeTextElement(dbNamespace,
"modifier",
"writable");
3375 m_writer->writeTextElement(dbNamespace,
"modifier",
"required");
3380 generateModifier(
"[read-only]");
3384 generateModifier(
"[default]");
3388 if (functionNode->virtualness() !=
"non")
3389 generateModifier(
"virtual");
3390 if (functionNode->isConst())
3391 generateModifier(
"const");
3392 if (functionNode->isStatic())
3393 generateModifier(
"static");
3398 if (functionNode->returnType() ==
"void")
3399 m_writer->writeEmptyElement(dbNamespace,
"void");
3401 m_writer->writeTextElement(dbNamespace,
"type", functionNode->returnTypeString());
3406 QString name = node->plainName();
3407 if (name.endsWith(
"()"))
3409 m_writer->writeTextElement(dbNamespace,
"methodname", name);
3413 m_writer->writeEmptyElement(dbNamespace,
"void");
3418 for (
int i = 0; i < lp
.count(); ++i) {
3420 m_writer->writeStartElement(dbNamespace,
"methodparam");
3422 m_writer->writeTextElement(dbNamespace,
"type", parameter.type());
3424 m_writer->writeTextElement(dbNamespace,
"parameter", parameter.name());
3426 if (!parameter.defaultValue().isEmpty()) {
3427 m_writer->writeTextElement(dbNamespace,
"initializer", parameter.defaultValue());
3430 m_writer->writeEndElement();
3434 if (functionNode->isImplicitlyGenerated())
3435 generateModifier(
"implicit");
3436 else if (functionNode->isExplicitlyDefaulted())
3437 generateModifier(
"default");
3438 else if (functionNode->isDeletedAsWritten())
3439 generateModifier(
"delete");
3440 if (functionNode->isFinal())
3441 generateModifier(
"final");
3442 if (functionNode->isOverride())
3443 generateModifier(
"override");
3445 m_writer->writeTextElement(dbNamespace,
"typedefname", node->plainName());
3449 QStringLiteral(
"Unexpected node type in generateDocBookSynopsis: %1")
3450 .arg(node->nodeTypeString()));
3456 for (
const EnumItem &item : enumNode->items()) {
3457 m_writer->writeStartElement(dbNamespace,
"enumitem");
3459 m_writer->writeTextElement(dbNamespace,
"enumidentifier", item.name());
3461 m_writer->writeTextElement(dbNamespace,
"enumvalue", item.value());
3463 m_writer->writeEndElement();
3467 if (enumNode->items().isEmpty()) {
3470 m_writer->writeStartElement(dbNamespace,
"enumitem");
3472 m_writer->writeEmptyElement(dbNamespace,
"enumidentifier");
3474 m_writer->writeEndElement();
3485 generateSynopsisInfo(
"meta", functionNode->metanessString());
3488 generateSynopsisInfo(
"overload",
"overload");
3489 generateSynopsisInfo(
"overload-number",
3490 QString::number(functionNode->overloadNumber()));
3493 if (functionNode->isRef())
3494 generateSynopsisInfo(
"refness", QString::number(1));
3495 else if (functionNode->isRefRef())
3496 generateSynopsisInfo(
"refness", QString::number(2));
3499 QStringList associatedProperties;
3500 const auto &nodes = functionNode->associatedProperties();
3501 for (
const Node *n : nodes) {
3502 const auto pn =
static_cast<
const PropertyNode *>(n);
3503 associatedProperties << pn->name();
3505 associatedProperties.sort();
3506 generateSynopsisInfo(
"associated-property",
3507 associatedProperties.join(QLatin1Char(
',')));
3513 signature +=
" final";
3515 signature +=
" override";
3517 signature +=
" = 0";
3519 signature +=
" = default";
3521 signature +=
" = delete";
3522 if (
const auto &req = functionNode->trailingRequiresClause(); req && !req->isEmpty())
3523 signature +=
" requires " + *req;
3524 generateSynopsisInfo(
"signature", signature);
3530 case Access::Public:
3531 generateSynopsisInfo(
"access",
"public");
3533 case Access::Protected:
3534 generateSynopsisInfo(
"access",
"protected");
3536 case Access::Private:
3537 generateSynopsisInfo(
"access",
"private");
3542 if (node->isAbstract())
3543 generateSynopsisInfo(
"abstract",
"true");
3548 case Status::Active:
3549 generateSynopsisInfo(
"status",
"active");
3551 case Status::Preliminary:
3552 generateSynopsisInfo(
"status",
3555 case Status::Deprecated:
3556 generateSynopsisInfo(
"status",
"deprecated");
3558 case Status::Internal:
3559 case Status::InternalAuto:
3560 generateSynopsisInfo(
"status",
"internal");
3563 generateSynopsisInfo(
"status",
"main");
3570 if (aggregate->includeFile()) generateSynopsisInfo(
"headers", *aggregate->includeFile());
3573 if (!aggregate->since().isEmpty())
3574 generateSynopsisInfo(
"since", formatSince(aggregate));
3578 if (!aggregate->physicalModuleName().isEmpty()) {
3580 m_qdb->getCollectionNode(aggregate->physicalModuleName(), NodeType::Module);
3582 if (
const auto result = cmakeRequisite(cn)) {
3583 generateSynopsisInfo(
"cmake-find-package", result->first);
3584 generateSynopsisInfo(
"cmake-target-link-libraries", result->second);
3587 if (cn && !cn->qtVariable().isEmpty())
3588 generateSynopsisInfo(
"qmake",
"QT += " + cn->qtVariable());
3594 auto *classe =
const_cast<ClassNode *>(
static_cast<
const ClassNode *>(aggregate));
3595 if (classe && classe->isQmlNativeType() && !classe->isInternal()) {
3596 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3597 m_writer->writeAttribute(
"role",
"nativeTypeFor");
3599 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
3602 for (
auto item : std::as_const(nativeTypes)) {
3603 const Node *otherNode{
nullptr};
3604 Atom a = Atom(Atom::LinkNode, Utilities::stringForNode(item));
3605 const QString &link = getAutoLink(&a, aggregate, &otherNode);
3606 generateSimpleLink(link, item->name());
3609 m_writer->writeEndElement();
3613 QList<RelatedClass>::ConstIterator r;
3614 if (!classe->baseClasses().isEmpty()) {
3615 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3616 m_writer->writeAttribute(
"role",
"inherits");
3618 r = classe->baseClasses().constBegin();
3620 while (r != classe->baseClasses().constEnd()) {
3622 generateFullName((*r).m_node, classe);
3624 if ((*r).m_access == Access::Protected) {
3625 m_writer->writeCharacters(
" (protected)");
3626 }
else if ((*r).m_access == Access::Private) {
3627 m_writer->writeCharacters(
" (private)");
3629 m_writer->writeCharacters(
3630 TextUtils::comma(index++, classe->baseClasses().size()));
3635 m_writer->writeEndElement();
3640 if (!classe->derivedClasses().isEmpty()) {
3641 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3642 m_writer->writeAttribute(
"role",
"inheritedBy");
3643 generateSortedNames(classe, classe->derivedClasses());
3644 m_writer->writeEndElement();
3653 QString logicalModuleVersion;
3655 m_qdb->getCollectionNode(qcn->logicalModuleName(), qcn->nodeType());
3657 logicalModuleVersion = collection->logicalModuleVersion();
3659 logicalModuleVersion = qcn->logicalModuleVersion();
3661 QStringList importText;
3662 importText <<
"import " + qcn->logicalModuleName();
3663 if (!logicalModuleVersion.isEmpty())
3664 importText << logicalModuleVersion;
3665 generateSynopsisInfo(
"import", importText.join(
' '));
3668 if (!qcn->since().isEmpty())
3669 generateSynopsisInfo(
"since", formatSince(qcn));
3672 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
3680 QStringList knownTypeNames{qcn->name()};
3682 knownTypeNames << base->name();
3687 if (!subs.isEmpty()) {
3688 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3689 m_writer->writeAttribute(
"role",
"inheritedBy");
3690 generateSortedQmlNames(qcn, knownTypeNames, subs);
3691 m_writer->writeEndElement();
3697 const Node *otherNode =
nullptr;
3699 QString link = getAutoLink(&a, base, &otherNode);
3701 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3702 m_writer->writeAttribute(
"role",
"inherits");
3703 generateSimpleLink(link, base->name());
3705 for (
const auto sub : std::as_const(subs)) {
3706 if (knownTypeNames.contains(sub->name())) {
3707 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
3711 m_writer->writeEndElement();
3719 const Node *otherNode =
nullptr;
3721 QString link = getAutoLink(&a, cn, &otherNode);
3723 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3724 m_writer->writeAttribute(
"role",
"nativeType");
3725 generateSimpleLink(link, cn->name());
3726 m_writer->writeEndElement();
3733 case Node::UnspecifiedSafeness:
3734 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3736 case Node::NonReentrant:
3737 generateSynopsisInfo(
"threadsafeness",
"non-reentrant");
3739 case Node::Reentrant:
3740 generateSynopsisInfo(
"threadsafeness",
"reentrant");
3742 case Node::ThreadSafe:
3743 generateSynopsisInfo(
"threadsafeness",
"thread safe");
3746 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3751 if (!node->physicalModuleName().isEmpty())
3752 generateSynopsisInfo(
"module", node->physicalModuleName());
3755 if (classNode && !classNode->groupNames().isEmpty()) {
3756 generateSynopsisInfo(
"groups", classNode->groupNames().join(QLatin1Char(
',')));
3757 }
else if (qcn && !qcn->groupNames().isEmpty()) {
3758 generateSynopsisInfo(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3763 for (
const Node *fnNode : propertyNode->getters()) {
3765 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3766 generateSynopsisInfo(
"getter", funcNode->name());
3769 for (
const Node *fnNode : propertyNode->setters()) {
3771 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3772 generateSynopsisInfo(
"setter", funcNode->name());
3775 for (
const Node *fnNode : propertyNode->resetters()) {
3777 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3778 generateSynopsisInfo(
"resetter", funcNode->name());
3781 for (
const Node *fnNode : propertyNode->notifiers()) {
3783 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3784 generateSynopsisInfo(
"notifier", funcNode->name());
3789 m_writer->writeEndElement();
3795 m_writer->writeStartElement(dbNamespace,
"typedefsynopsis");
3798 m_writer->writeTextElement(dbNamespace,
"typedefname",
3799 enumNode->flagsType()->fullDocumentName());
3802 m_writer->writeEndElement();
3813 return node->name().mid(4);
3814 return node->name();
3818
3819
3820
3821void DocBookGenerator::typified(
const QString &string,
const Node *relative,
bool trailingSpace,
3826 QString pendingWord;
3828 for (
int i = 0; i <= string.size(); ++i) {
3830 if (i != string.size())
3833 QChar lower = ch.toLower();
3834 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
3835 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
3838 if (!pendingWord.isEmpty()) {
3839 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
3840 if (generateType && isProbablyType) {
3842 m_writer->writeCharacters(result);
3846 const Node *n = m_qdb->findTypeNode(pendingWord, relative, Genus::DontCare);
3851 href = linkForNode(n, relative);
3854 m_writer->writeStartElement(dbNamespace,
"type");
3856 m_writer->writeCharacters(pendingWord);
3858 generateSimpleLink(href, pendingWord);
3859 m_writer->writeEndElement();
3861 result += pendingWord;
3864 pendingWord.clear();
3866 if (ch.unicode() !=
'\0')
3871 if (trailingSpace && string.size()) {
3872 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
3873 result += QLatin1Char(
' ');
3876 m_writer->writeCharacters(result);
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3896 const QStringList &concepts,
3897 const Node *relative)
3899 if (concepts.isEmpty()) {
3900 m_writer->writeCharacters(text);
3904 QStringList sorted = concepts;
3905 std::sort(sorted.begin(), sorted.end(),
3906 [](
const QString &a,
const QString &b) {
return a.size() > b.size(); });
3912 struct Match { qsizetype offset; qsizetype length; QString name; QString target; };
3913 QList<Match> matches;
3914 QList<
bool> occupied(text.size(),
false);
3916 for (
const QString &concept_name : sorted) {
3917 const QString unqualified = concept_name.section(
"::"_L1, -1);
3918 const QRegularExpression re(
"\\b"_L1
3919 + QRegularExpression::escape(unqualified) +
"\\b"_L1);
3920 auto it = re.globalMatch(text);
3921 while (it.hasNext()) {
3922 const auto m = it.next();
3923 const qsizetype start = m.capturedStart();
3924 const qsizetype len = m.capturedLength();
3926 for (qsizetype i = start; i < start + len; ++i) {
3934 for (qsizetype i = start; i < start + len; ++i)
3936 matches.append({start, len, unqualified, concept_name});
3940 std::sort(matches.begin(), matches.end(),
3941 [](
const Match &a,
const Match &b) {
return a.offset < b.offset; });
3944 for (
const auto &m : matches) {
3946 m_writer->writeCharacters(text.mid(pos, m.offset - pos));
3947 const Node *n = m_qdb->findConceptNode(m.target);
3949 generateSimpleLink(linkForNode(n, relative), m.name);
3951 m_writer->writeCharacters(m.name);
3952 pos = m.offset + m.length;
3954 if (pos < text.size())
3955 m_writer->writeCharacters(text.mid(pos));
3959
3960
3961
3962
3963
3964
3965
3966
3967
3969 const Node *relative)
3973 if (param.template_declaration) {
3978 m_writer->writeCharacters(
"template <"_L1);
3980 for (
const auto &sub : param.template_declaration->parameters) {
3981 if (sub.sfinae_constraint)
3984 m_writer->writeCharacters(
", "_L1);
3985 generateTemplateParameter(sub, relative);
3988 m_writer->writeCharacters(
"> "_L1);
3991 switch (param
.kind) {
3993 if (param.concept_name) {
3994 const QString fq = QString::fromStdString(*param.concept_name);
3995 const QString unqualified = fq.section(
"::"_L1, -1);
3996 const Node *n = m_qdb->findConceptNode(fq);
3998 generateSimpleLink(linkForNode(n, relative), unqualified);
4002 m_writer->writeCharacters(fq);
4004 m_writer->writeCharacters(
"typename"_L1);
4007 case RelaxedTemplateParameter::Kind::NonTypeTemplateParameter:
4008 if (!decl.type.empty())
4009 typified(QString::fromStdString(decl.type), relative,
false,
true);
4011 case RelaxedTemplateParameter::Kind::TemplateTemplateParameter:
4012 m_writer->writeCharacters(
"typename"_L1);
4016 if (param.is_parameter_pack)
4017 m_writer->writeCharacters(
"..."_L1);
4019 if (!decl
.name.empty()) {
4020 m_writer->writeCharacters(
" "_L1);
4021 m_writer->writeCharacters(QString::fromStdString(decl.name));
4025 m_writer->writeCharacters(
" = "_L1);
4028 typified(QString::fromStdString(decl.initializer), relative,
false,
true);
4030 m_writer->writeCharacters(QString::fromStdString(decl.initializer));
4036
4037
4038
4039
4040
4041
4042
4043
4044
4046 const Node *relative)
4054 m_writer->writeCharacters(
"template <"_L1);
4056 m_writer->writeCharacters(
"\n"_L1);
4059 for (
const auto ¶m : templateDecl->parameters) {
4060 if (param.sfinae_constraint)
4063 m_writer->writeCharacters(multiline ?
",\n"_L1 :
", "_L1);
4065 m_writer->writeCharacters(
" "_L1);
4066 generateTemplateParameter(param, relative);
4071 m_writer->writeCharacters(
"\n"_L1);
4072 m_writer->writeCharacters(
">"_L1);
4074 if (templateDecl->requires_clause && !templateDecl->requires_clause->empty()) {
4075 m_writer->writeCharacters(
" requires "_L1);
4076 QStringList concepts;
4077 concepts.reserve(
int(templateDecl->referenced_concepts.size()));
4078 for (
const auto &s : templateDecl->referenced_concepts)
4079 concepts.append(QString::fromStdString(s));
4080 generateRequiresClauseText(QString::fromStdString(*templateDecl->requires_clause),
4081 concepts, relative);
4086 bool generateNameLink)
4090 QString name = taggedNode(node);
4092 if (!generateNameLink) {
4093 m_writer->writeCharacters(name);
4097 m_writer->writeStartElement(dbNamespace,
"emphasis");
4098 m_writer->writeAttribute(
"role",
"bold");
4099 generateSimpleLink(linkForNode(node, relative), name);
4100 m_writer->writeEndElement();
4104 bool generateExtra,
bool generateType)
4106 const QString &pname = parameter.name();
4107 const QString &ptype = parameter.type();
4109 qsizetype insertPos = !pname.isEmpty() ? parameter.nameInsertionPoint() : -1;
4110 if (!pname.isEmpty()) {
4111 if (insertPos >= 0) {
4113 typified(ptype.left(insertPos), relative,
false, generateType);
4115 typified(ptype, relative,
true, generateType);
4122 if (generateExtra || pname.isEmpty()) {
4123 m_writer->writeStartElement(dbNamespace,
"emphasis");
4124 m_writer->writeCharacters(paramName);
4125 m_writer->writeEndElement();
4129 typified(ptype.mid(insertPos), relative,
false, generateType);
4131 const QString &pvalue = parameter.defaultValue();
4132 if (generateExtra && !pvalue.isEmpty())
4133 m_writer->writeCharacters(
" = " + pvalue);
4145 const int MaxEnumValues = 6;
4147 if (generateExtra) {
4148 if (
auto extra = CodeMarker::extraSynopsis(node, style); !extra.isEmpty()) {
4149 generateExtraSynopsis(extra);
4150 m_writer->writeCharacters(u" "_s);
4155 QString namePrefix {};
4159 namePrefix = taggedNode(node->parent()) +
"::";
4164 case NodeType::Namespace:
4165 m_writer->writeCharacters(
"namespace ");
4166 m_writer->writeCharacters(namePrefix);
4167 generateSynopsisName(node, relative, generateNameLink);
4169 case NodeType::Class:
4170 m_writer->writeCharacters(
"class ");
4171 m_writer->writeCharacters(namePrefix);
4172 generateSynopsisName(node, relative, generateNameLink);
4178 if (
auto templateDecl = func->templateDecl()) {
4179 generateTemplateDecl(&*templateDecl, relative);
4180 if (templateDecl->visibleParameterCount() > QDoc::MultilineTemplateParamThreshold)
4181 m_writer->writeCharacters(
"\n"_L1);
4183 m_writer->writeCharacters(
" "_L1);
4189 if (!func->isNonvirtual())
4190 m_writer->writeCharacters(QStringLiteral(
"virtual "));
4194 if (style != Section::AllMembers && !func->returnType().isEmpty())
4195 typified(func->returnTypeString(), relative,
true, generateType);
4196 m_writer->writeCharacters(namePrefix);
4197 generateSynopsisName(node, relative, generateNameLink);
4200 m_writer->writeCharacters(QStringLiteral(
"("));
4203 for (
int i = 0; i < parameters
.count(); i++) {
4205 m_writer->writeCharacters(QStringLiteral(
", "));
4206 generateParameter(parameters
.at(i
), relative, generateExtra, generateType);
4209 m_writer->writeCharacters(QStringLiteral(
")"));
4212 if (func->isConst())
4213 m_writer->writeCharacters(QStringLiteral(
" const"));
4219 synopsis += QStringLiteral(
" final");
4221 synopsis += QStringLiteral(
" override");
4223 synopsis += QStringLiteral(
" = 0");
4225 synopsis += QStringLiteral(
" &");
4227 synopsis += QStringLiteral(
" &&");
4228 m_writer->writeCharacters(synopsis);
4230 if (!func->returnType().isEmpty() && func->returnType() !=
"void") {
4231 m_writer->writeCharacters(QStringLiteral(
" : "));
4232 typified(func->returnTypeString(), relative,
false, generateType);
4237 synopsis +=
" &"_L1;
4238 else if (func->isRefRef())
4239 synopsis +=
" &&"_L1;
4240 m_writer->writeCharacters(synopsis);
4242 if (
const auto &req = func->trailingRequiresClause(); req && !req->isEmpty()) {
4243 m_writer->writeCharacters(
" requires "_L1);
4244 generateRequiresClauseText(*req, func->referencedConcepts(), relative);
4249 const auto enume =
static_cast<
const EnumNode *>(node);
4250 if (!enume->isAnonymous()) {
4251 m_writer->writeCharacters(
"enum "_L1);
4252 m_writer->writeCharacters(namePrefix);
4253 generateSynopsisName(node, relative, generateNameLink);
4254 }
else if (generateNameLink) {
4255 m_writer->writeStartElement(dbNamespace,
"emphasis");
4256 m_writer->writeAttribute(
"role",
"bold");
4257 generateSimpleLink(linkForNode(node, relative),
"enum");
4258 m_writer->writeEndElement();
4260 m_writer->writeCharacters(
"enum"_L1);
4267 QStringList documentedItems = enume->doc().enumItemNames();
4268 if (documentedItems.isEmpty()) {
4269 const auto &enumItems = enume->items();
4270 for (
const auto &item : enumItems)
4271 documentedItems << item.name();
4273 const QStringList omitItems = enume->doc().omitEnumItemNames();
4274 for (
const auto &item : omitItems)
4275 documentedItems.removeAll(item);
4277 if (documentedItems.size() > MaxEnumValues) {
4279 const QString last = documentedItems.last();
4280 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
4281 documentedItems +=
"…";
4282 documentedItems += last;
4284 synopsis += documentedItems.join(QLatin1String(
", "));
4286 if (!documentedItems.isEmpty())
4287 synopsis += QLatin1Char(
' ');
4288 synopsis += QLatin1Char(
'}');
4290 m_writer->writeCharacters(synopsis);
4294 if (
auto templateDecl = node->templateDecl()) {
4295 generateTemplateDecl(&*templateDecl, relative);
4296 if (templateDecl->visibleParameterCount() > QDoc::MultilineTemplateParamThreshold)
4297 m_writer->writeCharacters(
"\n"_L1);
4299 m_writer->writeCharacters(
" "_L1);
4302 m_writer->writeCharacters(namePrefix);
4303 generateSynopsisName(node, relative, generateNameLink);
4306 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
4307 m_writer->writeCharacters(
"flags ");
4308 m_writer->writeCharacters(namePrefix);
4309 generateSynopsisName(node, relative, generateNameLink);
4312 const auto property =
static_cast<
const PropertyNode *>(node);
4313 m_writer->writeCharacters(namePrefix);
4314 generateSynopsisName(node, relative, generateNameLink);
4315 m_writer->writeCharacters(
" : ");
4316 typified(property->qualifiedDataType(), relative,
false, generateType);
4319 const auto variable =
static_cast<
const VariableNode *>(node);
4321 generateSynopsisName(node, relative, generateNameLink);
4322 m_writer->writeCharacters(
" : ");
4323 typified(variable->dataType(), relative,
false, generateType);
4325 typified(variable->leftType(), relative,
false, generateType);
4326 m_writer->writeCharacters(
" ");
4327 m_writer->writeCharacters(namePrefix);
4328 generateSynopsisName(node, relative, generateNameLink);
4329 m_writer->writeCharacters(variable->rightType());
4333 m_writer->writeCharacters(namePrefix);
4334 generateSynopsisName(node, relative, generateNameLink);
4349 if (nativeEnum && nativeEnum
->enumNode() && !enumValue.startsWith(
"%1."_L1.arg(nativeEnum->prefix()))) {
4350 m_writer->writeCharacters(
"%1.%2"_L1.arg(nativeEnum->prefix(), enumValue));
4356 && enumValue.section(
' ', 0, 0).contains(
'.'_L1))) {
4357 m_writer->writeCharacters(enumValue);
4361 QList<
const Node *> parents;
4363 parents.prepend(node);
4368 if (
static_cast<
const EnumNode *>(relative)->isScoped())
4369 parents << relative;
4371 m_writer->writeStartElement(dbNamespace,
"code");
4372 for (
auto parent : parents) {
4373 generateSynopsisName(parent, relative,
true);
4374 m_writer->writeCharacters((relative->genus() == Genus::QML) ?
"."_L1 :
"::"_L1);
4377 m_writer->writeCharacters(enumValue);
4378 m_writer->writeEndElement();
4382
4383
4384
4389 Q_ASSERT(node && !node->name().isEmpty());
4395 m_writer->writeStartElement(dbNamespace,
"note");
4402 m_writer->writeStartElement(dbNamespace,
"para");
4403 m_writer->writeCharacters(
4404 "This function can be invoked via the meta-object system and from QML. See ");
4405 generateSimpleLink(node->url(),
"Q_INVOKABLE");
4406 m_writer->writeCharacters(
".");
4407 m_writer->writeEndElement();
4411 m_writer->writeTextElement(
4412 dbNamespace,
"para",
4413 "This is a private signal. It can be used in signal connections but "
4414 "cannot be emitted by the user.");
4418 QString handler(node->name());
4419 int prefixLocation = handler.lastIndexOf(
'.', -2) + 1;
4420 handler[prefixLocation] = handler[prefixLocation].toTitleCase();
4421 handler.insert(prefixLocation, QLatin1String(
"on"));
4422 m_writer->writeStartElement(dbNamespace,
"para");
4423 m_writer->writeCharacters(
"The corresponding handler is ");
4424 m_writer->writeTextElement(dbNamespace,
"code", handler);
4425 m_writer->writeCharacters(
".");
4426 m_writer->writeEndElement();
4434 const auto *fn =
static_cast<
const FunctionNode *>(node);
4435 auto nodes = fn->associatedProperties();
4436 if (nodes.isEmpty())
4441 QMap<PropertyNode::FunctionRole, QList<
const PropertyNode *>> roleGroups;
4442 for (
const auto *n : std::as_const(nodes)) {
4443 const auto *pn =
static_cast<
const PropertyNode *>(n);
4444 PropertyNode::FunctionRole role = pn->role(fn);
4445 roleGroups[role].append(pn);
4457 for (
auto role : roleOrder) {
4458 const auto it = roleGroups.constFind(role);
4459 if (it == roleGroups.cend())
4462 const auto &properties = it.value();
4467 msg = QStringLiteral(
"Getter function");
4470 msg = QStringLiteral(
"Setter function");
4473 msg = QStringLiteral(
"Resetter function");
4476 msg = QStringLiteral(
"Notifier signal");
4479 msg = QStringLiteral(
"Bindable function");
4485 m_writer->writeStartElement(dbNamespace,
"para");
4486 if (properties.size() == 1) {
4487 const auto *pn = properties.first();
4488 m_writer->writeCharacters(msg +
" for property ");
4489 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4490 m_writer->writeCharacters(
". ");
4492 m_writer->writeCharacters(msg +
" for properties ");
4493 for (qsizetype i = 0; i < properties.size(); ++i) {
4494 const auto *pn = properties.at(i);
4495 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4496 m_writer->writeCharacters(TextUtils::separator(i, properties.size()));
4498 m_writer->writeCharacters(
" ");
4500 m_writer->writeEndElement();
4507 const Node *linkNode;
4509 QString link = getAutoLink(&linkAtom, node, &linkNode);
4510 m_writer->writeStartElement(dbNamespace,
"para");
4511 m_writer->writeCharacters(
"This property supports ");
4512 generateSimpleLink(link,
"QProperty");
4513 m_writer->writeCharacters(
" bindings.");
4514 m_writer->writeEndElement();
4519 const auto *func =
static_cast<
const FunctionNode *>(node);
4522 if (func->isPrimaryOverload())
4525 m_writer->writeStartElement(dbNamespace,
"para");
4527 if (func->isSignal() || func->isSlot()) {
4528 auto writeDocBookLink = [&](
const QString &target,
const QString &label) {
4529 const Node *linkNode =
nullptr;
4531 const QString &link = getAutoLink(&linkAtom, node, &linkNode);
4533 m_writer->writeStartElement(dbNamespace,
"link");
4534 if (!link.isEmpty() && linkNode) {
4535 m_writer->writeAttribute(xlinkNamespace,
"href", link);
4537 m_writer->writeAttribute(dbNamespace,
"linkend", target);
4539 m_writer->writeCharacters(label);
4540 m_writer->writeEndElement();
4543 const QString &functionType = func->isSignal() ?
"signal" :
"slot";
4544 const QString &configKey = func->isSignal() ?
"overloadedsignalstarget" :
"overloadedslotstarget";
4545 const QString &defaultTarget = func->isSignal() ?
"connecting-overloaded-signals" :
"connecting-overloaded-slots";
4546 const QString &linkTarget = Config::instance().get(configKey).asString(defaultTarget);
4548 m_writer->writeCharacters(
"This " + functionType +
" is overloaded. ");
4550 QString snippet = generateOverloadSnippet(func);
4551 if (!snippet.isEmpty()) {
4552 m_writer->writeCharacters(
"To connect to this " + functionType +
":");
4553 m_writer->writeEndElement();
4555 m_writer->writeStartElement(dbNamespace,
"programlisting");
4556 m_writer->writeCharacters(snippet);
4557 m_writer->writeEndElement();
4562 m_writer->writeStartElement(dbNamespace,
"para");
4563 if (!linkTarget.isEmpty()) {
4564 m_writer->writeCharacters(
"For more examples and approaches, see ");
4565 writeDocBookLink(linkTarget,
"connecting to overloaded " + functionType +
"s");
4566 m_writer->writeCharacters(
".");
4568 }
else if (!linkTarget.isEmpty()) {
4569 m_writer->writeCharacters(
"For more examples and approaches, see ");
4570 writeDocBookLink(linkTarget,
"connecting to overloaded " + functionType +
"s");
4571 m_writer->writeCharacters(
".");
4575 const auto &args = node
->doc().overloadList();
4576 if (args.first().first.isEmpty()) {
4577 m_writer->writeCharacters(
"This is an overloaded function.");
4579 QString target = args.first().first;
4582 if (!target.contains(
"::")) {
4585 target = parent->name() +
"::" + target;
4588 m_writer->writeCharacters(
"This function overloads ");
4590 const Node *linkNode =
nullptr;
4592 QString link = getAutoLink(&linkAtom, node, &linkNode);
4593 if (!link.isEmpty() && linkNode)
4594 generateSimpleLink(link, target);
4596 m_writer->writeCharacters(target);
4597 m_writer->writeCharacters(
".");
4601 m_writer->writeEndElement();
4610 m_writer->writeEndElement();
4618 bool closeSupplementarySection =
false;
4622 const QList<Node *> &collective = scn->collective();
4624 bool firstFunction =
true;
4625 for (
const auto *sharedNode : collective) {
4626 if (firstFunction) {
4627 startSectionBegin(sharedNode);
4629 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4630 m_writer->writeAttribute(
"renderas",
"sect2");
4631 writeXmlId(sharedNode);
4634 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4636 generateSynopsis(sharedNode, relative, Section::Details);
4638 if (firstFunction) {
4640 firstFunction =
false;
4642 m_writer->writeEndElement();
4648 if (node->isEnumType(Genus::CPP) && (etn =
static_cast<
const EnumNode *>(node))->flagsType()) {
4649 startSectionBegin(node);
4651 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4655 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4656 m_writer->writeAttribute(
"renderas",
"sect2");
4658 m_writer->writeEndElement();
4661 startSectionBegin(node);
4663 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4668 Q_ASSERT(m_hasSection);
4677 closeSupplementarySection =
true;
4678 startSection(
"",
"Notes");
4682 const auto *func =
static_cast<
const FunctionNode *>(node);
4683 if (func->hasOverloads() && (func->isSignal() || func->isSlot()))
4691 const auto property =
static_cast<
const PropertyNode *>(node);
4700 m_writer->writeStartElement(dbNamespace,
"para");
4702 m_writer->writeStartElement(dbNamespace,
"emphasis");
4703 m_writer->writeAttribute(
"role",
"bold");
4704 m_writer->writeCharacters(
"Access functions:");
4706 m_writer->writeEndElement();
4708 m_writer->writeEndElement();
4710 generateSectionList(section, node);
4717 m_writer->writeStartElement(dbNamespace,
"para");
4719 m_writer->writeStartElement(dbNamespace,
"emphasis");
4720 m_writer->writeAttribute(
"role",
"bold");
4721 m_writer->writeCharacters(
"Notifier signal:");
4723 m_writer->writeEndElement();
4725 m_writer->writeEndElement();
4727 generateSectionList(notifiers, node);
4731 const auto en =
static_cast<
const EnumNode *>(node);
4733 if (m_qflagsHref.isEmpty()) {
4734 Node *qflags = m_qdb->findClassNode(QStringList(
"QFlags"));
4736 m_qflagsHref = linkForNode(qflags,
nullptr);
4739 if (en->flagsType()) {
4740 m_writer->writeStartElement(dbNamespace,
"para");
4741 m_writer->writeCharacters(
"The ");
4742 m_writer->writeStartElement(dbNamespace,
"code");
4743 m_writer->writeCharacters(en->flagsType()->name());
4744 m_writer->writeEndElement();
4745 m_writer->writeCharacters(
" type is a typedef for ");
4746 m_writer->writeStartElement(dbNamespace,
"code");
4747 generateSimpleLink(m_qflagsHref,
"QFlags");
4748 m_writer->writeCharacters(
"<" + en->name() +
">. ");
4749 m_writer->writeEndElement();
4750 m_writer->writeCharacters(
"It stores an OR combination of ");
4751 m_writer->writeStartElement(dbNamespace,
"code");
4752 m_writer->writeCharacters(en->name());
4753 m_writer->writeEndElement();
4754 m_writer->writeCharacters(
" values.");
4755 m_writer->writeEndElement();
4760 if (closeSupplementarySection)
4771 bool useObsoleteMembers)
4776 if (!members.isEmpty()) {
4777 bool hasPrivateSignals =
false;
4778 bool isInvokable =
false;
4780 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4782 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4785 NodeVector::ConstIterator m = members.constBegin();
4786 while (m != members.constEnd()) {
4787 if ((*m)->access() == Access::Private) {
4792 m_writer->writeStartElement(dbNamespace,
"listitem");
4794 m_writer->writeStartElement(dbNamespace,
"para");
4797 generateSynopsis(*m, relative, section
.style());
4798 if ((*m)->isFunction()) {
4800 if (fn->isPrivateSignal())
4801 hasPrivateSignals =
true;
4802 else if (fn->isInvokable())
4806 m_writer->writeEndElement();
4808 m_writer->writeEndElement();
4814 m_writer->writeEndElement();
4817 if (hasPrivateSignals)
4824 && !section.inheritedMembers().isEmpty()) {
4825 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4827 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4830 generateSectionInheritedList(section, relative);
4832 m_writer->writeEndElement();
4840 QList<std::pair<
const Aggregate *,
int>>::ConstIterator p = section.inheritedMembers().constBegin();
4841 while (p != section.inheritedMembers().constEnd()) {
4842 m_writer->writeStartElement(dbNamespace,
"listitem");
4843 m_writer->writeCharacters(QString::number((*p).second) + u' ');
4844 if ((*p).second == 1)
4845 m_writer->writeCharacters(section.singular());
4847 m_writer->writeCharacters(section.plural());
4848 m_writer->writeCharacters(
" inherited from ");
4849 generateSimpleLink(fileName((*p).first) +
'#'
4850 + Generator::cleanRef(section.title().toLower()),
4851 (*p).first->plainFullName(relative));
4857
4858
4859
4863 Q_ASSERT(m_writer ==
nullptr);
4864 m_writer = startDocument(pn);
4875
4876
4881 Q_ASSERT(m_writer ==
nullptr);
4882 m_writer = startDocument(qcn);
4885 QString title = qcn->name();
4887 title.append(
" QML Value Type");
4889 title.append(
" QML Type");
4892 title.append(
" (Singleton)");
4894 title.append(
" (Uncreatable)");
4905 m_writer->writeStartElement(dbNamespace,
"note");
4906 m_writer->writeStartElement(dbNamespace,
"para");
4907 m_writer->writeStartElement(dbNamespace,
"emphasis");
4908 m_writer->writeAttribute(
"role",
"bold");
4909 m_writer->writeCharacters(
"Note: ");
4910 m_writer->writeEndElement();
4911 if (qcn->isSingleton())
4912 m_writer->writeCharacters(
"This type is a QML singleton. "
4913 "There is only one instance of this type in the QML engine.");
4915 m_writer->writeCharacters(
"This is an uncreatable type. "
4916 "It cannot be instantiated in QML.");
4917 m_writer->writeEndElement();
4918 m_writer->writeEndElement();
4921 startSection(
"details",
"Detailed Description");
4929 for (
const auto §ion : sections.detailsSections()) {
4930 if (!section.isEmpty()) {
4931 startSection(section.title().toLower(), section.title());
4933 for (
const auto &member : section.members())
4934 generateDetailedQmlMember(member, qcn);
4940 generateObsoleteQmlMembers(sections);
4949
4950
4951
4958 if (!title.isEmpty())
4962 title += n->element() + QLatin1Char(
'.');
4963 title += n->name() +
" : " + n->dataType();
4968 auto generateQmlMethodTitle = [&](
Node *node) {
4973 const auto *scn =
static_cast<
const SharedCommentNode *>(node);
4976 if (!scn->name().isEmpty())
4977 heading = scn->name() +
" group";
4979 heading = node->name();
4980 startSection(scn, heading);
4985 const QList<Node *> sharedNodes = scn->collective();
4986 for (
const auto &sharedNode : sharedNodes) {
4987 if (sharedNode->isQmlProperty()) {
4988 auto *qpn =
static_cast<QmlPropertyNode *>(sharedNode);
4990 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4991 m_writer->writeAttribute(
"renderas",
"sect2");
4993 m_writer->writeCharacters(getQmlPropertyTitle(qpn));
4994 m_writer->writeEndElement();
4997 generateDocBookSynopsis(qpn);
5001 auto qpn =
static_cast<QmlPropertyNode *>(node);
5002 startSection(qpn, getQmlPropertyTitle(qpn));
5006 const QList<Node *> &sharedNodes = scn->collective();
5011 for (
const auto &sharedNode : sharedNodes) {
5013 if (!sharedNode->isFunction(Genus::QML) && !sharedNode->isQmlProperty()) {
5019 startSectionBegin(sharedNode);
5021 m_writer->writeStartElement(dbNamespace,
"bridgehead");
5022 m_writer->writeAttribute(
"renderas",
"sect2");
5026 if (sharedNode->isFunction(Genus::QML))
5027 generateQmlMethodTitle(sharedNode);
5028 else if (sharedNode->isQmlProperty())
5029 m_writer->writeCharacters(
5030 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(sharedNode)));
5036 m_writer->writeEndElement();
5037 generateDocBookSynopsis(sharedNode);
5043 startSectionBegin(refForNode(node));
5046 generateQmlMethodTitle(node);
5047 else if (node->isQmlProperty())
5048 m_writer->writeCharacters(
5049 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(node)));
5054 startSectionBegin(node);
5058 startSectionBegin(node);
5059 generateQmlMethodTitle(node);
5073
5074
5081 if (!node->url().isNull())
5085 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113 auto cn =
static_cast<CollectionNode *>(node);
5114 if (cn->wasSeen()) {
5115 m_qdb->mergeCollections(cn);
5116 generateCollectionNode(cn);
5117 }
else if (cn->isGenericCollection()) {
5121 generateGenericCollectionPage(cn);
5124 generatePageNode(
static_cast<PageNode *>(node));
5128 generateCppReferencePage(
static_cast<Aggregate *>(node));
5130 generateQmlTypePage(
static_cast<QmlTypeNode *>(node));
5132 generateProxyPage(
static_cast<Aggregate *>(node));
5138 auto *aggregate =
static_cast<Aggregate *>(node);
5139 for (
auto c : aggregate->childNodes()) {
5140 if (node->isPageNode())
5141 generateDocumentation(c);
5152 Q_ASSERT(m_writer ==
nullptr);
5153 m_writer = startDocument(aggregate);
5161 if (!aggregate
->doc().isEmpty()) {
5162 startSection(
"details",
"Detailed Description");
5164 generateBody(aggregate);
5173 for (
const auto §ion : detailsSections) {
5174 if (section.isEmpty())
5177 startSection(section.title().toLower(), section.title());
5179 const QList<Node *> &members = section.members();
5180 for (
const auto &member : members) {
5181 if (!member->isClassNode()) {
5182 generateDetailedMember(member, aggregate);
5184 startSectionBegin();
5185 generateFullName(member, aggregate);
5188 generateBrief(member);
5202
5203
5208 Q_ASSERT(m_writer ==
nullptr);
5209 m_writer = startDocument(cn);
5218 if (cn
->genus() != Genus::DOC && cn
->genus() != Genus::DontCare) {
5229 if (!nmm.isEmpty()) {
5230 startSection(
"namespaces",
"Namespaces");
5231 generateAnnotatedList(cn, nmm.values(),
"namespaces");
5235 if (!nmm.isEmpty()) {
5236 startSection(
"classes",
"Classes");
5237 generateAnnotatedList(cn, nmm.values(),
"classes");
5243 bool generatedTitle =
false;
5245 startSection(
"details",
"Detailed Description");
5246 generatedTitle =
true;
5251 !cn
->doc().body().isEmpty() ||
5253 !cn
->doc().alsoList().empty() ||
5256 writeAnchor(
"details");
5262 if (!cn->noAutoList() && (cn->isGroup() || cn->isQmlModule()))
5263 generateAnnotatedList(cn, cn->members(),
"members", AutoSection);
5274
5275
5276
5277
5282 QString name = cn->name().toLower();
5283 name.replace(QChar(
' '), QString(
"-"));
5284 QString filename = cn->tree()->physicalModuleName() +
"-" + name +
"." + fileExtension();
5287 Q_ASSERT(m_writer ==
nullptr);
5288 m_writer = startGenericDocument(cn, filename);
5297 m_writer->writeStartElement(dbNamespace,
"para");
5298 m_writer->writeCharacters(
"Each function or type documented here is related to a class or "
5299 "namespace that is documented in a different module. The reference "
5300 "page for that class or namespace will link to the function or type "
5302 m_writer->writeEndElement();
5306 for (
const auto &member : members)
5307 generateDetailedMember(member, cnc);
5320 m_writer->writeStartElement(dbNamespace,
"link");
5321 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(node));
5322 m_writer->writeAttribute(xlinkNamespace,
"role", targetType(node));
5323 m_writer->writeCharacters(node->fullName(relative));
5324 m_writer->writeEndElement();
5328 const Node *actualNode)
5330 Q_ASSERT(apparentNode);
5331 Q_ASSERT(actualNode);
5334 m_writer->writeStartElement(dbNamespace,
"link");
5335 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(actualNode));
5336 m_writer->writeAttribute(
"role", targetType(actualNode));
5337 m_writer->writeCharacters(fullName);
5338 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
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.