27#include <QtCore/qlist.h>
28#include <QtCore/qmap.h>
29#include <QtCore/quuid.h>
30#include <QtCore/qurl.h>
31#include <QtCore/qregularexpression.h>
32#include <QtCore/qversionnumber.h>
38using namespace Qt::StringLiterals;
40static const char dbNamespace[] =
"http://docbook.org/ns/docbook";
48 m_writer->writeCharacters(
"\n");
56 m_writer->writeAttribute(
"xml:id", registerRef(id,
true));
69 QString id = Generator::cleanRef(refForNode(node),
true);
71 m_writer->writeAttribute(
"xml:id", id);
78 m_writer->writeStartElement(dbNamespace,
"section");
81 m_writer->writeStartElement(dbNamespace,
"title");
86 m_writer->writeStartElement(dbNamespace,
"section");
89 m_writer->writeStartElement(dbNamespace,
"title");
94 m_writer->writeEndElement();
100 startSectionBegin(id);
101 m_writer->writeCharacters(title);
107 startSectionBegin(node);
108 m_writer->writeCharacters(title);
115 startSection(
"", title);
120 m_writer->writeEndElement();
129 m_writer->writeEmptyElement(dbNamespace,
"anchor");
135
136
137
142 m_config = &Config::instance();
147 if (m_projectDescription.isEmpty() && !m_project.isEmpty())
148 m_projectDescription = m_project + QLatin1String(
" Reference Documentation");
151 if (m_naturalLanguage.isEmpty())
152 m_naturalLanguage = QLatin1String(
"en");
156 m_config->get(format() + Config::dot +
"usedocbookextensions").asBool();
157 m_useITS = m_config->get(format() + Config::dot +
"its").asBool();
166
167
174
175
176
177
192 QString rewritten = code;
193 static const QRegularExpression re(
"(<@[^>&]*>)|(<\\/@[^&>]*>)");
194 rewritten.replace(re,
"");
199
200
216 const Node *node =
nullptr;
217 QString link = getAutoLink(atom, relative, &node, genus);
222 if (link.isEmpty()) {
223 m_writer->writeCharacters(atom->string());
225 beginLink(link, node, relative);
230 m_writer->writeCharacters(atom->string());
240 m_writer->writeStartElement(dbNamespace,
"para");
246 m_writer->writeEndElement();
256 m_writer->writeCharacters(plainCode(atom->string()));
258 m_writer->writeTextElement(dbNamespace,
"code", plainCode(atom->string()));
260 case Atom::CaptionLeft:
261 m_writer->writeStartElement(dbNamespace,
"title");
265 m_writer->writeEndElement();
269 m_writer->writeStartElement(dbNamespace,
"programlisting");
270 m_writer->writeAttribute(
"language",
"qml");
272 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
273 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
274 m_writer->writeEndElement();
278 m_writer->writeStartElement(dbNamespace,
"programlisting");
279 m_writer->writeAttribute(
"language",
"cpp");
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");
288 m_writer->writeAttribute(
"language",
"cpp");
289 m_writer->writeAttribute(
"role",
"bad");
291 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
292 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
293 m_writer->writeEndElement();
302 case Atom::FootnoteLeft:
303 m_writer->writeStartElement(dbNamespace,
"footnote");
305 m_writer->writeStartElement(dbNamespace,
"para");
308 case Atom::FootnoteRight:
309 m_writer->writeEndElement();
312 m_writer->writeEndElement();
320 m_writer->writeStartElement(dbNamespace,
"emphasis");
321 m_writer->writeAttribute(
"role",
"bold");
323 m_writer->writeStartElement(dbNamespace,
"emphasis");
325 m_writer->writeStartElement(dbNamespace,
"emphasis");
326 m_writer->writeAttribute(
"role",
"underline");
328 m_writer->writeStartElement(dbNamespace,
"subscript");
330 m_writer->writeStartElement(dbNamespace,
"superscript");
333 m_writer->writeStartElement(dbNamespace,
"code");
335 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
338 m_writer->writeAttribute(
"role",
"parameter");
342 m_writer->writeStartElement(dbNamespace,
"guilabel");
344 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
346 m_writer->writeStartElement(dbNamespace,
347 appendTrademark(atom->find(Atom::FormattingRight)) ?
348 "trademark" :
"phrase");
350 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
352 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
364 m_writer->writeEndElement();
367 m_inTeletype =
false;
370 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
374 if (
const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), Node::Group))
375 generateList(cn, atom->string(), Generator::sortOrder(atom->strings().last()));
378 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
379 bool hasGeneratedSomething =
false;
380 if (atom->string() == QLatin1String(
"annotatedclasses")
381 || atom->string() == QLatin1String(
"attributions")
382 || atom->string() == QLatin1String(
"namespaces")) {
383 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedclasses")
387 generateAnnotatedList(relative, things.values(), atom->string(), Auto, sortOrder);
388 hasGeneratedSomething = !things.isEmpty();
389 }
else if (atom->string() == QLatin1String(
"annotatedexamples")
390 || atom->string() == QLatin1String(
"annotatedattributions")) {
391 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedexamples")
394 generateAnnotatedLists(relative, things, atom->string());
395 hasGeneratedSomething = !things.isEmpty();
396 }
else if (atom->string() == QLatin1String(
"classes")
397 || atom->string() == QLatin1String(
"qmlbasictypes")
398 || atom->string() == QLatin1String(
"qmlvaluetypes")
399 || atom->string() == QLatin1String(
"qmltypes")) {
400 const NodeMultiMap things = atom->string() == QLatin1String(
"classes")
402 : (atom->string() == QLatin1String(
"qmlvaluetypes")
403 || atom->string() == QLatin1String(
"qmlbasictypes"))
406 generateCompactList(relative, things,
true, QString(), atom->string());
407 hasGeneratedSomething = !things.isEmpty();
408 }
else if (atom->string().contains(
"classes ")) {
409 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
412 hasGeneratedSomething = !things.isEmpty();
413 generateCompactList(relative, things,
true, rootName, atom->string());
414 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
415 QString moduleName = atom->string().mid(idx + 8).trimmed();
418 if (
const CollectionNode *cn = qdb->getCollectionNode(moduleName, moduleType)) {
420 switch (moduleType) {
426 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
432 generateAnnotatedList(relative, cn->members(), atom->string(), Auto, sortOrder);
436 if (!map.isEmpty()) {
437 generateAnnotatedList(relative, map.values(), atom->string(), Auto, sortOrder);
438 hasGeneratedSomething =
true;
441 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
444 }
else if (atom->string().startsWith(
"obsolete")) {
445 QString prefix = atom->string().contains(
"cpp") ? QStringLiteral(
"Q") : QString();
446 const NodeMultiMap &things = atom->string() == QLatin1String(
"obsoleteclasses")
448 : atom->string() == QLatin1String(
"obsoleteqmltypes")
450 : atom->string() == QLatin1String(
"obsoletecppmembers")
453 generateCompactList(relative, things,
false, prefix, atom->string());
454 hasGeneratedSomething = !things.isEmpty();
455 }
else if (atom->string() == QLatin1String(
"functionindex")) {
456 generateFunctionIndex(relative);
458 }
else if (atom->string() == QLatin1String(
"legalese")) {
459 generateLegaleseList(relative);
461 }
else if (atom->string() == QLatin1String(
"overviews")
462 || atom->string() == QLatin1String(
"cpp-modules")
463 || atom->string() == QLatin1String(
"qml-modules")
464 || atom->string() == QLatin1String(
"related")) {
465 generateList(relative, atom->string());
466 hasGeneratedSomething =
true;
468 }
else if (
const auto *cn =
m_qdb->getCollectionNode(atom->string(),
Node::Group); cn) {
469 generateAnnotatedList(cn, cn->members(), atom->string(), ItemizedList, sortOrder);
470 hasGeneratedSomething =
true;
475 if (!hasGeneratedSomething && !m_inPara) {
476 m_writer->writeEmptyElement(dbNamespace,
"para");
508 m_writer->writeStartElement(dbNamespace,
"figure");
515 generateAtom(current, relative,
nullptr);
520 generateAtom(current, relative,
nullptr);
526 generateAtom(current, relative,
nullptr);
530 m_closeFigureWrapper =
true;
541 m_writer->writeStartElement(dbNamespace,
"figure");
548 generateAtom(current, relative,
nullptr);
553 generateAtom(current, relative,
nullptr);
559 generateAtom(current, relative,
nullptr);
563 m_closeFigureWrapper =
true;
585 QString tag = atom->type() == Atom::Image ?
"mediaobject" :
"inlinemediaobject";
586 m_writer->writeStartElement(dbNamespace, tag);
589 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
590 if (!maybe_resolved_file) {
592 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
594 m_writer->writeStartElement(dbNamespace,
"textobject");
596 m_writer->writeStartElement(dbNamespace,
"para");
597 m_writer->writeTextElement(dbNamespace,
"emphasis",
598 "[Missing image " + atom->string() +
"]");
599 m_writer->writeEndElement();
601 m_writer->writeEndElement();
605 QString file_name{QFileInfo{file.get_path()}.fileName()};
608 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
612 m_writer->writeTextElement(dbNamespace,
"alt", atom->next()->string());
616 m_writer->writeStartElement(dbNamespace,
"imageobject");
618 m_writer->writeEmptyElement(dbNamespace,
"imagedata");
620 m_writer->writeAttribute(
"fileref",
"images/" + file_name);
622 m_writer->writeEndElement();
626 setImageFileName(relative,
"images/" + file_name);
629 m_writer->writeEndElement();
633 if (m_closeFigureWrapper) {
634 m_writer->writeEndElement();
636 m_closeFigureWrapper =
false;
644 QString admonType = atom->typeString().toLower();
647 m_writer->writeStartElement(dbNamespace, admonType);
649 m_writer->writeStartElement(dbNamespace,
"para");
652 case Atom::ImportantRight:
653 case Atom::NoteRight:
654 case Atom::WarningRight:
655 m_writer->writeEndElement();
658 m_writer->writeEndElement();
666 const Node *node =
nullptr;
667 QString link = getLink(atom, relative, &node);
668 beginLink(link, node, relative);
672 const Node *node = CodeMarker::nodeForString(atom->string());
673 beginLink(linkForNode(node, relative), node, relative);
683 m_writer->writeEndElement();
689 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
692 m_writer->writeStartElement(dbNamespace,
"variablelist");
695 m_writer->writeStartElement(dbNamespace,
"informaltable");
697 m_writer->writeStartElement(dbNamespace,
"thead");
699 m_writer->writeStartElement(dbNamespace,
"tr");
701 m_writer->writeTextElement(dbNamespace,
"th",
"Constant");
707 m_writer->writeTextElement(dbNamespace,
"th",
"Value");
712 m_writer->writeTextElement(dbNamespace,
"th",
"Description");
716 m_writer->writeEndElement();
718 m_writer->writeEndElement();
721 m_writer->writeStartElement(dbNamespace,
"orderedlist");
723 if (atom->next() !=
nullptr && atom->next()->string().toInt() > 1)
724 m_writer->writeAttribute(
"startingnumber", atom->next()->string());
727 m_writer->writeAttribute(
"numeration",
"upperalpha");
729 m_writer->writeAttribute(
"numeration",
"loweralpha");
731 m_writer->writeAttribute(
"numeration",
"upperroman");
733 m_writer->writeAttribute(
"numeration",
"lowerroman");
735 m_writer->writeAttribute(
"numeration",
"arabic");
745 m_writer->writeStartElement(dbNamespace,
"varlistentry");
747 m_writer->writeStartElement(dbNamespace,
"item");
749 std::pair<QString,
int> pair = getAtomListValue(atom);
750 skipAhead = pair.second;
752 m_writer->writeStartElement(dbNamespace,
"tr");
754 m_writer->writeStartElement(dbNamespace,
"td");
756 m_writer->writeStartElement(dbNamespace,
"para");
758 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
759 generateEnumValue(pair.first, relative);
760 m_writer->writeEndElement();
762 m_writer->writeEndElement();
766 const auto enume =
static_cast<
const EnumNode *>(relative);
767 QString itemValue = enume->itemValue(atom->next()->string());
769 m_writer->writeStartElement(dbNamespace,
"td");
770 if (itemValue.isEmpty())
771 m_writer->writeCharacters(
"?");
773 m_writer->writeStartElement(dbNamespace,
"code");
775 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
776 m_writer->writeCharacters(itemValue);
777 m_writer->writeEndElement();
779 m_writer->writeEndElement();
787 m_writer->writeEndElement();
793 m_writer->writeEndElement();
800 m_inListItemLineOpen =
false;
802 m_writer->writeStartElement(dbNamespace,
"listitem");
804 m_writer->writeStartElement(dbNamespace,
"para");
809 m_writer->writeEmptyElement(dbNamespace,
"td");
811 m_inListItemLineOpen =
false;
813 m_writer->writeStartElement(dbNamespace,
"td");
815 m_inListItemLineOpen =
true;
819 m_writer->writeStartElement(dbNamespace,
"listitem");
828 m_writer->writeEndElement();
831 m_writer->writeEndElement();
833 m_writer->writeEndElement();
836 if (m_inListItemLineOpen) {
837 m_writer->writeEndElement();
839 m_inListItemLineOpen =
false;
841 m_writer->writeEndElement();
844 m_writer->writeEndElement();
849 case Atom::ListRight:
855 m_writer->writeEndElement();
862 m_writer->writeStartElement(dbNamespace,
"para");
868 m_writer->writeEndElement();
873 case Atom::QuotationLeft:
874 m_writer->writeStartElement(dbNamespace,
"blockquote");
875 m_inBlockquote =
true;
877 case Atom::QuotationRight:
878 m_writer->writeEndElement();
880 m_inBlockquote =
false;
883 m_writer->device()->write(atom->string().toUtf8());
889 currentSectionLevel = atom->string().toInt() +
hOffset(relative
);
891 if (currentSectionLevel > 1) {
894 while (!sectionLevels.empty() && sectionLevels.top() >= currentSectionLevel) {
896 m_writer->writeEndElement();
900 sectionLevels.push(currentSectionLevel);
902 m_writer->writeStartElement(dbNamespace,
"section");
903 writeXmlId(Tree::refForAtom(atom));
916 generateAtom(atom->next(), relative,
nullptr);
917 generateAtom(atom->next()->next(), relative,
nullptr);
918 generateAtom(atom->next()->next()->next(), relative,
nullptr);
920 m_closeSectionAfterGeneratedList =
true;
927 m_writer->writeTextElement(dbNamespace,
"title",
"");
936 if (currentSectionLevel > 1) {
937 m_writer->writeStartElement(dbNamespace,
"title");
943 if (currentSectionLevel > 1) {
944 m_writer->writeEndElement();
949 case Atom::SidebarLeft:
950 m_writer->writeStartElement(dbNamespace,
"sidebar");
952 case Atom::SidebarRight:
953 m_writer->writeEndElement();
960 m_writer->writeCharacters(atom->string());
963 std::pair<QString, QString> pair = getTableWidthAttr(atom);
964 QString attr = pair.second;
965 QString width = pair.first;
968 m_writer->writeEndElement();
973 m_tableHeaderAlreadyOutput =
false;
975 m_writer->writeStartElement(dbNamespace,
"informaltable");
976 m_writer->writeAttribute(
"style", attr);
977 if (!width.isEmpty())
978 m_writer->writeAttribute(
"width", width);
981 case Atom::TableRight:
982 m_tableWidthAttr = {
"",
""};
983 m_writer->writeEndElement();
992 if (m_tableHeaderAlreadyOutput) {
995 m_writer->writeEndElement();
998 const QString &attr = m_tableWidthAttr.second;
999 const QString &width = m_tableWidthAttr.first;
1001 m_writer->writeStartElement(dbNamespace,
"informaltable");
1002 m_writer->writeAttribute(
"style", attr);
1003 if (!width.isEmpty())
1004 m_writer->writeAttribute(
"width", width);
1007 m_tableHeaderAlreadyOutput =
true;
1013 id = Utilities::asAsciiPrintable(next->string());
1018 m_writer->writeStartElement(dbNamespace,
"thead");
1020 m_writer->writeStartElement(dbNamespace,
"tr");
1026 m_closeTableCell =
true;
1027 m_writer->writeStartElement(dbNamespace,
"td");
1033 if (m_closeTableCell) {
1034 m_closeTableCell =
false;
1035 m_writer->writeEndElement();
1039 m_writer->writeEndElement();
1043 m_writer->writeStartElement(dbNamespace,
"tr");
1046 m_writer->writeEndElement();
1058 bool hasTarget {
false};
1060 id = Utilities::asAsciiPrintable(atom
->next()->string());
1065 m_writer->writeStartElement(dbNamespace,
"tr");
1068 if (atom->string().isEmpty()) {
1069 m_writer->writeAttribute(
"valign",
"top");
1074 QStringList args = atom->string().split(
"\"", Qt::SkipEmptyParts);
1077 const int nArgs = args.size();
1082 QStringLiteral(
"Error when parsing attributes for the table: got \"%1\"")
1083 .arg(atom->string()));
1085 for (
int i = 0; i + 1 < nArgs; i += 2) {
1088 const QString &attr = args.at(i).chopped(1);
1091 writeXmlId(args.at(i + 1));
1093 m_writer->writeAttribute(attr, args.at(i + 1));
1109 m_closeTableRow =
true;
1110 m_writer->writeEndElement();
1116 if (m_closeTableRow) {
1117 m_closeTableRow =
false;
1118 m_writer->writeEndElement();
1122 m_writer->writeEndElement();
1125 case Atom::TableItemLeft:
1126 m_writer->writeStartElement(dbNamespace, m_inTableHeader ?
"th" :
"td");
1128 for (
int i = 0; i < atom->count(); ++i) {
1129 const QString &p = atom->string(i);
1130 if (p.contains(
'=')) {
1131 QStringList lp = p.split(QLatin1Char(
'='));
1132 m_writer->writeAttribute(lp.at(0), lp.at(1));
1134 QStringList spans = p.split(QLatin1Char(
','));
1135 if (spans.size() == 2) {
1136 if (spans.at(0) !=
"1")
1137 m_writer->writeAttribute(
"colspan", spans.at(0).trimmed());
1138 if (spans.at(1) !=
"1")
1139 m_writer->writeAttribute(
"rowspan", spans.at(1).trimmed());
1146 case Atom::TableItemRight:
1147 m_writer->writeEndElement();
1157 QString nextId = Utilities::asAsciiPrintable(
1158 Text::sectionHeading(atom->next()->next()).toString());
1159 QString ownId = Utilities::asAsciiPrintable(atom->string());
1160 if (nextId == ownId)
1164 writeAnchor(Utilities::asAsciiPrintable(atom->string()));
1166 case Atom::UnhandledFormat:
1167 m_writer->writeStartElement(dbNamespace,
"emphasis");
1168 m_writer->writeAttribute(
"role",
"bold");
1169 m_writer->writeCharacters(
"<Missing DocBook>");
1170 m_writer->writeEndElement();
1172 case Atom::UnknownCommand:
1173 m_writer->writeStartElement(dbNamespace,
"emphasis");
1174 m_writer->writeAttribute(
"role",
"bold");
1176 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1177 m_writer->writeCharacters(
"<Unknown command>");
1178 m_writer->writeStartElement(dbNamespace,
"code");
1179 m_writer->writeCharacters(atom->string());
1180 m_writer->writeEndElement();
1181 m_writer->writeEndElement();
1201 if (classMap.isEmpty())
1204 std::function<
void(
ClassNode *)> generateClassAndChildren
1205 = [
this, &relative, &generateClassAndChildren](ClassNode * classe) {
1206 m_writer->writeStartElement(dbNamespace,
"listitem");
1210 m_writer->writeStartElement(dbNamespace,
"para");
1211 generateFullName(classe, relative);
1212 m_writer->writeEndElement();
1216 bool hasChild =
false;
1217 for (
const RelatedClass &relatedClass : classe->derivedClasses()) {
1218 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1225 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1228 for (
const RelatedClass &relatedClass: classe->derivedClasses()) {
1229 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1230 generateClassAndChildren(relatedClass.m_node);
1234 m_writer->writeEndElement();
1239 m_writer->writeEndElement();
1243 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1246 for (
const auto &it : classMap) {
1247 auto *classe =
static_cast<ClassNode *>(it);
1248 if (classe->baseClasses().isEmpty())
1249 generateClassAndChildren(classe);
1252 m_writer->writeEndElement();
1263 if (match.hasMatch()) {
1265 qsizetype leftParenLoc = match.capturedStart(1);
1266 m_writer->writeCharacters(atom->string().left(leftParenLoc));
1268 m_writer->writeCharacters(atom->string().mid(leftParenLoc));
1272 m_writer->writeCharacters(atom->string());
1276
1277
1278
1282 m_writer->writeStartElement(dbNamespace,
"link");
1283 m_writer->writeAttribute(xlinkNamespace,
"href", link);
1284 if (node && !(relative && node->status() == relative->status())
1285 && node->isDeprecated())
1286 m_writer->writeAttribute(
"role",
"deprecated");
1295 m_writer->writeEndElement();
1301 Qt::SortOrder sortOrder)
1306 if (selector == QLatin1String(
"overviews"))
1308 else if (selector == QLatin1String(
"cpp-modules"))
1310 else if (selector == QLatin1String(
"qml-modules"))
1316 const QList<CollectionNode *> collectionList = cnm.values();
1317 nodeList.reserve(collectionList.size());
1318 for (
auto *collectionNode : collectionList)
1319 nodeList.append(collectionNode);
1320 generateAnnotatedList(relative, nodeList, selector, Auto, sortOrder);
1323
1324
1325
1326 Node *n =
const_cast<
Node *>(relative);
1329 generateAnnotatedList(cn, cn->members(), selector, Auto, sortOrder);
1334
1335
1336
1338 const QString &selector, GeneratedListType type,
1339 Qt::SortOrder sortOrder)
1341 if (nodeList.isEmpty())
1345 if (
std::all_of(nodeList.cbegin(), nodeList.cend(), [](
const Node *n) {
1352 bool noItemsHaveTitle =
1353 type == ItemizedList ||
std::all_of(nodeList.begin(), nodeList.end(),
1354 [](
const Node* node) {
1355 return node->doc().briefText().toString().isEmpty();
1359 if (type == AutoSection && m_hasSection)
1360 startSection(
"",
"Contents");
1363 if (!nodeList.isEmpty()) {
1364 m_writer->writeStartElement(dbNamespace, noItemsHaveTitle ?
"itemizedlist" :
"variablelist");
1365 m_writer->writeAttribute(
"role", selector);
1369 if (sortOrder == Qt::DescendingOrder)
1373 for (
const auto &node : std::as_const(members)) {
1374 if (node->isInternal() || node->isDeprecated())
1377 if (noItemsHaveTitle) {
1378 m_writer->writeStartElement(dbNamespace,
"listitem");
1380 m_writer->writeStartElement(dbNamespace,
"para");
1382 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1384 m_writer->writeStartElement(dbNamespace,
"term");
1386 generateFullName(node, relative);
1387 if (noItemsHaveTitle) {
1388 m_writer->writeEndElement();
1390 m_writer->writeEndElement();
1392 m_writer->writeEndElement();
1394 m_writer->writeStartElement(dbNamespace,
"listitem");
1396 m_writer->writeStartElement(dbNamespace,
"para");
1397 m_writer->writeCharacters(node->doc().briefText().toString());
1398 m_writer->writeEndElement();
1400 m_writer->writeEndElement();
1402 m_writer->writeEndElement();
1407 m_writer->writeEndElement();
1411 if (type == AutoSection && m_hasSection)
1416
1417
1418
1420 const QString &selector)
1423 for (
const QString &name : nmm.uniqueKeys()) {
1424 if (!name.isEmpty())
1425 startSection(name.toLower(), name);
1426 generateAnnotatedList(relative, nmm.values(name), selector);
1427 if (!name.isEmpty())
1433
1434
1435
1436
1437
1438
1439
1440
1441
1443 bool includeAlphabet,
const QString &commonPrefix,
1444 const QString &selector)
1454 const int NumParagraphs = 37;
1455 qsizetype commonPrefixLen = commonPrefix.size();
1458
1459
1460
1461
1462
1464 QString paragraphName[NumParagraphs + 1];
1465 QSet<
char> usedParagraphNames;
1467 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
1468 QStringList pieces = c.key().split(
"::");
1469 int idx = commonPrefixLen;
1470 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
1472 QString last = pieces.last().toLower();
1473 QString key = last.mid(idx);
1475 int paragraphNr = NumParagraphs - 1;
1477 if (key[0].digitValue() != -1) {
1478 paragraphNr = key[0].digitValue();
1479 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
1480 paragraphNr = 10 + key[0].unicode() -
'a';
1483 paragraphName[paragraphNr] = key[0].toUpper();
1484 usedParagraphNames.insert(key[0].toLower().cell());
1485 paragraph[paragraphNr].insert(last, c.value());
1489
1490
1491
1492
1493
1494
1495
1496 int paragraphOffset[NumParagraphs + 1];
1497 paragraphOffset[0] = 0;
1498 for (
int i = 0; i < NumParagraphs; i++)
1499 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
1502 if (includeAlphabet && !usedParagraphNames.isEmpty()) {
1503 m_writer->writeStartElement(dbNamespace,
"simplelist");
1506 for (
int i = 0; i < 26; i++) {
1508 if (usedParagraphNames.contains(
char(
'a' + i))) {
1509 m_writer->writeStartElement(dbNamespace,
"member");
1510 generateSimpleLink(ch, ch.toUpper());
1511 m_writer->writeEndElement();
1516 m_writer->writeEndElement();
1522 int curParOffset = 0;
1523 QString previousName;
1524 bool multipleOccurrences =
false;
1526 m_writer->writeStartElement(dbNamespace,
"variablelist");
1527 m_writer->writeAttribute(
"role", selector);
1530 for (
int i = 0; i < nmm.size(); i++) {
1531 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
1538 if (curParOffset == 0) {
1540 m_writer->writeEndElement();
1542 m_writer->writeEndElement();
1544 m_writer->writeEndElement();
1548 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1549 if (includeAlphabet)
1550 writeXmlId(paragraphName[curParNr][0].toLower());
1553 m_writer->writeStartElement(dbNamespace,
"term");
1554 m_writer->writeStartElement(dbNamespace,
"emphasis");
1555 m_writer->writeAttribute(
"role",
"bold");
1556 m_writer->writeCharacters(paragraphName[curParNr]);
1557 m_writer->writeEndElement();
1558 m_writer->writeEndElement();
1561 m_writer->writeStartElement(dbNamespace,
"listitem");
1563 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1568 m_writer->writeStartElement(dbNamespace,
"listitem");
1570 m_writer->writeStartElement(dbNamespace,
"para");
1572 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
1573 NodeMultiMap::Iterator it;
1574 NodeMultiMap::Iterator next;
1575 it = paragraph[curParNr].begin();
1576 for (
int j = 0; j < curParOffset; j++)
1581 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
1582 const auto &name{pieces.last()};
1585 if (name != previousName)
1586 multipleOccurrences =
false;
1587 if ((next != paragraph[curParNr].end()) && (name == next.value()->name())) {
1588 multipleOccurrences =
true;
1589 previousName = name;
1591 if (multipleOccurrences && pieces.size() == 1)
1592 pieces.last().append(
": "_L1.arg(it.value()->tree()->camelCaseModuleName()));
1595 m_writer->writeStartElement(dbNamespace,
"link");
1596 m_writer->writeAttribute(xlinkNamespace,
"href", linkForNode(*it, relative));
1597 if (
const QString type = targetType(it.value()); !type.isEmpty())
1598 m_writer->writeAttribute(
"role", type);
1599 m_writer->writeCharacters(pieces.last());
1600 m_writer->writeEndElement();
1603 if (pieces.size() > 1) {
1604 m_writer->writeCharacters(
" (");
1605 generateFullName(it.value()->parent(), relative);
1606 m_writer->writeCharacters(
")");
1610 m_writer->writeEndElement();
1612 m_writer->writeEndElement();
1617 m_writer->writeEndElement();
1619 m_writer->writeEndElement();
1621 m_writer->writeEndElement();
1624 m_writer->writeEndElement();
1633 m_writer->writeStartElement(dbNamespace,
"simplelist");
1634 m_writer->writeAttribute(
"role",
"functionIndex");
1636 for (
int i = 0; i < 26; i++) {
1638 m_writer->writeStartElement(dbNamespace,
"member");
1639 m_writer->writeAttribute(xlinkNamespace,
"href", QString(
"#") + ch);
1640 m_writer->writeCharacters(ch.toUpper());
1641 m_writer->writeEndElement();
1644 m_writer->writeEndElement();
1651 char nextLetter =
'a';
1654 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1658 QMap<QString, NodeMap>::ConstIterator f = funcIndex.constBegin();
1659 while (f != funcIndex.constEnd()) {
1660 m_writer->writeStartElement(dbNamespace,
"listitem");
1662 m_writer->writeStartElement(dbNamespace,
"para");
1663 m_writer->writeCharacters(f.key() +
": ");
1665 currentLetter = f.key()[0].unicode();
1666 while (islower(currentLetter) && currentLetter >= nextLetter) {
1667 writeAnchor(QString(nextLetter));
1671 NodeMap::ConstIterator s = (*f).constBegin();
1672 while (s != (*f).constEnd()) {
1673 m_writer->writeCharacters(
" ");
1674 generateFullName((*s)->parent(), relative);
1678 m_writer->writeEndElement();
1680 m_writer->writeEndElement();
1684 m_writer->writeEndElement();
1692 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
1693 Text text = it.key();
1695 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1698 m_writer->writeStartElement(dbNamespace,
"listitem");
1700 m_writer->writeStartElement(dbNamespace,
"para");
1701 generateFullName(it.value(), relative);
1702 m_writer->writeEndElement();
1704 m_writer->writeEndElement();
1707 }
while (it != legaleseTexts.constEnd() && it.key() == text);
1708 m_writer->writeEndElement();
1723 m_writer->writeStartElement(dbNamespace,
"para");
1725 m_writer->writeEndElement();
1733 if (!node->since().isEmpty()) {
1734 m_writer->writeStartElement(dbNamespace,
"para");
1735 m_writer->writeCharacters(
"This " + typeString(node) +
" was introduced in ");
1736 m_writer->writeCharacters(formatSince(node) +
".");
1737 m_writer->writeEndElement();
1747
1748
1749
1756 m_writer->writeStartElement(dbNamespace,
"info");
1758 m_writer->writeStartElement(dbNamespace,
"title");
1759 if (node->genus() & Node::API && m_useITS)
1760 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1761 m_writer->writeCharacters(title);
1762 m_writer->writeEndElement();
1765 if (!subTitle.isEmpty()) {
1766 m_writer->writeStartElement(dbNamespace,
"subtitle");
1767 if (node->genus() & Node::API && m_useITS)
1768 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1769 m_writer->writeCharacters(subTitle);
1770 m_writer->writeEndElement();
1774 if (!m_project.isEmpty()) {
1775 m_writer->writeTextElement(dbNamespace,
"productname", m_project);
1779 if (!m_buildVersion.isEmpty()) {
1780 m_writer->writeTextElement(dbNamespace,
"edition", m_buildVersion);
1784 if (!m_projectDescription.isEmpty()) {
1785 m_writer->writeTextElement(dbNamespace,
"titleabbrev", m_projectDescription);
1793 if (node && !node->links().empty()) {
1794 std::pair<QString, QString> linkPair;
1795 std::pair<QString, QString> anchorPair;
1796 const Node *linkNode;
1798 if (node->links().contains(Node::PreviousLink)) {
1799 linkPair = node->links()[Node::PreviousLink];
1800 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1801 if (!linkNode || linkNode == node)
1802 anchorPair = linkPair;
1804 anchorPair = anchorForNode(linkNode);
1806 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1807 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1808 m_writer->writeEmptyElement(dbNamespace,
"link");
1809 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1810 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1811 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"prev");
1812 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1813 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1815 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1816 m_writer->writeEndElement();
1819 if (node->links().contains(Node::NextLink)) {
1820 linkPair = node->links()[Node::NextLink];
1821 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1822 if (!linkNode || linkNode == node)
1823 anchorPair = linkPair;
1825 anchorPair = anchorForNode(linkNode);
1827 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1828 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1829 m_writer->writeEmptyElement(dbNamespace,
"link");
1830 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1831 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1832 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"next");
1833 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1834 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1836 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1837 m_writer->writeEndElement();
1840 if (node->links().contains(Node::StartLink)) {
1841 linkPair = node->links()[Node::StartLink];
1842 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1843 if (!linkNode || linkNode == node)
1844 anchorPair = linkPair;
1846 anchorPair = anchorForNode(linkNode);
1848 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1849 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1850 m_writer->writeEmptyElement(dbNamespace,
"link");
1851 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1852 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1853 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"start");
1854 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1855 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1857 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1858 m_writer->writeEndElement();
1870 m_writer->writeStartElement(dbNamespace,
"abstract");
1873 bool generatedSomething =
false;
1880 brief <<
"The " << ns->name()
1881 <<
" namespace includes the following elements from module "
1882 << ns->tree()->camelCaseModuleName() <<
". The full namespace is "
1883 <<
"documented in module " << NS->tree()->camelCaseModuleName()
1884 << Atom(Atom::LinkNode, fullDocumentLocation(NS))
1886 << Atom(Atom::String,
" here.")
1896 m_writer->writeStartElement(dbNamespace,
"para");
1898 m_writer->writeEndElement();
1901 generatedSomething =
true;
1912 if (!generatedSomething)
1913 m_writer->writeTextElement(dbNamespace,
"para", m_projectDescription +
".");
1915 m_writer->writeEndElement();
1920 m_writer->writeEndElement();
1926 while (!sectionLevels.isEmpty()) {
1927 sectionLevels.pop();
1934 if (m_closeSectionAfterGeneratedList) {
1935 m_closeSectionAfterGeneratedList =
false;
1938 if (m_closeSectionAfterRawTitle) {
1939 m_closeSectionAfterRawTitle =
false;
1944 m_writer->writeEndElement();
1947void DocBookGenerator::generateSimpleLink(
const QString &href,
const QString &text)
1949 m_writer->writeStartElement(dbNamespace,
"link");
1950 m_writer->writeAttribute(xlinkNamespace,
"href", href);
1951 m_writer->writeCharacters(text);
1952 m_writer->writeEndElement();
1964 startSection(
"obsolete",
"Obsolete Members for " + aggregate->name());
1966 m_writer->writeStartElement(dbNamespace,
"para");
1967 m_writer->writeStartElement(dbNamespace,
"emphasis");
1968 m_writer->writeAttribute(
"role",
"bold");
1969 m_writer->writeCharacters(
"The following members of class ");
1970 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
1971 m_writer->writeCharacters(
" are deprecated.");
1972 m_writer->writeEndElement();
1973 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
1974 m_writer->writeEndElement();
1977 for (
const Section *section : details_spv) {
1978 const QString &title =
"Obsolete " + section->title();
1979 startSection(title.toLower(), title);
1981 const NodeVector &members = section->obsoleteMembers();
1982 NodeVector::ConstIterator m = members.constBegin();
1983 while (m != members.constEnd()) {
1984 if ((*m)->access() != Access::Private)
1985 generateDetailedMember(*m, aggregate);
1996
1997
1998
1999
2000
2001
2002
2012 startSection(
"obsolete",
"Obsolete Members for " + aggregate->name());
2014 m_writer->writeStartElement(dbNamespace,
"para");
2015 m_writer->writeStartElement(dbNamespace,
"emphasis");
2016 m_writer->writeAttribute(
"role",
"bold");
2017 m_writer->writeCharacters(
"The following members of QML type ");
2018 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2019 m_writer->writeCharacters(
" are deprecated.");
2020 m_writer->writeEndElement();
2021 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2022 m_writer->writeEndElement();
2025 for (
const auto *section : details_spv) {
2026 const QString &title =
"Obsolete " + section->title();
2027 startSection(title.toLower(), title);
2029 const NodeVector &members = section->obsoleteMembers();
2030 NodeVector::ConstIterator m = members.constBegin();
2031 while (m != members.constEnd()) {
2032 if ((*m)->access() != Access::Private)
2033 generateDetailedQmlMember(*m, aggregate);
2047 return QStringLiteral(
"classsynopsis");
2049 return QStringLiteral(
"packagesynopsis");
2055 return QStringLiteral(
"enumsynopsis");
2057 return QStringLiteral(
"typedefsynopsis");
2060 const auto fn =
static_cast<
const FunctionNode *>(node);
2062 return QStringLiteral(
"constructorsynopsis");
2064 return QStringLiteral(
"destructorsynopsis");
2065 return QStringLiteral(
"methodsynopsis");
2068 return QStringLiteral(
"fieldsynopsis");
2070 node
->doc().location().warning(QString(
"Unknown node tag %1").arg(node->nodeTypeString()));
2071 return QStringLiteral(
"synopsis");
2076 m_writer->writeStartElement(dbNamespace,
"varlistentry");
2078 m_writer->writeTextElement(dbNamespace,
"term", description);
2080 m_writer->writeStartElement(dbNamespace,
"listitem");
2082 m_writer->writeStartElement(dbNamespace,
"para");
2088 m_writer->writeEndElement();
2091 m_writer->writeEndElement();
2093 m_writer->writeEndElement();
2097void DocBookGenerator::generateRequisite(
const QString &description,
const QString &value)
2099 generateStartRequisite(description);
2100 m_writer->writeCharacters(value);
2101 generateEndRequisite();
2105
2106
2107
2108void DocBookGenerator::generateCMakeRequisite(
const QString &findPackage,
const QString &linkLibraries)
2110 const QString description(
"CMake");
2111 generateStartRequisite(description);
2112 m_writer->writeCharacters(findPackage);
2113 m_writer->writeEndElement();
2116 m_writer->writeStartElement(dbNamespace,
"para");
2117 m_writer->writeCharacters(linkLibraries);
2118 generateEndRequisite();
2124 QMap<QString, ClassNode *> classMap;
2125 QList<RelatedClass>::ConstIterator r = rc.constBegin();
2126 while (r != rc.constEnd()) {
2129 && !rcn
->doc().isEmpty()) {
2130 classMap[rcn->plainFullName(cn).toLower()] = rcn;
2135 QStringList classNames = classMap.keys();
2139 for (
const QString &className : classNames) {
2140 generateFullName(classMap.value(className), cn);
2141 m_writer->writeCharacters(Utilities::comma(index++, classNames.size()));
2148 QMap<QString, Node *> classMap;
2150 for (
auto sub : subs)
2151 classMap[sub->plainFullName(base).toLower()] = sub;
2153 QStringList names = classMap.keys();
2157 for (
const QString &name : names) {
2158 generateFullName(classMap.value(name), base);
2159 m_writer->writeCharacters(Utilities::comma(index++, names.size()));
2164
2165
2174 QXmlStreamWriter* oldWriter = m_writer;
2176 m_writer =
new QXmlStreamWriter(&output);
2179 if (aggregate->includeFile()) generateRequisite(
"Header", *aggregate->includeFile());
2182 if (!aggregate->since().isEmpty())
2183 generateRequisite(
"Since", formatSince(aggregate));
2190 if (
const auto result = cmakeRequisite(cn)) {
2191 generateCMakeRequisite(result->first, result->second);
2194 if (cn && !cn->qtVariable().isEmpty())
2195 generateRequisite(
"qmake",
"QT += " + cn->qtVariable());
2202 generateStartRequisite(
"In QML");
2205 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2208 for (
const auto &item : std::as_const(nativeTypes)) {
2209 generateFullName(item, classe);
2210 m_writer->writeCharacters(
2211 Utilities::comma(idx++, nativeTypes.size()));
2213 generateEndRequisite();
2217 QList<RelatedClass>::ConstIterator r;
2218 if (!classe->baseClasses().isEmpty()) {
2219 generateStartRequisite(
"Inherits");
2221 r = classe->baseClasses().constBegin();
2223 while (r != classe->baseClasses().constEnd()) {
2225 generateFullName((*r).m_node, classe);
2227 if ((*r).m_access == Access::Protected)
2228 m_writer->writeCharacters(
" (protected)");
2229 else if ((*r).m_access == Access::Private)
2230 m_writer->writeCharacters(
" (private)");
2231 m_writer->writeCharacters(
2232 Utilities::comma(index++, classe->baseClasses().size()));
2237 generateEndRequisite();
2241 if (!classe->derivedClasses().isEmpty()) {
2242 generateStartRequisite(
"Inherited By");
2243 generateSortedNames(classe, classe->derivedClasses());
2244 generateEndRequisite();
2249 if (!aggregate->groupNames().empty()) {
2250 generateStartRequisite(
"Group");
2252 generateEndRequisite();
2256 if (
auto status = formatStatus(aggregate, m_qdb); status)
2257 generateRequisite(
"Status", status.value());
2261 m_writer = oldWriter;
2263 if (!output.isEmpty()) {
2266 static const QRegularExpression xmlTag(R"(<(/?)n\d+:)");
2267 static const QRegularExpression xmlnsDocBookDefinition(R"( xmlns:n\d+=")" + QString{dbNamespace} +
"\"");
2268 static const QRegularExpression xmlnsXLinkDefinition(R"( xmlns:n\d+=")" + QString{xlinkNamespace} +
"\"");
2269 static const QRegularExpression xmlAttr(R"( n\d+:)");
2271 const QString cleanOutput = output.replace(xmlTag, R"(<\1db:)")
2272 .replace(xmlnsDocBookDefinition,
"")
2273 .replace(xmlnsXLinkDefinition,
"")
2274 .replace(xmlAttr,
" xlink:");
2276 m_writer->writeStartElement(dbNamespace,
"variablelist");
2278 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2281 m_writer->device()->write(cleanOutput.toUtf8());
2283 m_writer->writeEndElement();
2289
2290
2309 const bool generate_import_statement = !qcn->logicalModuleName().isEmpty() && (!collection || !collection
->isInternal() ||
m_showInternal);
2311 const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base;
2313 if (!generates_something)
2317 m_writer->writeStartElement(dbNamespace,
"variablelist");
2319 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2322 if (generate_import_statement) {
2323 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2324 generateRequisite(
"Import Statement", parts.join(
' ').trimmed());
2328 if (!qcn->since().isEmpty())
2329 generateRequisite(
"Since:", formatSince(qcn));
2332 if (!subs.isEmpty()) {
2333 generateStartRequisite(
"Inherited By:");
2335 generateEndRequisite();
2340 const Node *otherNode =
nullptr;
2342 QString link = getAutoLink(&a, qcn, &otherNode);
2344 generateStartRequisite(
"Inherits:");
2345 generateSimpleLink(link, base->name());
2346 generateEndRequisite();
2352 generateStartRequisite(
"In C++:");
2353 generateSimpleLink(fullDocumentLocation(cn), cn->name());
2354 generateEndRequisite();
2358 if (!qcn->groupNames().empty()) {
2359 generateStartRequisite(
"Group");
2361 generateEndRequisite();
2365 if (
auto status = formatStatus(qcn, m_qdb); status)
2366 generateRequisite(
"Status:", status.value());
2368 m_writer->writeEndElement();
2379 const QString &state =
static_cast<
const CollectionNode*>(node)->state();
2380 if (!state.isEmpty()) {
2381 m_writer->writeStartElement(dbNamespace,
"para");
2382 m_writer->writeCharacters(
"This " + typeString(node) +
" is in ");
2383 m_writer->writeStartElement(dbNamespace,
"emphasis");
2384 m_writer->writeCharacters(state);
2385 m_writer->writeEndElement();
2386 m_writer->writeCharacters(
" state.");
2387 m_writer->writeEndElement();
2392 if (
const auto version = node->deprecatedSince(); !version.isEmpty()) {
2393 m_writer->writeStartElement(dbNamespace,
"para");
2394 m_writer->writeCharacters(
"This " + typeString(node)
2395 +
" is scheduled for deprecation in version "
2397 m_writer->writeEndElement();
2402 case Node::Preliminary:
2403 m_writer->writeStartElement(dbNamespace,
"para");
2404 m_writer->writeStartElement(dbNamespace,
"emphasis");
2405 m_writer->writeAttribute(
"role",
"bold");
2406 m_writer->writeCharacters(
"This " + typeString(node)
2407 +
" is under development and is subject to change.");
2408 m_writer->writeEndElement();
2409 m_writer->writeEndElement();
2412 case Node::Deprecated:
2413 m_writer->writeStartElement(dbNamespace,
"para");
2415 m_writer->writeStartElement(dbNamespace,
"emphasis");
2416 m_writer->writeAttribute(
"role",
"bold");
2418 m_writer->writeCharacters(
"This " + typeString(node) +
" is deprecated");
2419 if (
const QString &version = node->deprecatedSince(); !version.isEmpty()) {
2420 m_writer->writeCharacters(
" since ");
2421 if (node->isQmlNode() && !node->logicalModuleName().isEmpty())
2422 m_writer->writeCharacters(node->logicalModuleName() +
" ");
2423 m_writer->writeCharacters(version);
2425 m_writer->writeCharacters(
". We strongly advise against using it in new code.");
2426 if (node->isAggregate())
2427 m_writer->writeEndElement();
2428 m_writer->writeEndElement();
2438
2439
2440
2444 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2447 NodeList::ConstIterator n = nodes.constBegin();
2448 while (n != nodes.constEnd()) {
2449 m_writer->writeStartElement(dbNamespace,
"listitem");
2451 m_writer->writeStartElement(dbNamespace,
"para");
2453 generateSimpleLink(currentGenerator()->fullDocumentLocation(*n),
2454 (*n)->signature(Node::SignaturePlain));
2456 m_writer->writeEndElement();
2458 m_writer->writeEndElement();
2463 m_writer->writeEndElement();
2468
2469
2470
2477 const auto aggregate =
static_cast<
const Aggregate *>(node);
2479 const QStringList &groups_names{aggregate->groupNames()};
2480 if (!groups_names.empty()) {
2481 m_writer->writeCharacters(aggregate->name() +
" is part of ");
2482 m_writer->writeStartElement(dbNamespace,
"simplelist");
2484 for (qsizetype index{0}; index < groups_names.size(); ++index) {
2488 m_writer->writeStartElement(dbNamespace,
"member");
2489 if (QString target{linkForNode(group,
nullptr)}; !target.isEmpty())
2490 generateSimpleLink(target, group->fullTitle());
2492 m_writer->writeCharacters(group->name());
2493 m_writer->writeEndElement();
2496 m_writer->writeEndElement();
2502
2503
2504
2510 const Node *reentrantNode;
2512 QString linkReentrant = getAutoLink(&reentrantAtom, node, &reentrantNode);
2513 const Node *threadSafeNode;
2515 QString linkThreadSafe = getAutoLink(&threadSafeAtom, node, &threadSafeNode);
2518 m_writer->writeStartElement(dbNamespace,
"warning");
2520 m_writer->writeStartElement(dbNamespace,
"para");
2521 m_writer->writeCharacters(
"This " + typeString(node) +
" is not ");
2522 generateSimpleLink(linkReentrant,
"reentrant");
2523 m_writer->writeCharacters(
".");
2524 m_writer->writeEndElement();
2526 m_writer->writeEndElement();
2530 m_writer->writeStartElement(dbNamespace,
"note");
2532 m_writer->writeStartElement(dbNamespace,
"para");
2535 m_writer->writeCharacters(
"All functions in this " + typeString(node) +
" are ");
2536 if (ts == Node::ThreadSafe)
2537 generateSimpleLink(linkThreadSafe,
"thread-safe");
2539 generateSimpleLink(linkReentrant,
"reentrant");
2545 if (!exceptions || (ts ==
Node::Reentrant && !threadsafe.isEmpty())) {
2546 m_writer->writeCharacters(
".");
2547 m_writer->writeEndElement();
2550 m_writer->writeCharacters(
" with the following exceptions:");
2551 m_writer->writeEndElement();
2553 m_writer->writeStartElement(dbNamespace,
"para");
2556 if (!nonreentrant.isEmpty()) {
2557 m_writer->writeCharacters(
"These functions are not ");
2558 generateSimpleLink(linkReentrant,
"reentrant");
2559 m_writer->writeCharacters(
":");
2560 m_writer->writeEndElement();
2562 generateSignatureList(nonreentrant);
2564 if (!threadsafe.isEmpty()) {
2565 m_writer->writeCharacters(
"These functions are also ");
2566 generateSimpleLink(linkThreadSafe,
"thread-safe");
2567 m_writer->writeCharacters(
":");
2568 m_writer->writeEndElement();
2570 generateSignatureList(threadsafe);
2573 if (!reentrant.isEmpty()) {
2574 m_writer->writeCharacters(
"These functions are only ");
2575 generateSimpleLink(linkReentrant,
"reentrant");
2576 m_writer->writeCharacters(
":");
2577 m_writer->writeEndElement();
2579 generateSignatureList(reentrant);
2581 if (!nonreentrant.isEmpty()) {
2582 m_writer->writeCharacters(
"These functions are not ");
2583 generateSimpleLink(linkReentrant,
"reentrant");
2584 m_writer->writeCharacters(
":");
2585 m_writer->writeEndElement();
2587 generateSignatureList(nonreentrant);
2592 m_writer->writeCharacters(
"This " + typeString(node) +
" is ");
2593 if (ts == Node::ThreadSafe)
2594 generateSimpleLink(linkThreadSafe,
"thread-safe");
2596 generateSimpleLink(linkReentrant,
"reentrant");
2597 m_writer->writeCharacters(
".");
2598 m_writer->writeEndElement();
2601 m_writer->writeEndElement();
2611
2612
2613
2621
2622
2623
2627 t =
"Destroys the instance of " + fn
->parent()->name() +
".";
2629 t +=
" The destructor is virtual.";
2631 t =
"Default constructs an instance of " + fn
->parent()->name() +
".";
2633 t =
"Copy constructor.";
2635 t =
"Move-copy constructor.";
2637 t =
"Copy-assignment constructor.";
2639 t =
"Move-assignment constructor.";
2643 m_writer->writeTextElement(dbNamespace,
"para", t);
2647 if (fn && !fn->overridesThis().isEmpty())
2648 generateReimplementsClause(fn);
2676 generateRequiredLinks(node);
2680
2681
2682
2683
2684
2691 const auto en =
static_cast<
const ExampleNode *>(node);
2694 if (exampleUrl.isEmpty()) {
2696 generateFileList(en,
false);
2697 generateFileList(en,
true);
2700 generateLinkToExample(en, exampleUrl);
2705
2706
2707
2708
2709
2713 QString exampleUrl(baseUrl);
2715#ifndef QT_BOOTSTRAPPED
2716 link = QUrl(exampleUrl).host();
2718 if (!link.isEmpty())
2719 link.prepend(
" @ ");
2720 link.prepend(
"Example project");
2722 const QLatin1Char separator(
'/');
2723 const QLatin1Char placeholder(
'\1');
2724 if (!exampleUrl.contains(placeholder)) {
2725 if (!exampleUrl.endsWith(separator))
2726 exampleUrl += separator;
2727 exampleUrl += placeholder;
2731 QStringList path = QStringList()
2733 path.removeAll(QString());
2737 startSection(
"Example project");
2739 m_writer->writeStartElement(dbNamespace,
"para");
2740 generateSimpleLink(exampleUrl.replace(placeholder, path.join(separator)), link);
2741 m_writer->writeEndElement();
2750
2751
2752
2753
2754
2755
2771 paths = en->images();
2774 paths = en->files();
2777 std::sort(paths.begin(), paths.end(), Generator::comparePaths);
2779 if (paths.isEmpty())
2782 startSection(
"",
"List of Files");
2784 m_writer->writeStartElement(dbNamespace,
"para");
2785 m_writer->writeCharacters(tag);
2786 m_writer->writeEndElement();
2789 startSection(
"List of Files");
2791 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2794 for (
const auto &path : std::as_const(paths)) {
2795 auto maybe_resolved_file{file_resolver.resolve(path)};
2796 if (!maybe_resolved_file) {
2798 QString details = std::transform_reduce(
2799 file_resolver.get_search_directories().cbegin(),
2800 file_resolver.get_search_directories().cend(),
2801 u"Searched directories:"_s,
2803 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
2806 en->location().warning(u"Cannot find file to quote from: %1"_s.arg(path), details);
2811 auto file{*maybe_resolved_file};
2812 if (images) addImageToCopy(en, file);
2813 else generateExampleFilePage(en, file);
2815 m_writer->writeStartElement(dbNamespace,
"listitem");
2817 m_writer->writeStartElement(dbNamespace,
"para");
2818 generateSimpleLink(file.get_query(), file.get_query());
2819 m_writer->writeEndElement();
2820 m_writer->writeEndElement();
2824 m_writer->writeEndElement();
2831
2832
2842 const auto en =
static_cast<
const ExampleNode *>(node);
2845 QXmlStreamWriter *currentWriter = m_writer;
2846 m_writer = startDocument(en, resolved_file.get_query());
2847 generateHeader(en->fullTitle(), en->subtitle(), en);
2852 QString code = quoter.quoteTo(en->location(), QString(), QString());
2853 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
2859 m_writer = currentWriter;
2865 if (fn->overridesThis().isEmpty() || !fn
->parent()->isClassNode())
2870 if (
const FunctionNode *overrides = cn->findOverriddenFunction(fn);
2873 m_writer->writeStartElement(dbNamespace,
"para");
2874 m_writer->writeCharacters(
"Reimplements: ");
2876 overrides->parent()->name() +
"::" + overrides->signature(Node::SignaturePlain);
2877 generateFullName(overrides
->parent(), fullName, overrides);
2878 m_writer->writeCharacters(
".");
2879 m_writer->writeEndElement();
2885 if (
const PropertyNode *sameName = cn->findOverriddenProperty(fn); sameName && sameName
->hasDoc()) {
2886 m_writer->writeStartElement(dbNamespace,
"para");
2887 m_writer->writeCharacters(
"Reimplements an access function for property: ");
2888 QString fullName = sameName->parent()->name() +
"::" + sameName->name();
2889 generateFullName(sameName
->parent(), fullName, sameName);
2890 m_writer->writeCharacters(
".");
2891 m_writer->writeEndElement();
2900 QList<Text> alsoList = node->doc().alsoList();
2901 supplementAlsoList(node, alsoList);
2903 if (!alsoList.isEmpty()) {
2904 startSection(
"See Also");
2906 m_writer->writeStartElement(dbNamespace,
"para");
2907 m_writer->writeStartElement(dbNamespace,
"emphasis");
2908 m_writer->writeCharacters(
"See also ");
2909 m_writer->writeEndElement();
2912 m_writer->writeStartElement(dbNamespace,
"simplelist");
2913 m_writer->writeAttribute(
"type",
"vert");
2914 m_writer->writeAttribute(
"role",
"see-also");
2917 for (
const Text &text : alsoList) {
2918 m_writer->writeStartElement(dbNamespace,
"member");
2919 generateText(text, node);
2920 m_writer->writeEndElement();
2924 m_writer->writeEndElement();
2927 m_writer->writeEndElement();
2935
2936
2937
2938QXmlStreamWriter *
DocBookGenerator::startGenericDocument(
const Node *node,
const QString &fileName)
2941 QFile *outFile = openSubPageFile(
static_cast<
const PageNode*>(node), fileName);
2942 m_writer =
new QXmlStreamWriter(outFile);
2943 m_writer->setAutoFormatting(
false);
2945 m_writer->writeStartDocument();
2947 m_writer->writeNamespace(dbNamespace,
"db");
2948 m_writer->writeNamespace(xlinkNamespace,
"xlink");
2950 m_writer->writeNamespace(itsNamespace,
"its");
2951 m_writer->writeStartElement(dbNamespace,
"article");
2952 m_writer->writeAttribute(
"version",
"5.2");
2953 if (!m_naturalLanguage.isEmpty())
2954 m_writer->writeAttribute(
"xml:lang", m_naturalLanguage);
2958 sectionLevels.resize(0);
2967 m_hasSection =
false;
2970 QString fileName = Generator::fileName(node, fileExtension());
2971 return startGenericDocument(node, fileName);
2976 m_hasSection =
false;
2978 QString fileName = linkForExampleFile(file);
2979 return startGenericDocument(en, fileName);
2984 m_writer->writeEndElement();
2985 m_writer->writeEndDocument();
2987 m_writer->device()->close();
2988 delete m_writer->device();
2994
2995
2996
3001 const auto aggregate =
static_cast<
const Aggregate *>(node);
3007 rawTitle = aggregate->plainName();
3008 fullTitle = aggregate->plainFullName();
3009 title = rawTitle +
" Namespace";
3011 rawTitle = aggregate->plainName();
3013 auto templateDecl = node->templateDecl();
3015 fullTitle = QString(
"%1 %2 ").arg((*templateDecl).to_qstring(), aggregate->typeWord(
false));
3017 fullTitle += aggregate->plainFullName();
3018 title = rawTitle + QLatin1Char(
' ') + aggregate->typeWord(
true);
3020 title = fullTitle = rawTitle = aggregate->fullTitle();
3023 QString subtitleText;
3024 if (rawTitle != fullTitle)
3025 subtitleText = fullTitle;
3028 m_writer = startDocument(node);
3031 generateHeader(title, subtitleText, aggregate);
3040 if (!aggregate
->doc().isEmpty()) {
3041 startSection(
"details",
"Detailed Description");
3043 generateBody(aggregate);
3054 for (
const Section §ion : sectionVector) {
3055 if (section.members().isEmpty())
3058 startSection(section.title().toLower(), section.title());
3060 for (
const Node *member : section.members()) {
3061 if (member->access() == Access::Private)
3064 if (member->nodeType() != Node::Class) {
3066 generateDetailedMember(member, aggregate);
3068 startSectionBegin();
3069 m_writer->writeCharacters(
"class ");
3070 generateFullName(member, aggregate);
3073 generateBrief(member);
3082 generateObsoleteMembers(sections);
3087void DocBookGenerator::generateSynopsisInfo(
const QString &key,
const QString &value)
3089 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3090 m_writer->writeAttribute(
"role", key);
3091 m_writer->writeCharacters(value);
3092 m_writer->writeEndElement();
3098 m_writer->writeTextElement(dbNamespace,
"modifier", value);
3103
3104
3114 if (!m_useDocBook52)
3141 QString synopsisTag = nodeToSynopsisTag(node);
3142 m_writer->writeStartElement(dbNamespace, synopsisTag);
3147 m_writer->writeStartElement(dbNamespace,
"ooclass");
3148 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3149 m_writer->writeEndElement();
3152 m_writer->writeTextElement(dbNamespace,
"namespacename", node->plainName());
3155 m_writer->writeStartElement(dbNamespace,
"ooclass");
3156 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3157 m_writer->writeEndElement();
3159 if (!qcn->groupNames().isEmpty())
3160 m_writer->writeAttribute(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3162 m_writer->writeTextElement(dbNamespace,
"modifier",
"(Qt property)");
3164 m_writer->writeTextElement(dbNamespace,
"type", propertyNode->dataType());
3166 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3170 m_writer->writeTextElement(dbNamespace,
"modifier",
"static");
3173 m_writer->writeTextElement(dbNamespace,
"type", variableNode->dataType());
3175 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3178 m_writer->writeTextElement(dbNamespace,
"enumname", node->plainName());
3181 QString name = node->name();
3183 name.prepend(qpn->element() + QLatin1Char(
'.'));
3185 m_writer->writeTextElement(dbNamespace,
"type", qpn->dataType());
3187 m_writer->writeTextElement(dbNamespace,
"varname", name);
3191 m_writer->writeTextElement(dbNamespace,
"modifier",
"attached");
3195 m_writer->writeTextElement(dbNamespace,
"modifier",
"writable");
3199 m_writer->writeTextElement(dbNamespace,
"modifier",
"required");
3203 generateModifier(
"[read-only]");
3207 generateModifier(
"[default]");
3211 if (functionNode->virtualness() !=
"non")
3212 generateModifier(
"virtual");
3213 if (functionNode->isConst())
3214 generateModifier(
"const");
3215 if (functionNode->isStatic())
3216 generateModifier(
"static");
3221 if (functionNode->returnType() ==
"void")
3222 m_writer->writeEmptyElement(dbNamespace,
"void");
3224 m_writer->writeTextElement(dbNamespace,
"type", functionNode->returnTypeString());
3229 QString name = node->plainName();
3230 if (name.endsWith(
"()"))
3232 m_writer->writeTextElement(dbNamespace,
"methodname", name);
3236 m_writer->writeEmptyElement(dbNamespace,
"void");
3241 for (
int i = 0; i < lp
.count(); ++i) {
3243 m_writer->writeStartElement(dbNamespace,
"methodparam");
3245 m_writer->writeTextElement(dbNamespace,
"type", parameter.type());
3247 m_writer->writeTextElement(dbNamespace,
"parameter", parameter.name());
3249 if (!parameter.defaultValue().isEmpty()) {
3250 m_writer->writeTextElement(dbNamespace,
"initializer", parameter.defaultValue());
3253 m_writer->writeEndElement();
3257 if (functionNode->isDefault())
3258 generateModifier(
"default");
3259 if (functionNode->isFinal())
3260 generateModifier(
"final");
3261 if (functionNode->isOverride())
3262 generateModifier(
"override");
3264 m_writer->writeTextElement(dbNamespace,
"typedefname", node->plainName());
3268 QStringLiteral(
"Unexpected node type in generateDocBookSynopsis: %1")
3269 .arg(node->nodeTypeString()));
3275 for (
const EnumItem &item : enumNode->items()) {
3276 m_writer->writeStartElement(dbNamespace,
"enumitem");
3278 m_writer->writeTextElement(dbNamespace,
"enumidentifier", item.name());
3280 m_writer->writeTextElement(dbNamespace,
"enumvalue", item.value());
3282 m_writer->writeEndElement();
3286 if (enumNode->items().isEmpty()) {
3289 m_writer->writeStartElement(dbNamespace,
"enumitem");
3291 m_writer->writeEmptyElement(dbNamespace,
"enumidentifier");
3293 m_writer->writeEndElement();
3304 generateSynopsisInfo(
"meta", functionNode->metanessString());
3307 generateSynopsisInfo(
"overload",
"overload");
3308 generateSynopsisInfo(
"overload-number",
3309 QString::number(functionNode->overloadNumber()));
3312 if (functionNode->isRef())
3313 generateSynopsisInfo(
"refness", QString::number(1));
3314 else if (functionNode->isRefRef())
3315 generateSynopsisInfo(
"refness", QString::number(2));
3318 QStringList associatedProperties;
3319 const auto &nodes = functionNode->associatedProperties();
3320 for (
const Node *n : nodes) {
3321 const auto pn =
static_cast<
const PropertyNode *>(n);
3322 associatedProperties << pn->name();
3324 associatedProperties.sort();
3325 generateSynopsisInfo(
"associated-property",
3326 associatedProperties.join(QLatin1Char(
',')));
3329 QString signature = functionNode->signature(Node::SignatureReturnType);
3332 signature +=
" final";
3334 signature +=
" override";
3336 signature +=
" = 0";
3338 signature +=
" = default";
3339 generateSynopsisInfo(
"signature", signature);
3345 case Access::Public:
3346 generateSynopsisInfo(
"access",
"public");
3348 case Access::Protected:
3349 generateSynopsisInfo(
"access",
"protected");
3351 case Access::Private:
3352 generateSynopsisInfo(
"access",
"private");
3357 if (node->isAbstract())
3358 generateSynopsisInfo(
"abstract",
"true");
3364 generateSynopsisInfo(
"status",
"active");
3366 case Node::Preliminary:
3367 generateSynopsisInfo(
"status",
"preliminary");
3369 case Node::Deprecated:
3370 generateSynopsisInfo(
"status",
"deprecated");
3372 case Node::Internal:
3373 generateSynopsisInfo(
"status",
"internal");
3376 generateSynopsisInfo(
"status",
"main");
3383 if (aggregate->includeFile()) generateSynopsisInfo(
"headers", *aggregate->includeFile());
3386 if (!aggregate->since().isEmpty())
3387 generateSynopsisInfo(
"since", formatSince(aggregate));
3391 if (!aggregate->physicalModuleName().isEmpty()) {
3395 if (
const auto result = cmakeRequisite(cn)) {
3396 generateSynopsisInfo(
"cmake-find-package", result->first);
3397 generateSynopsisInfo(
"cmake-target-link-libraries", result->second);
3400 if (cn && !cn->qtVariable().isEmpty())
3401 generateSynopsisInfo(
"qmake",
"QT += " + cn->qtVariable());
3409 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3410 m_writer->writeAttribute(
"role",
"nativeTypeFor");
3412 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
3415 for (
auto item : std::as_const(nativeTypes)) {
3416 const Node *otherNode{
nullptr};
3417 Atom a = Atom(Atom::LinkNode, CodeMarker::stringForNode(item));
3418 const QString &link = getAutoLink(&a, aggregate, &otherNode);
3419 generateSimpleLink(link, item->name());
3422 m_writer->writeEndElement();
3426 QList<RelatedClass>::ConstIterator r;
3427 if (!classe->baseClasses().isEmpty()) {
3428 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3429 m_writer->writeAttribute(
"role",
"inherits");
3431 r = classe->baseClasses().constBegin();
3433 while (r != classe->baseClasses().constEnd()) {
3435 generateFullName((*r).m_node, classe);
3437 if ((*r).m_access == Access::Protected) {
3438 m_writer->writeCharacters(
" (protected)");
3439 }
else if ((*r).m_access == Access::Private) {
3440 m_writer->writeCharacters(
" (private)");
3442 m_writer->writeCharacters(
3443 Utilities::comma(index++, classe->baseClasses().size()));
3448 m_writer->writeEndElement();
3453 if (!classe->derivedClasses().isEmpty()) {
3454 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3455 m_writer->writeAttribute(
"role",
"inheritedBy");
3456 generateSortedNames(classe, classe->derivedClasses());
3457 m_writer->writeEndElement();
3466 QString logicalModuleVersion;
3470 logicalModuleVersion = collection->logicalModuleVersion();
3472 logicalModuleVersion = qcn->logicalModuleVersion();
3474 QStringList importText;
3475 importText <<
"import " + qcn->logicalModuleName();
3476 if (!logicalModuleVersion.isEmpty())
3477 importText << logicalModuleVersion;
3478 generateSynopsisInfo(
"import", importText.join(
' '));
3481 if (!qcn->since().isEmpty())
3482 generateSynopsisInfo(
"since", formatSince(qcn));
3487 if (!subs.isEmpty()) {
3488 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3489 m_writer->writeAttribute(
"role",
"inheritedBy");
3491 m_writer->writeEndElement();
3500 const Node *otherNode =
nullptr;
3502 QString link = getAutoLink(&a, base, &otherNode);
3504 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3505 m_writer->writeAttribute(
"role",
"inherits");
3506 generateSimpleLink(link, base->name());
3507 m_writer->writeEndElement();
3515 const Node *otherNode =
nullptr;
3517 QString link = getAutoLink(&a, cn, &otherNode);
3519 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3520 m_writer->writeAttribute(
"role",
"nativeType");
3521 generateSimpleLink(link, cn->name());
3522 m_writer->writeEndElement();
3529 case Node::UnspecifiedSafeness:
3530 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3532 case Node::NonReentrant:
3533 generateSynopsisInfo(
"threadsafeness",
"non-reentrant");
3535 case Node::Reentrant:
3536 generateSynopsisInfo(
"threadsafeness",
"reentrant");
3538 case Node::ThreadSafe:
3539 generateSynopsisInfo(
"threadsafeness",
"thread safe");
3542 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3547 if (!node->physicalModuleName().isEmpty())
3548 generateSynopsisInfo(
"module", node->physicalModuleName());
3551 if (classNode && !classNode->groupNames().isEmpty()) {
3552 generateSynopsisInfo(
"groups", classNode->groupNames().join(QLatin1Char(
',')));
3553 }
else if (qcn && !qcn->groupNames().isEmpty()) {
3554 generateSynopsisInfo(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3559 for (
const Node *fnNode : propertyNode->getters()) {
3561 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3562 generateSynopsisInfo(
"getter", funcNode->name());
3565 for (
const Node *fnNode : propertyNode->setters()) {
3567 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3568 generateSynopsisInfo(
"setter", funcNode->name());
3571 for (
const Node *fnNode : propertyNode->resetters()) {
3573 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3574 generateSynopsisInfo(
"resetter", funcNode->name());
3577 for (
const Node *fnNode : propertyNode->notifiers()) {
3579 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3580 generateSynopsisInfo(
"notifier", funcNode->name());
3585 m_writer->writeEndElement();
3591 m_writer->writeStartElement(dbNamespace,
"typedefsynopsis");
3594 m_writer->writeTextElement(dbNamespace,
"typedefname",
3595 enumNode->flagsType()->fullDocumentName());
3598 m_writer->writeEndElement();
3609 return node->name().mid(4);
3610 return node->name();
3614
3615
3616
3617void DocBookGenerator::typified(
const QString &string,
const Node *relative,
bool trailingSpace,
3622 QString pendingWord;
3624 for (
int i = 0; i <= string.size(); ++i) {
3626 if (i != string.size())
3629 QChar lower = ch.toLower();
3630 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
3631 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
3634 if (!pendingWord.isEmpty()) {
3635 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
3636 if (generateType && isProbablyType) {
3638 m_writer->writeCharacters(result);
3647 href = linkForNode(n, relative);
3650 m_writer->writeStartElement(dbNamespace,
"type");
3652 m_writer->writeCharacters(pendingWord);
3654 generateSimpleLink(href, pendingWord);
3655 m_writer->writeEndElement();
3657 result += pendingWord;
3660 pendingWord.clear();
3662 if (ch.unicode() !=
'\0')
3667 if (trailingSpace && string.size()) {
3668 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
3669 result += QLatin1Char(
' ');
3672 m_writer->writeCharacters(result);
3676 bool generateNameLink)
3680 QString name = taggedNode(node);
3682 if (!generateNameLink) {
3683 m_writer->writeCharacters(name);
3687 m_writer->writeStartElement(dbNamespace,
"emphasis");
3688 m_writer->writeAttribute(
"role",
"bold");
3689 generateSimpleLink(linkForNode(node, relative), name);
3690 m_writer->writeEndElement();
3694 bool generateExtra,
bool generateType)
3696 const QString &pname = parameter.name();
3697 const QString &ptype = parameter.type();
3699 if (!pname.isEmpty()) {
3700 typified(ptype, relative,
true, generateType);
3706 if (generateExtra || pname.isEmpty()) {
3707 m_writer->writeStartElement(dbNamespace,
"emphasis");
3708 m_writer->writeCharacters(paramName);
3709 m_writer->writeEndElement();
3712 const QString &pvalue = parameter.defaultValue();
3713 if (generateExtra && !pvalue.isEmpty())
3714 m_writer->writeCharacters(
" = " + pvalue);
3726 const int MaxEnumValues = 6;
3728 if (generateExtra) {
3729 if (
auto extra = CodeMarker::extraSynopsis(node, style); !extra.isEmpty())
3730 m_writer->writeCharacters(extra +
" ");
3734 QString namePrefix {};
3738 namePrefix = taggedNode(node->parent()) +
"::";
3743 case Node::Namespace:
3744 m_writer->writeCharacters(
"namespace ");
3745 m_writer->writeCharacters(namePrefix);
3746 generateSynopsisName(node, relative, generateNameLink);
3749 m_writer->writeCharacters(
"class ");
3750 m_writer->writeCharacters(namePrefix);
3751 generateSynopsisName(node, relative, generateNameLink);
3758 if (!func->isNonvirtual())
3759 m_writer->writeCharacters(QStringLiteral(
"virtual "));
3763 if (style != Section::AllMembers && !func->returnType().isEmpty())
3764 typified(func->returnTypeString(), relative,
true, generateType);
3765 m_writer->writeCharacters(namePrefix);
3766 generateSynopsisName(node, relative, generateNameLink);
3769 m_writer->writeCharacters(QStringLiteral(
"("));
3772 for (
int i = 0; i < parameters
.count(); i++) {
3774 m_writer->writeCharacters(QStringLiteral(
", "));
3775 generateParameter(parameters
.at(i
), relative, generateExtra, generateType);
3778 m_writer->writeCharacters(QStringLiteral(
")"));
3781 if (func->isConst())
3782 m_writer->writeCharacters(QStringLiteral(
" const"));
3788 synopsis += QStringLiteral(
" final");
3790 synopsis += QStringLiteral(
" override");
3792 synopsis += QStringLiteral(
" = 0");
3794 synopsis += QStringLiteral(
" &");
3796 synopsis += QStringLiteral(
" &&");
3797 m_writer->writeCharacters(synopsis);
3799 if (!func->returnType().isEmpty() && func->returnType() !=
"void") {
3800 m_writer->writeCharacters(QStringLiteral(
" : "));
3801 typified(func->returnTypeString(), relative,
false, generateType);
3806 synopsis += QStringLiteral(
" &");
3808 synopsis += QStringLiteral(
" &&");
3809 m_writer->writeCharacters(synopsis);
3813 const auto enume =
static_cast<
const EnumNode *>(node);
3814 m_writer->writeCharacters(QStringLiteral(
"enum "));
3815 m_writer->writeCharacters(namePrefix);
3816 generateSynopsisName(node, relative, generateNameLink);
3822 QStringList documentedItems = enume->doc().enumItemNames();
3823 if (documentedItems.isEmpty()) {
3824 const auto &enumItems = enume->items();
3825 for (
const auto &item : enumItems)
3826 documentedItems << item.name();
3828 const QStringList omitItems = enume->doc().omitEnumItemNames();
3829 for (
const auto &item : omitItems)
3830 documentedItems.removeAll(item);
3832 if (documentedItems.size() > MaxEnumValues) {
3834 const QString last = documentedItems.last();
3835 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
3836 documentedItems +=
"…";
3837 documentedItems += last;
3839 synopsis += documentedItems.join(QLatin1String(
", "));
3841 if (!documentedItems.isEmpty())
3842 synopsis += QLatin1Char(
' ');
3843 synopsis += QLatin1Char(
'}');
3845 m_writer->writeCharacters(synopsis);
3849 auto templateDecl = node->templateDecl();
3851 m_writer->writeCharacters((*templateDecl).to_qstring() + QLatin1Char(
' '));
3853 m_writer->writeCharacters(namePrefix);
3854 generateSynopsisName(node, relative, generateNameLink);
3857 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
3858 m_writer->writeCharacters(
"flags ");
3859 m_writer->writeCharacters(namePrefix);
3860 generateSynopsisName(node, relative, generateNameLink);
3863 const auto property =
static_cast<
const PropertyNode *>(node);
3864 m_writer->writeCharacters(namePrefix);
3865 generateSynopsisName(node, relative, generateNameLink);
3866 m_writer->writeCharacters(
" : ");
3867 typified(property->qualifiedDataType(), relative,
false, generateType);
3870 const auto variable =
static_cast<
const VariableNode *>(node);
3872 generateSynopsisName(node, relative, generateNameLink);
3873 m_writer->writeCharacters(
" : ");
3874 typified(variable->dataType(), relative,
false, generateType);
3876 typified(variable->leftType(), relative,
false, generateType);
3877 m_writer->writeCharacters(
" ");
3878 m_writer->writeCharacters(namePrefix);
3879 generateSynopsisName(node, relative, generateNameLink);
3880 m_writer->writeCharacters(variable->rightType());
3884 m_writer->writeCharacters(namePrefix);
3885 generateSynopsisName(node, relative, generateNameLink);
3898 if (qpn->enumNode() && !enumValue.startsWith(
"%1."_L1.arg(qpn->enumPrefix()))) {
3899 m_writer->writeCharacters(
"%1.%2"_L1.arg(qpn->enumPrefix(), enumValue));
3905 m_writer->writeCharacters(enumValue);
3909 QList<
const Node *> parents;
3911 parents.prepend(node);
3917 parents << relative;
3919 m_writer->writeStartElement(dbNamespace,
"code");
3920 for (
auto parent : parents) {
3921 generateSynopsisName(parent, relative,
true);
3922 m_writer->writeCharacters(
"::");
3925 m_writer->writeCharacters(enumValue);
3926 m_writer->writeEndElement();
3930
3931
3932
3933
3934
3935
3936
3940 QString code = getOverloadedSignalCode(node);
3944 m_writer->writeStartElement(dbNamespace,
"note");
3946 m_writer->writeStartElement(dbNamespace,
"para");
3947 m_writer->writeCharacters(
"Signal ");
3948 m_writer->writeTextElement(dbNamespace,
"emphasis", node->name());
3949 m_writer->writeCharacters(
" is overloaded in this class. To connect to this "
3950 "signal by using the function pointer syntax, Qt "
3951 "provides a convenient helper for obtaining the "
3952 "function pointer as shown in this example:");
3953 m_writer->writeTextElement(dbNamespace,
"code", code);
3954 m_writer->writeEndElement();
3956 m_writer->writeEndElement();
3961
3962
3963
3968 Q_ASSERT(node && !node->name().isEmpty());
3970 m_writer->writeStartElement(dbNamespace,
"note");
3975 m_writer->writeStartElement(dbNamespace,
"para");
3976 m_writer->writeCharacters(
3977 "This function can be invoked via the meta-object system and from QML. See ");
3978 generateSimpleLink(node->url(),
"Q_INVOKABLE");
3979 m_writer->writeCharacters(
".");
3980 m_writer->writeEndElement();
3984 m_writer->writeTextElement(
3985 dbNamespace,
"para",
3986 "This is a private signal. It can be used in signal connections but "
3987 "cannot be emitted by the user.");
3991 QString handler(node->name());
3992 int prefixLocation = handler.lastIndexOf(
'.', -2) + 1;
3993 handler[prefixLocation] = handler[prefixLocation].toTitleCase();
3994 handler.insert(prefixLocation, QLatin1String(
"on"));
3995 m_writer->writeStartElement(dbNamespace,
"para");
3996 m_writer->writeCharacters(
"The corresponding handler is ");
3997 m_writer->writeTextElement(dbNamespace,
"code", handler);
3998 m_writer->writeCharacters(
".");
3999 m_writer->writeEndElement();
4007 const auto *fn =
static_cast<
const FunctionNode *>(node);
4008 auto propertyNodes = fn->associatedProperties();
4009 if (propertyNodes.isEmpty())
4012 for (
const auto propertyNode : std::as_const(propertyNodes)) {
4014 const auto pn =
static_cast<
const PropertyNode *>(propertyNode);
4015 switch (pn->role(fn)) {
4016 case PropertyNode::FunctionRole::Getter:
4017 msg = QStringLiteral(
"Getter function");
4019 case PropertyNode::FunctionRole::Setter:
4020 msg = QStringLiteral(
"Setter function");
4022 case PropertyNode::FunctionRole::Resetter:
4023 msg = QStringLiteral(
"Resetter function");
4025 case PropertyNode::FunctionRole::Notifier:
4026 msg = QStringLiteral(
"Notifier signal");
4031 m_writer->writeStartElement(dbNamespace,
"para");
4032 m_writer->writeCharacters(msg +
" for property ");
4033 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4034 m_writer->writeCharacters(
". ");
4035 m_writer->writeEndElement();
4042 const Node *linkNode;
4044 QString link = getAutoLink(&linkAtom, node, &linkNode);
4045 m_writer->writeStartElement(dbNamespace,
"para");
4046 m_writer->writeCharacters(
"This property supports ");
4047 generateSimpleLink(link,
"QProperty");
4048 m_writer->writeCharacters(
" bindings.");
4049 m_writer->writeEndElement();
4058 m_writer->writeEndElement();
4066 bool closeSupplementarySection =
false;
4070 const QList<Node *> &collective = scn->collective();
4072 bool firstFunction =
true;
4073 for (
const auto *sharedNode : collective) {
4074 if (firstFunction) {
4075 startSectionBegin(sharedNode);
4077 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4078 m_writer->writeAttribute(
"renderas",
"sect2");
4079 writeXmlId(sharedNode);
4082 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4084 generateSynopsis(sharedNode, relative, Section::Details);
4086 if (firstFunction) {
4088 firstFunction =
false;
4090 m_writer->writeEndElement();
4097 startSectionBegin(node);
4099 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4103 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4104 m_writer->writeAttribute(
"renderas",
"sect2");
4106 m_writer->writeEndElement();
4109 startSectionBegin(node);
4111 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4116 Q_ASSERT(m_hasSection);
4125 closeSupplementarySection =
true;
4126 startSection(
"",
"Notes");
4129 generateOverloadedSignal(node);
4135 const auto property =
static_cast<
const PropertyNode *>(node);
4144 m_writer->writeStartElement(dbNamespace,
"para");
4146 m_writer->writeStartElement(dbNamespace,
"emphasis");
4147 m_writer->writeAttribute(
"role",
"bold");
4148 m_writer->writeCharacters(
"Access functions:");
4150 m_writer->writeEndElement();
4152 m_writer->writeEndElement();
4154 generateSectionList(section, node);
4161 m_writer->writeStartElement(dbNamespace,
"para");
4163 m_writer->writeStartElement(dbNamespace,
"emphasis");
4164 m_writer->writeAttribute(
"role",
"bold");
4165 m_writer->writeCharacters(
"Notifier signal:");
4167 m_writer->writeEndElement();
4169 m_writer->writeEndElement();
4171 generateSectionList(notifiers, node);
4175 const auto en =
static_cast<
const EnumNode *>(node);
4177 if (m_qflagsHref.isEmpty()) {
4178 Node *qflags =
m_qdb->findClassNode(QStringList(
"QFlags"));
4180 m_qflagsHref = linkForNode(qflags,
nullptr);
4184 m_writer->writeStartElement(dbNamespace,
"para");
4185 m_writer->writeCharacters(
"The ");
4186 m_writer->writeStartElement(dbNamespace,
"code");
4187 m_writer->writeCharacters(en->flagsType()->name());
4188 m_writer->writeEndElement();
4189 m_writer->writeCharacters(
" type is a typedef for ");
4190 m_writer->writeStartElement(dbNamespace,
"code");
4191 generateSimpleLink(m_qflagsHref,
"QFlags");
4192 m_writer->writeCharacters(
"<" + en->name() +
">. ");
4193 m_writer->writeEndElement();
4194 m_writer->writeCharacters(
"It stores an OR combination of ");
4195 m_writer->writeStartElement(dbNamespace,
"code");
4196 m_writer->writeCharacters(en->name());
4197 m_writer->writeEndElement();
4198 m_writer->writeCharacters(
" values.");
4199 m_writer->writeEndElement();
4204 if (closeSupplementarySection)
4215 bool useObsoleteMembers)
4220 if (!members.isEmpty()) {
4221 bool hasPrivateSignals =
false;
4222 bool isInvokable =
false;
4224 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4226 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4229 NodeVector::ConstIterator m = members.constBegin();
4230 while (m != members.constEnd()) {
4231 if ((*m)->access() == Access::Private) {
4236 m_writer->writeStartElement(dbNamespace,
"listitem");
4238 m_writer->writeStartElement(dbNamespace,
"para");
4241 generateSynopsis(*m, relative, section
.style());
4242 if ((*m)->isFunction()) {
4244 if (fn->isPrivateSignal())
4245 hasPrivateSignals =
true;
4246 else if (fn->isInvokable())
4250 m_writer->writeEndElement();
4252 m_writer->writeEndElement();
4258 m_writer->writeEndElement();
4261 if (hasPrivateSignals)
4268 && !section.inheritedMembers().isEmpty()) {
4269 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4271 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4274 generateSectionInheritedList(section, relative);
4276 m_writer->writeEndElement();
4284 QList<std::pair<Aggregate *,
int>>::ConstIterator p = section.inheritedMembers().constBegin();
4285 while (p != section.inheritedMembers().constEnd()) {
4286 m_writer->writeStartElement(dbNamespace,
"listitem");
4287 m_writer->writeCharacters(QString::number((*p).second) + u' ');
4288 if ((*p).second == 1)
4289 m_writer->writeCharacters(section.singular());
4291 m_writer->writeCharacters(section.plural());
4292 m_writer->writeCharacters(
" inherited from ");
4293 generateSimpleLink(fileName((*p).first) +
'#'
4294 + Generator::cleanRef(section.title().toLower()),
4295 (*p).first->plainFullName(relative));
4301
4302
4303
4307 Q_ASSERT(m_writer ==
nullptr);
4308 m_writer = startDocument(pn);
4310 generateHeader(pn->fullTitle(), pn->subtitle(), pn);
4319
4320
4325 Q_ASSERT(m_writer ==
nullptr);
4326 m_writer = startDocument(qcn);
4329 QString title = qcn->fullTitle();
4331 title.append(
" QML Value Type");
4333 title.append(
" QML Type");
4339 generateHeader(title, qcn->subtitle(), qcn);
4343 startSection(
"details",
"Detailed Description");
4351 for (
const auto §ion : sections.stdQmlTypeDetailsSections()) {
4352 if (!section.isEmpty()) {
4353 startSection(section.title().toLower(), section.title());
4355 for (
const auto &member : section.members())
4356 generateDetailedQmlMember(member, qcn);
4362 generateObsoleteQmlMembers(sections);
4371
4372
4373
4379 QString title{CodeMarker::extraSynopsis(n, Section::Details)};
4380 if (!title.isEmpty())
4384 title += n->element() + QLatin1Char(
'.');
4385 title += n->name() +
" : " + n->dataType();
4390 auto generateQmlMethodTitle = [&](
Node *node) {
4398 if (!scn->name().isEmpty())
4399 heading = scn->name() +
" group";
4401 heading = node->name();
4402 startSection(scn, heading);
4407 const QList<Node *> sharedNodes = scn->collective();
4408 for (
const auto &sharedNode : sharedNodes) {
4409 if (sharedNode->isQmlProperty()) {
4410 auto *qpn =
static_cast<QmlPropertyNode *>(sharedNode);
4412 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4413 m_writer->writeAttribute(
"renderas",
"sect2");
4415 m_writer->writeCharacters(getQmlPropertyTitle(qpn));
4416 m_writer->writeEndElement();
4419 generateDocBookSynopsis(qpn);
4424 startSection(qpn, getQmlPropertyTitle(qpn));
4428 const QList<Node *> &sharedNodes = scn->collective();
4433 for (
const auto &sharedNode : sharedNodes) {
4435 if (!sharedNode->isFunction(Node::QML) && !sharedNode->isQmlProperty()) {
4441 startSectionBegin(sharedNode);
4443 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4444 m_writer->writeAttribute(
"renderas",
"sect2");
4448 if (sharedNode->isFunction(Node::QML))
4449 generateQmlMethodTitle(sharedNode);
4450 else if (sharedNode->isQmlProperty())
4451 m_writer->writeCharacters(
4452 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(sharedNode)));
4458 m_writer->writeEndElement();
4459 generateDocBookSynopsis(sharedNode);
4465 startSectionBegin(refForNode(node));
4468 generateQmlMethodTitle(node);
4469 else if (node->isQmlProperty())
4470 m_writer->writeCharacters(
4471 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(node)));
4476 startSectionBegin(node);
4477 generateQmlMethodTitle(node);
4491
4492
4499 if (!node->url().isNull())
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4544 generateCppReferencePage(
static_cast<
Aggregate *>(node));
4554 auto *aggregate =
static_cast<
Aggregate *>(node);
4555 for (
auto c : aggregate->childNodes()) {
4556 if (node->isPageNode() && !node->isPrivate())
4557 generateDocumentation(c);
4568 Q_ASSERT(m_writer ==
nullptr);
4569 m_writer = startDocument(aggregate);
4572 generateHeader(aggregate->plainFullName(),
"", aggregate);
4577 if (!aggregate
->doc().isEmpty()) {
4578 startSection(
"details",
"Detailed Description");
4580 generateBody(aggregate);
4589 for (
const auto §ion : std::as_const(*detailsSections)) {
4590 if (section.isEmpty())
4593 startSection(section.title().toLower(), section.title());
4595 const QList<Node *> &members = section.members();
4596 for (
const auto &member : members) {
4597 if (!member->isPrivate()) {
4598 if (!member->isClassNode()) {
4599 generateDetailedMember(member, aggregate);
4601 startSectionBegin();
4602 generateFullName(member, aggregate);
4605 generateBrief(member);
4620
4621
4626 Q_ASSERT(m_writer ==
nullptr);
4627 m_writer = startDocument(cn);
4630 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4647 if (!nmm.isEmpty()) {
4648 startSection(
"namespaces",
"Namespaces");
4649 generateAnnotatedList(cn, nmm.values(),
"namespaces");
4653 if (!nmm.isEmpty()) {
4654 startSection(
"classes",
"Classes");
4655 generateAnnotatedList(cn, nmm.values(),
"classes");
4661 bool generatedTitle =
false;
4663 startSection(
"details",
"Detailed Description");
4664 generatedTitle =
true;
4669 !cn
->doc().body().isEmpty() ||
4671 !cn
->doc().alsoList().empty() ||
4674 writeAnchor(
"details");
4680 if (!cn->noAutoList() && (cn->isGroup() || cn->isQmlModule()))
4681 generateAnnotatedList(cn, cn->members(),
"members", AutoSection);
4692
4693
4694
4695
4700 QString name = cn->name().toLower();
4701 name.replace(QChar(
' '), QString(
"-"));
4702 QString filename = cn->tree()->physicalModuleName() +
"-" + name +
"." + fileExtension();
4705 Q_ASSERT(m_writer ==
nullptr);
4706 m_writer = startGenericDocument(cn, filename);
4709 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4715 m_writer->writeStartElement(dbNamespace,
"para");
4716 m_writer->writeCharacters(
"Each function or type documented here is related to a class or "
4717 "namespace that is documented in a different module. The reference "
4718 "page for that class or namespace will link to the function or type "
4720 m_writer->writeEndElement();
4723 const QList<Node *> members = cn->members();
4724 for (
const auto &member : members)
4725 generateDetailedMember(member, cnc);
4738 m_writer->writeStartElement(dbNamespace,
"link");
4739 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(node));
4740 m_writer->writeAttribute(xlinkNamespace,
"role", targetType(node));
4741 m_writer->writeCharacters(node->fullName(relative));
4742 m_writer->writeEndElement();
4746 const Node *actualNode)
4748 Q_ASSERT(apparentNode);
4749 Q_ASSERT(actualNode);
4752 m_writer->writeStartElement(dbNamespace,
"link");
4753 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(actualNode));
4754 m_writer->writeAttribute(
"role", targetType(actualNode));
4755 m_writer->writeCharacters(fullName);
4756 m_writer->writeEndElement();
#define ATOM_FORMATTING_TELETYPE
#define ATOM_LIST_LOWERALPHA
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_LIST_UPPERALPHA
#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(Node::NodeType type) const
Returns a map containing this collection node's member nodes with a specified node type.
bool wasSeen() const override
Returns the seen flag data member of this node if it is a NamespaceNode or a CollectionNode.
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 generateSortedQmlNames(const Node *base, const NodeList &subs)
void initializeGenerator() override
Initializes the DocBook output generator's data structures from the configuration (Config).
void generateExampleFilePage(const Node *en, ResolvedFile resolved_file, CodeMarker *=nullptr) override
Generate a file with the contents of a C++ or QML source file.
bool generateText(const Text &text, const Node *relative) override
Generate the documentation for relative.
void generateCppReferencePage(Node *node)
Generate a reference page for the C++ class, namespace, or header file documented in node.
void generateHeader(const QString &title, const QString &subtitle, const Node *node)
Generate the DocBook header for the file, including the abstract.
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.
QString format() override
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...
void generateAddendum(const Node *node, Generator::Addendum type, CodeMarker *marker, bool generateNote) override
Generates an addendum note of type type for node.
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)
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 isDefault() const override
Returns true if the QML property node is marked as default.
bool isPureVirtual() const
bool isMacro() const override
returns true if either FunctionNode::isMacroWithParams() or FunctionNode::isMacroWithoutParams() retu...
bool hasAssociatedProperties() const
bool generateComparisonCategory(const Node *node, CodeMarker *marker=nullptr)
static bool hasExceptions(const Node *node, NodeList &reentrant, NodeList &threadsafe, NodeList &nonreentrant)
void generateEnumValuesForQmlProperty(const Node *node, CodeMarker *marker)
FileResolver & file_resolver
static void setQmlTypeContext(QmlTypeNode *t)
const Atom * generateAtomList(const Atom *atom, const Node *relative, CodeMarker *marker, bool generate, int &numGeneratedAtoms)
bool generateComparisonList(const Node *node)
Generates a list of types that compare to node with the comparison category that applies for the rela...
void unknownAtom(const Atom *atom)
static bool matchAhead(const Atom *atom, Atom::AtomType expectedAtomType)
virtual int skipAtoms(const Atom *atom, Atom::AtomType type) const
bool m_threeColumnEnumValueTable
virtual void initializeGenerator()
Updates the generator's m_showInternal from the Config.
void initializeTextOutput()
Resets the variables used during text output.
This class represents a C++ namespace.
NamespaceNode * docNode() const
Returns a pointer to the NamespaceNode that represents where the namespace documentation is actually ...
bool isGenericCollection() const
Returns true if the node type is Collection.
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 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.
NodeType
An unsigned char value that identifies an object as a particular subclass of Node.
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 isFunction(Genus g=DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
bool isSharedCommentNode() const
Returns true if the node type is SharedComment.
virtual bool isInternal() const
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
bool isHeader() const
Returns true if the node type is HeaderFile.
virtual bool isPageNode() const
Returns true if this node represents something that generates a documentation page.
bool isEnumType() const
Returns true if the node type is Enum.
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...
NodeType nodeType() const
Returns this node's type.
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.
ThreadSafeness threadSafeness() const
Returns the thread safeness value for whatever this node represents.
Genus
An unsigned char value that specifies whether the Node represents a C++ element, a QML element,...
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.
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...
Genus genus() const
Returns this node's Genus.
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...
LinkType
An unsigned char value that probably should be moved out of the Node base class.
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.
Status status() const
Returns the node's status value.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.
A PageNode is a Node that generates a documentation page.
bool noAutoList() const
Returns the value of the no auto-list flag.
The Parameter class describes one function parameter.
A class for parsing and managing a function parameter list.
const Parameter & at(int i) const
This class describes one instance of using the Q_PROPERTY macro.
const NodeList & getters() const
const NodeList & resetters() const
const NodeList & setters() const
PropertyType propertyType() const
const NodeList & notifiers() const
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
NodeMapMap & getFunctionIndex()
Returns the function index.
TextToNodeMap & getLegaleseTexts()
Returns a reference to the collection of legalese texts.
NodeMultiMap & getAttributions()
Returns a reference to the multimap of attribution nodes.
NodeMultiMap & getQmlTypesWithObsoleteMembers()
Returns a reference to the map of QML types with obsolete members.
NodeMultiMap & getObsoleteQmlTypes()
Returns a reference to the map of obsolete QML types.
static QDocDatabase * qdocDB()
Creates the singleton.
NodeMultiMap & getQmlTypes()
Returns a reference to the multimap of QML types.
NodeMultiMap & getClassesWithObsoleteMembers()
Returns a reference to the map of C++ classes with obsolete members.
NodeMultiMap & getQmlValueTypes()
Returns a reference to the map of QML basic types.
NodeMultiMap & getCppClasses()
Returns a reference to the map of all C++ classes.
NodeMultiMap & getNamespaces()
Returns a reference to the namespace map.
NodeMultiMap & getExamples()
Returns a reference to the multimap of example nodes.
NodeMultiMap & getObsoleteClasses()
Returns a reference to the map of obsolete C++ clases.
void mergeCollections(Node::NodeType type, CNMap &cnm, const Node *relative)
Finds all the collection nodes of the specified type and merges them into the collection node map cnm...
void mergeCollections(CollectionNode *c)
Finds all the collection nodes with the same name and type as c and merges their members into the mem...
const CNMap & groups()
Returns a const reference to the collection of all group nodes in the primary tree.
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()
Returns true if this QML property is marked with \required or the corresponding C++ property uses the...
bool isReadOnly()
Returns true if this QML property or attached property is read-only.
bool isAttached() const override
Returns true if the QML property or QML method node is marked as attached.
ClassNode * classNode() override
If this is a QmlTypeNode, this function returns the pointer to the C++ ClassNode that this QML type r...
bool isInternal() const override
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
static void subclasses(const Node *base, NodeList &subs)
Loads the list subs with the nodes of all the subclasses of base.
QmlTypeNode * qmlBaseNode() const override
If this Aggregate is a QmlTypeNode, this function returns a pointer to the QmlTypeNode that is its ba...
CollectionNode * logicalModule() const override
If this is a QmlTypeNode, a pointer to its QML module is returned, which is a pointer to a Collection...
A class for containing the elements of one documentation section.
const NodeVector & obsoleteMembers() const
void appendMembers(const NodeVector &nv)
const NodeVector & members() const
A class for creating vectors of collections for documentation.
Aggregate * aggregate() const
Sections(Aggregate *aggregate)
This constructor builds the vectors of sections based on the type of the aggregate node.
SectionVector & stdDetailsSections()
SectionVector & stdCppClassDetailsSections()
bool hasObsoleteMembers(SectionPtrVector *summary_spv, SectionPtrVector *details_spv) const
Returns true if any sections in this object contain obsolete members.
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 isThreeColumnEnumValueTable(const Atom *atom)
Determines whether the list atom should be shown with three columns (constant-value-description).
static Node::NodeType typeFromString(const Atom *atom)
Returns the type of this atom as an enumeration.
static 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
#define CONFIG_DOCBOOKEXTENSIONS
#define CONFIG_DESCRIPTION
#define CONFIG_EXAMPLESINSTALLPATH
#define CONFIG_NATURALLANGUAGE
#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[]
Combined button and popup list for selecting options.
QList< Node * > NodeVector
QMap< QString, Node * > NodeMap
QMap< QString, NodeMap > NodeMapMap
QMap< QString, CollectionNode * > CNMap
QT_BEGIN_NAMESPACE typedef QMultiMap< Text, const Node * > TextToNodeMap
QList< const Section * > SectionPtrVector
QList< Section > SectionVector
Represents a file that is reachable by QDoc based on its current configuration.