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();
148 if (m_projectDescription.isEmpty() && !m_project.isEmpty())
149 m_projectDescription = m_project + QLatin1String(
" Reference Documentation");
152 if (m_naturalLanguage.isEmpty())
153 m_naturalLanguage = QLatin1String(
"en");
157 m_config->get(format() + Config::dot +
"usedocbookextensions").asBool();
158 m_useITS = m_config->get(format() + Config::dot +
"its").asBool();
167
168
175
176
177
178
193 QString rewritten = code;
194 static const QRegularExpression re(
"(<@[^>&]*>)|(<\\/@[^&>]*>)");
195 rewritten.replace(re,
"");
200
201
217 const Node *node =
nullptr;
218 QString link = getAutoLink(atom, relative, &node, genus);
223 if (link.isEmpty()) {
224 m_writer->writeCharacters(atom->string());
226 beginLink(link, node, relative);
231 m_writer->writeCharacters(atom->string());
241 m_writer->writeStartElement(dbNamespace,
"para");
247 m_writer->writeEndElement();
257 m_writer->writeCharacters(plainCode(atom->string()));
259 m_writer->writeTextElement(dbNamespace,
"code", plainCode(atom->string()));
261 case Atom::CaptionLeft:
262 m_writer->writeStartElement(dbNamespace,
"title");
266 m_writer->writeEndElement();
270 m_writer->writeStartElement(dbNamespace,
"programlisting");
271 m_writer->writeAttribute(
"language",
"qml");
273 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
274 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
275 m_writer->writeEndElement();
279 m_writer->writeStartElement(dbNamespace,
"programlisting");
280 m_writer->writeAttribute(
"language",
"cpp");
282 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
283 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
284 m_writer->writeEndElement();
288 m_writer->writeStartElement(dbNamespace,
"programlisting");
289 m_writer->writeAttribute(
"language",
"cpp");
290 m_writer->writeAttribute(
"role",
"bad");
292 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
293 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
294 m_writer->writeEndElement();
303 case Atom::FootnoteLeft:
304 m_writer->writeStartElement(dbNamespace,
"footnote");
306 m_writer->writeStartElement(dbNamespace,
"para");
309 case Atom::FootnoteRight:
310 m_writer->writeEndElement();
313 m_writer->writeEndElement();
321 m_writer->writeStartElement(dbNamespace,
"emphasis");
322 m_writer->writeAttribute(
"role",
"bold");
324 m_writer->writeStartElement(dbNamespace,
"emphasis");
326 m_writer->writeStartElement(dbNamespace,
"emphasis");
327 m_writer->writeAttribute(
"role",
"underline");
329 m_writer->writeStartElement(dbNamespace,
"subscript");
331 m_writer->writeStartElement(dbNamespace,
"superscript");
334 m_writer->writeStartElement(dbNamespace,
"code");
336 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
339 m_writer->writeAttribute(
"role",
"parameter");
343 m_writer->writeStartElement(dbNamespace,
"guilabel");
345 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
347 m_writer->writeStartElement(dbNamespace,
348 appendTrademark(atom->find(Atom::FormattingRight)) ?
349 "trademark" :
"phrase");
351 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
353 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
365 m_writer->writeEndElement();
368 m_inTeletype =
false;
371 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
375 if (
const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), Node::Group))
376 generateList(cn, atom->string(), Generator::sortOrder(atom->strings().last()));
379 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
380 bool hasGeneratedSomething =
false;
381 if (atom->string() == QLatin1String(
"annotatedclasses")
382 || atom->string() == QLatin1String(
"attributions")
383 || atom->string() == QLatin1String(
"namespaces")) {
384 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedclasses")
388 generateAnnotatedList(relative, things.values(), atom->string(), Auto, sortOrder);
389 hasGeneratedSomething = !things.isEmpty();
390 }
else if (atom->string() == QLatin1String(
"annotatedexamples")
391 || atom->string() == QLatin1String(
"annotatedattributions")) {
392 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedexamples")
395 generateAnnotatedLists(relative, things, atom->string());
396 hasGeneratedSomething = !things.isEmpty();
397 }
else if (atom->string() == QLatin1String(
"classes")
398 || atom->string() == QLatin1String(
"qmlbasictypes")
399 || atom->string() == QLatin1String(
"qmlvaluetypes")
400 || atom->string() == QLatin1String(
"qmltypes")) {
401 const NodeMultiMap things = atom->string() == QLatin1String(
"classes")
403 : (atom->string() == QLatin1String(
"qmlvaluetypes")
404 || atom->string() == QLatin1String(
"qmlbasictypes"))
407 generateCompactList(relative, things,
true, QString(), atom->string());
408 hasGeneratedSomething = !things.isEmpty();
409 }
else if (atom->string().contains(
"classes ")) {
410 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
413 hasGeneratedSomething = !things.isEmpty();
414 generateCompactList(relative, things,
true, rootName, atom->string());
415 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
416 QString moduleName = atom->string().mid(idx + 8).trimmed();
419 if (
const CollectionNode *cn = qdb->getCollectionNode(moduleName, moduleType)) {
421 switch (moduleType) {
427 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
433 generateAnnotatedList(relative, cn->members(), atom->string(), Auto, sortOrder);
437 if (!map.isEmpty()) {
438 generateAnnotatedList(relative, map.values(), atom->string(), Auto, sortOrder);
439 hasGeneratedSomething =
true;
442 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
445 }
else if (atom->string().startsWith(
"obsolete")) {
446 QString prefix = atom->string().contains(
"cpp") ? QStringLiteral(
"Q") : QString();
447 const NodeMultiMap &things = atom->string() == QLatin1String(
"obsoleteclasses")
449 : atom->string() == QLatin1String(
"obsoleteqmltypes")
451 : atom->string() == QLatin1String(
"obsoletecppmembers")
454 generateCompactList(relative, things,
false, prefix, atom->string());
455 hasGeneratedSomething = !things.isEmpty();
456 }
else if (atom->string() == QLatin1String(
"functionindex")) {
457 generateFunctionIndex(relative);
459 }
else if (atom->string() == QLatin1String(
"legalese")) {
460 generateLegaleseList(relative);
462 }
else if (atom->string() == QLatin1String(
"overviews")
463 || atom->string() == QLatin1String(
"cpp-modules")
464 || atom->string() == QLatin1String(
"qml-modules")
465 || atom->string() == QLatin1String(
"related")) {
466 generateList(relative, atom->string());
467 hasGeneratedSomething =
true;
469 }
else if (
const auto *cn =
m_qdb->getCollectionNode(atom->string(),
Node::Group); cn) {
470 generateAnnotatedList(cn, cn->members(), atom->string(), ItemizedList, sortOrder);
471 hasGeneratedSomething =
true;
476 if (!hasGeneratedSomething && !m_inPara) {
477 m_writer->writeEmptyElement(dbNamespace,
"para");
509 m_writer->writeStartElement(dbNamespace,
"figure");
516 generateAtom(current, relative,
nullptr);
521 generateAtom(current, relative,
nullptr);
527 generateAtom(current, relative,
nullptr);
531 m_closeFigureWrapper =
true;
542 m_writer->writeStartElement(dbNamespace,
"figure");
549 generateAtom(current, relative,
nullptr);
554 generateAtom(current, relative,
nullptr);
560 generateAtom(current, relative,
nullptr);
564 m_closeFigureWrapper =
true;
587 m_writer->writeStartElement(dbNamespace, tag);
590 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
591 if (!maybe_resolved_file) {
593 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
595 m_writer->writeStartElement(dbNamespace,
"textobject");
597 m_writer->writeStartElement(dbNamespace,
"para");
598 m_writer->writeTextElement(dbNamespace,
"emphasis",
599 "[Missing image " + atom->string() +
"]");
600 m_writer->writeEndElement();
602 m_writer->writeEndElement();
606 QString file_name{QFileInfo{file.get_path()}.fileName()};
609 Config::copyFile(relative
->doc().location(), file.get_path(), file_name, outputDir() + QLatin1String(
"/images"));
613 m_writer->writeTextElement(dbNamespace,
"alt", atom->next()->string());
617 m_writer->writeStartElement(dbNamespace,
"imageobject");
619 m_writer->writeEmptyElement(dbNamespace,
"imagedata");
621 m_writer->writeAttribute(
"fileref",
"images/" + file_name);
623 m_writer->writeEndElement();
627 setImageFileName(relative,
"images/" + file_name);
630 m_writer->writeEndElement();
634 if (m_closeFigureWrapper) {
635 m_writer->writeEndElement();
637 m_closeFigureWrapper =
false;
645 QString admonType = atom->typeString().toLower();
648 m_writer->writeStartElement(dbNamespace, admonType);
650 m_writer->writeStartElement(dbNamespace,
"para");
653 case Atom::ImportantRight:
654 case Atom::NoteRight:
655 case Atom::WarningRight:
656 m_writer->writeEndElement();
659 m_writer->writeEndElement();
667 const Node *node =
nullptr;
668 QString link = getLink(atom, relative, &node);
669 beginLink(link, node, relative);
673 const Node *node = CodeMarker::nodeForString(atom->string());
674 beginLink(linkForNode(node, relative), node, relative);
684 m_writer->writeEndElement();
690 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
693 m_writer->writeStartElement(dbNamespace,
"variablelist");
696 m_writer->writeStartElement(dbNamespace,
"informaltable");
698 m_writer->writeStartElement(dbNamespace,
"thead");
700 m_writer->writeStartElement(dbNamespace,
"tr");
702 m_writer->writeTextElement(dbNamespace,
"th",
"Constant");
708 m_writer->writeTextElement(dbNamespace,
"th",
"Value");
713 m_writer->writeTextElement(dbNamespace,
"th",
"Description");
717 m_writer->writeEndElement();
719 m_writer->writeEndElement();
722 m_writer->writeStartElement(dbNamespace,
"orderedlist");
724 if (atom->next() !=
nullptr && atom->next()->string().toInt() > 1)
725 m_writer->writeAttribute(
"startingnumber", atom->next()->string());
728 m_writer->writeAttribute(
"numeration",
"upperalpha");
730 m_writer->writeAttribute(
"numeration",
"loweralpha");
732 m_writer->writeAttribute(
"numeration",
"upperroman");
734 m_writer->writeAttribute(
"numeration",
"lowerroman");
736 m_writer->writeAttribute(
"numeration",
"arabic");
746 m_writer->writeStartElement(dbNamespace,
"varlistentry");
748 m_writer->writeStartElement(dbNamespace,
"item");
750 std::pair<QString,
int> pair = getAtomListValue(atom);
751 skipAhead = pair.second;
753 m_writer->writeStartElement(dbNamespace,
"tr");
755 m_writer->writeStartElement(dbNamespace,
"td");
757 m_writer->writeStartElement(dbNamespace,
"para");
759 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
760 generateEnumValue(pair.first, relative);
761 m_writer->writeEndElement();
763 m_writer->writeEndElement();
767 const auto enume =
static_cast<
const EnumNode *>(relative);
768 QString itemValue = enume->itemValue(atom
->next()->string());
770 m_writer->writeStartElement(dbNamespace,
"td");
771 if (itemValue.isEmpty())
772 m_writer->writeCharacters(
"?");
774 m_writer->writeStartElement(dbNamespace,
"code");
776 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
777 m_writer->writeCharacters(itemValue);
778 m_writer->writeEndElement();
780 m_writer->writeEndElement();
788 m_writer->writeEndElement();
794 m_writer->writeEndElement();
801 m_inListItemLineOpen =
false;
803 m_writer->writeStartElement(dbNamespace,
"listitem");
805 m_writer->writeStartElement(dbNamespace,
"para");
810 m_writer->writeEmptyElement(dbNamespace,
"td");
812 m_inListItemLineOpen =
false;
814 m_writer->writeStartElement(dbNamespace,
"td");
816 m_inListItemLineOpen =
true;
820 m_writer->writeStartElement(dbNamespace,
"listitem");
829 m_writer->writeEndElement();
832 m_writer->writeEndElement();
834 m_writer->writeEndElement();
837 if (m_inListItemLineOpen) {
838 m_writer->writeEndElement();
840 m_inListItemLineOpen =
false;
842 m_writer->writeEndElement();
845 m_writer->writeEndElement();
850 case Atom::ListRight:
856 m_writer->writeEndElement();
863 m_writer->writeStartElement(dbNamespace,
"para");
869 m_writer->writeEndElement();
874 case Atom::QuotationLeft:
875 m_writer->writeStartElement(dbNamespace,
"blockquote");
876 m_inBlockquote =
true;
878 case Atom::QuotationRight:
879 m_writer->writeEndElement();
881 m_inBlockquote =
false;
884 m_writer->device()->write(atom->string().toUtf8());
890 currentSectionLevel = atom->string().toInt() +
hOffset(relative
);
892 if (currentSectionLevel > 1) {
895 while (!sectionLevels.empty() && sectionLevels.top() >= currentSectionLevel) {
897 m_writer->writeEndElement();
901 sectionLevels.push(currentSectionLevel);
903 m_writer->writeStartElement(dbNamespace,
"section");
904 writeXmlId(Tree::refForAtom(atom));
917 generateAtom(atom->next(), relative,
nullptr);
918 generateAtom(atom->next()->next(), relative,
nullptr);
919 generateAtom(atom->next()->next()->next(), relative,
nullptr);
921 m_closeSectionAfterGeneratedList =
true;
928 m_writer->writeTextElement(dbNamespace,
"title",
"");
937 if (currentSectionLevel > 1) {
938 m_writer->writeStartElement(dbNamespace,
"title");
944 if (currentSectionLevel > 1) {
945 m_writer->writeEndElement();
950 case Atom::SidebarLeft:
951 m_writer->writeStartElement(dbNamespace,
"sidebar");
953 case Atom::SidebarRight:
954 m_writer->writeEndElement();
961 m_writer->writeCharacters(atom->string());
964 std::pair<QString, QString> pair = getTableWidthAttr(atom);
965 QString attr = pair.second;
966 QString width = pair.first;
969 m_writer->writeEndElement();
974 m_tableHeaderAlreadyOutput =
false;
976 m_writer->writeStartElement(dbNamespace,
"informaltable");
977 m_writer->writeAttribute(
"style", attr);
978 if (!width.isEmpty())
979 m_writer->writeAttribute(
"width", width);
982 case Atom::TableRight:
983 m_tableWidthAttr = {
"",
""};
984 m_writer->writeEndElement();
993 if (m_tableHeaderAlreadyOutput) {
996 m_writer->writeEndElement();
999 const QString &attr = m_tableWidthAttr.second;
1000 const QString &width = m_tableWidthAttr.first;
1002 m_writer->writeStartElement(dbNamespace,
"informaltable");
1003 m_writer->writeAttribute(
"style", attr);
1004 if (!width.isEmpty())
1005 m_writer->writeAttribute(
"width", width);
1008 m_tableHeaderAlreadyOutput =
true;
1014 id = Utilities::asAsciiPrintable(next->string());
1019 m_writer->writeStartElement(dbNamespace,
"thead");
1021 m_writer->writeStartElement(dbNamespace,
"tr");
1027 m_closeTableCell =
true;
1028 m_writer->writeStartElement(dbNamespace,
"td");
1034 if (m_closeTableCell) {
1035 m_closeTableCell =
false;
1036 m_writer->writeEndElement();
1040 m_writer->writeEndElement();
1044 m_writer->writeStartElement(dbNamespace,
"tr");
1047 m_writer->writeEndElement();
1059 bool hasTarget {
false};
1061 id = Utilities::asAsciiPrintable(atom
->next()->string());
1066 m_writer->writeStartElement(dbNamespace,
"tr");
1069 if (atom->string().isEmpty()) {
1070 m_writer->writeAttribute(
"valign",
"top");
1075 QStringList args = atom->string().split(
"\"", Qt::SkipEmptyParts);
1078 const int nArgs = args.size();
1083 QStringLiteral(
"Error when parsing attributes for the table: got \"%1\"")
1084 .arg(atom->string()));
1086 for (
int i = 0; i + 1 < nArgs; i += 2) {
1089 const QString &attr = args.at(i).chopped(1);
1092 writeXmlId(args.at(i + 1));
1094 m_writer->writeAttribute(attr, args.at(i + 1));
1110 m_closeTableRow =
true;
1111 m_writer->writeEndElement();
1117 if (m_closeTableRow) {
1118 m_closeTableRow =
false;
1119 m_writer->writeEndElement();
1123 m_writer->writeEndElement();
1126 case Atom::TableItemLeft:
1127 m_writer->writeStartElement(dbNamespace, m_inTableHeader ?
"th" :
"td");
1129 for (
int i = 0; i < atom->count(); ++i) {
1130 const QString &p = atom->string(i);
1131 if (p.contains(
'=')) {
1132 QStringList lp = p.split(QLatin1Char(
'='));
1133 m_writer->writeAttribute(lp.at(0), lp.at(1));
1135 QStringList spans = p.split(QLatin1Char(
','));
1136 if (spans.size() == 2) {
1137 if (spans.at(0) !=
"1")
1138 m_writer->writeAttribute(
"colspan", spans.at(0).trimmed());
1139 if (spans.at(1) !=
"1")
1140 m_writer->writeAttribute(
"rowspan", spans.at(1).trimmed());
1147 case Atom::TableItemRight:
1148 m_writer->writeEndElement();
1158 QString nextId = Utilities::asAsciiPrintable(
1160 QString ownId = Utilities::asAsciiPrintable(atom->string());
1161 if (nextId == ownId)
1165 writeAnchor(Utilities::asAsciiPrintable(atom->string()));
1167 case Atom::UnhandledFormat:
1168 m_writer->writeStartElement(dbNamespace,
"emphasis");
1169 m_writer->writeAttribute(
"role",
"bold");
1170 m_writer->writeCharacters(
"<Missing DocBook>");
1171 m_writer->writeEndElement();
1173 case Atom::UnknownCommand:
1174 m_writer->writeStartElement(dbNamespace,
"emphasis");
1175 m_writer->writeAttribute(
"role",
"bold");
1177 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1178 m_writer->writeCharacters(
"<Unknown command>");
1179 m_writer->writeStartElement(dbNamespace,
"code");
1180 m_writer->writeCharacters(atom->string());
1181 m_writer->writeEndElement();
1182 m_writer->writeEndElement();
1202 if (classMap.isEmpty())
1205 std::function<
void(
ClassNode *)> generateClassAndChildren
1206 = [
this, &relative, &generateClassAndChildren](ClassNode * classe) {
1207 m_writer->writeStartElement(dbNamespace,
"listitem");
1211 m_writer->writeStartElement(dbNamespace,
"para");
1212 generateFullName(classe, relative);
1213 m_writer->writeEndElement();
1217 bool hasChild =
false;
1218 for (
const RelatedClass &relatedClass : classe->derivedClasses()) {
1219 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1226 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1229 for (
const RelatedClass &relatedClass: classe->derivedClasses()) {
1230 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1231 generateClassAndChildren(relatedClass.m_node);
1235 m_writer->writeEndElement();
1240 m_writer->writeEndElement();
1244 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1247 for (
const auto &it : classMap) {
1248 auto *classe =
static_cast<ClassNode *>(it);
1249 if (classe->baseClasses().isEmpty())
1250 generateClassAndChildren(classe);
1253 m_writer->writeEndElement();
1264 if (match.hasMatch()) {
1266 qsizetype leftParenLoc = match.capturedStart(1);
1267 m_writer->writeCharacters(atom->string().left(leftParenLoc));
1269 m_writer->writeCharacters(atom->string().mid(leftParenLoc));
1273 m_writer->writeCharacters(atom->string());
1277
1278
1279
1283 m_writer->writeStartElement(dbNamespace,
"link");
1284 m_writer->writeAttribute(xlinkNamespace,
"href", link);
1285 if (node && !(relative && node->status() == relative->status())
1286 && node->isDeprecated())
1287 m_writer->writeAttribute(
"role",
"deprecated");
1296 m_writer->writeEndElement();
1302 Qt::SortOrder sortOrder)
1307 if (selector == QLatin1String(
"overviews"))
1309 else if (selector == QLatin1String(
"cpp-modules"))
1311 else if (selector == QLatin1String(
"qml-modules"))
1317 const QList<CollectionNode *> collectionList = cnm.values();
1318 nodeList.reserve(collectionList.size());
1319 for (
auto *collectionNode : collectionList)
1320 nodeList.append(collectionNode);
1321 generateAnnotatedList(relative, nodeList, selector, Auto, sortOrder);
1324
1325
1326
1327 Node *n =
const_cast<
Node *>(relative);
1330 generateAnnotatedList(cn, cn->members(), selector, Auto, sortOrder);
1335
1336
1337
1339 const QString &selector, GeneratedListType type,
1340 Qt::SortOrder sortOrder)
1342 if (nodeList.isEmpty())
1346 if (
std::all_of(nodeList.cbegin(), nodeList.cend(), [](
const Node *n) {
1353 bool noItemsHaveTitle =
1354 type == ItemizedList ||
std::all_of(nodeList.begin(), nodeList.end(),
1355 [](
const Node* node) {
1356 return node->doc().briefText().toString().isEmpty();
1360 if (type == AutoSection && m_hasSection)
1361 startSection(
"",
"Contents");
1364 if (!nodeList.isEmpty()) {
1365 m_writer->writeStartElement(dbNamespace, noItemsHaveTitle ?
"itemizedlist" :
"variablelist");
1366 m_writer->writeAttribute(
"role", selector);
1370 if (sortOrder == Qt::DescendingOrder)
1374 for (
const auto &node : std::as_const(members)) {
1375 if (node->isInternal() || node->isDeprecated())
1378 if (noItemsHaveTitle) {
1379 m_writer->writeStartElement(dbNamespace,
"listitem");
1381 m_writer->writeStartElement(dbNamespace,
"para");
1383 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1385 m_writer->writeStartElement(dbNamespace,
"term");
1387 generateFullName(node, relative);
1388 if (noItemsHaveTitle) {
1389 m_writer->writeEndElement();
1391 m_writer->writeEndElement();
1393 m_writer->writeEndElement();
1395 m_writer->writeStartElement(dbNamespace,
"listitem");
1397 m_writer->writeStartElement(dbNamespace,
"para");
1398 m_writer->writeCharacters(node->doc().briefText().toString());
1399 m_writer->writeEndElement();
1401 m_writer->writeEndElement();
1403 m_writer->writeEndElement();
1408 m_writer->writeEndElement();
1412 if (type == AutoSection && m_hasSection)
1417
1418
1419
1421 const QString &selector)
1424 for (
const QString &name : nmm.uniqueKeys()) {
1425 if (!name.isEmpty())
1426 startSection(name.toLower(), name);
1427 generateAnnotatedList(relative, nmm.values(name), selector);
1428 if (!name.isEmpty())
1434
1435
1436
1437
1438
1439
1440
1441
1442
1444 bool includeAlphabet,
const QString &commonPrefix,
1445 const QString &selector)
1455 const int NumParagraphs = 37;
1456 qsizetype commonPrefixLen = commonPrefix.size();
1459
1460
1461
1462
1463
1465 QString paragraphName[NumParagraphs + 1];
1466 QSet<
char> usedParagraphNames;
1468 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
1469 QStringList pieces = c.key().split(
"::");
1470 int idx = commonPrefixLen;
1471 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
1473 QString last = pieces.last().toLower();
1474 QString key = last.mid(idx);
1476 int paragraphNr = NumParagraphs - 1;
1478 if (key[0].digitValue() != -1) {
1479 paragraphNr = key[0].digitValue();
1480 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
1481 paragraphNr = 10 + key[0].unicode() -
'a';
1484 paragraphName[paragraphNr] = key[0].toUpper();
1485 usedParagraphNames.insert(key[0].toLower().cell());
1486 paragraph[paragraphNr].insert(last, c.value());
1490
1491
1492
1493
1494
1495
1496
1497 int paragraphOffset[NumParagraphs + 1];
1498 paragraphOffset[0] = 0;
1499 for (
int i = 0; i < NumParagraphs; i++)
1500 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
1503 if (includeAlphabet && !usedParagraphNames.isEmpty()) {
1504 m_writer->writeStartElement(dbNamespace,
"simplelist");
1507 for (
int i = 0; i < 26; i++) {
1509 if (usedParagraphNames.contains(
char(
'a' + i))) {
1510 m_writer->writeStartElement(dbNamespace,
"member");
1511 generateSimpleLink(ch, ch.toUpper());
1512 m_writer->writeEndElement();
1517 m_writer->writeEndElement();
1523 int curParOffset = 0;
1524 QString previousName;
1525 bool multipleOccurrences =
false;
1527 m_writer->writeStartElement(dbNamespace,
"variablelist");
1528 m_writer->writeAttribute(
"role", selector);
1531 for (
int i = 0; i < nmm.size(); i++) {
1532 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
1539 if (curParOffset == 0) {
1541 m_writer->writeEndElement();
1543 m_writer->writeEndElement();
1545 m_writer->writeEndElement();
1549 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1550 if (includeAlphabet)
1551 writeXmlId(paragraphName[curParNr][0].toLower());
1554 m_writer->writeStartElement(dbNamespace,
"term");
1555 m_writer->writeStartElement(dbNamespace,
"emphasis");
1556 m_writer->writeAttribute(
"role",
"bold");
1557 m_writer->writeCharacters(paragraphName[curParNr]);
1558 m_writer->writeEndElement();
1559 m_writer->writeEndElement();
1562 m_writer->writeStartElement(dbNamespace,
"listitem");
1564 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1569 m_writer->writeStartElement(dbNamespace,
"listitem");
1571 m_writer->writeStartElement(dbNamespace,
"para");
1573 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
1574 NodeMultiMap::Iterator it;
1575 NodeMultiMap::Iterator next;
1576 it = paragraph[curParNr].begin();
1577 for (
int j = 0; j < curParOffset; j++)
1582 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
1583 const auto &name{pieces.last()};
1586 if (name != previousName)
1587 multipleOccurrences =
false;
1588 if ((next != paragraph[curParNr].end()) && (name == next.value()->name())) {
1589 multipleOccurrences =
true;
1590 previousName = name;
1592 if (multipleOccurrences && pieces.size() == 1)
1593 pieces.last().append(
": "_L1.arg(it.value()->tree()->camelCaseModuleName()));
1596 m_writer->writeStartElement(dbNamespace,
"link");
1597 m_writer->writeAttribute(xlinkNamespace,
"href", linkForNode(*it, relative));
1598 if (
const QString type = targetType(it.value()); !type.isEmpty())
1599 m_writer->writeAttribute(
"role", type);
1600 m_writer->writeCharacters(pieces.last());
1601 m_writer->writeEndElement();
1604 if (pieces.size() > 1) {
1605 m_writer->writeCharacters(
" (");
1606 generateFullName(it.value()->parent(), relative);
1607 m_writer->writeCharacters(
")");
1611 m_writer->writeEndElement();
1613 m_writer->writeEndElement();
1618 m_writer->writeEndElement();
1620 m_writer->writeEndElement();
1622 m_writer->writeEndElement();
1625 m_writer->writeEndElement();
1634 m_writer->writeStartElement(dbNamespace,
"simplelist");
1635 m_writer->writeAttribute(
"role",
"functionIndex");
1637 for (
int i = 0; i < 26; i++) {
1639 m_writer->writeStartElement(dbNamespace,
"member");
1640 m_writer->writeAttribute(xlinkNamespace,
"href", QString(
"#") + ch);
1641 m_writer->writeCharacters(ch.toUpper());
1642 m_writer->writeEndElement();
1645 m_writer->writeEndElement();
1652 char nextLetter =
'a';
1655 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1659 QMap<QString, NodeMap>::ConstIterator f = funcIndex.constBegin();
1660 while (f != funcIndex.constEnd()) {
1661 m_writer->writeStartElement(dbNamespace,
"listitem");
1663 m_writer->writeStartElement(dbNamespace,
"para");
1664 m_writer->writeCharacters(f.key() +
": ");
1666 currentLetter = f.key()[0].unicode();
1667 while (islower(currentLetter) && currentLetter >= nextLetter) {
1668 writeAnchor(QString(nextLetter));
1672 NodeMap::ConstIterator s = (*f).constBegin();
1673 while (s != (*f).constEnd()) {
1674 m_writer->writeCharacters(
" ");
1675 generateFullName((*s)->parent(), relative);
1679 m_writer->writeEndElement();
1681 m_writer->writeEndElement();
1685 m_writer->writeEndElement();
1693 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
1694 Text text = it.key();
1696 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1699 m_writer->writeStartElement(dbNamespace,
"listitem");
1701 m_writer->writeStartElement(dbNamespace,
"para");
1702 generateFullName(it.value(), relative);
1703 m_writer->writeEndElement();
1705 m_writer->writeEndElement();
1708 }
while (it != legaleseTexts.constEnd() && it.key() == text);
1709 m_writer->writeEndElement();
1724 m_writer->writeStartElement(dbNamespace,
"para");
1726 m_writer->writeEndElement();
1734 if (!node->since().isEmpty()) {
1735 m_writer->writeStartElement(dbNamespace,
"para");
1736 m_writer->writeCharacters(
"This " + typeString(node) +
" was introduced in ");
1737 m_writer->writeCharacters(formatSince(node) +
".");
1738 m_writer->writeEndElement();
1748
1749
1750
1757 m_writer->writeStartElement(dbNamespace,
"info");
1759 m_writer->writeStartElement(dbNamespace,
"title");
1760 if (node->genus() & Node::API && m_useITS)
1761 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1762 m_writer->writeCharacters(title);
1763 m_writer->writeEndElement();
1766 if (!subTitle.isEmpty()) {
1767 m_writer->writeStartElement(dbNamespace,
"subtitle");
1768 if (node->genus() & Node::API && m_useITS)
1769 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1770 m_writer->writeCharacters(subTitle);
1771 m_writer->writeEndElement();
1775 if (!m_productName.isEmpty() || !m_project.isEmpty()) {
1776 m_writer->writeTextElement(dbNamespace,
"productname", m_productName.isEmpty() ?
1777 m_project : m_productName);
1781 if (!m_buildVersion.isEmpty()) {
1782 m_writer->writeTextElement(dbNamespace,
"edition", m_buildVersion);
1786 if (!m_projectDescription.isEmpty()) {
1787 m_writer->writeTextElement(dbNamespace,
"titleabbrev", m_projectDescription);
1795 if (node && !node->links().empty()) {
1796 std::pair<QString, QString> linkPair;
1797 std::pair<QString, QString> anchorPair;
1798 const Node *linkNode;
1800 if (node->links().contains(Node::PreviousLink)) {
1801 linkPair = node->links()[Node::PreviousLink];
1802 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1803 if (!linkNode || linkNode == node)
1804 anchorPair = linkPair;
1806 anchorPair = anchorForNode(linkNode);
1808 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1809 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1810 m_writer->writeEmptyElement(dbNamespace,
"link");
1811 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1812 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1813 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"prev");
1814 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1815 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1817 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1818 m_writer->writeEndElement();
1821 if (node->links().contains(Node::NextLink)) {
1822 linkPair = node->links()[Node::NextLink];
1823 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1824 if (!linkNode || linkNode == node)
1825 anchorPair = linkPair;
1827 anchorPair = anchorForNode(linkNode);
1829 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1830 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1831 m_writer->writeEmptyElement(dbNamespace,
"link");
1832 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1833 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1834 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"next");
1835 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1836 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1838 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1839 m_writer->writeEndElement();
1842 if (node->links().contains(Node::StartLink)) {
1843 linkPair = node->links()[Node::StartLink];
1844 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1845 if (!linkNode || linkNode == node)
1846 anchorPair = linkPair;
1848 anchorPair = anchorForNode(linkNode);
1850 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1851 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1852 m_writer->writeEmptyElement(dbNamespace,
"link");
1853 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1854 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1855 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"start");
1856 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1857 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1859 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1860 m_writer->writeEndElement();
1872 m_writer->writeStartElement(dbNamespace,
"abstract");
1875 bool generatedSomething =
false;
1882 brief <<
"The " << ns->name()
1883 <<
" namespace includes the following elements from module "
1884 << ns->tree()->camelCaseModuleName() <<
". The full namespace is "
1885 <<
"documented in module " << NS->tree()->camelCaseModuleName()
1886 << Atom(Atom::LinkNode, fullDocumentLocation(NS))
1888 << Atom(Atom::String,
" here.")
1898 m_writer->writeStartElement(dbNamespace,
"para");
1900 m_writer->writeEndElement();
1903 generatedSomething =
true;
1914 if (!generatedSomething)
1915 m_writer->writeTextElement(dbNamespace,
"para", m_projectDescription +
".");
1917 m_writer->writeEndElement();
1922 m_writer->writeEndElement();
1928 while (!sectionLevels.isEmpty()) {
1929 sectionLevels.pop();
1936 if (m_closeSectionAfterGeneratedList) {
1937 m_closeSectionAfterGeneratedList =
false;
1940 if (m_closeSectionAfterRawTitle) {
1941 m_closeSectionAfterRawTitle =
false;
1946 m_writer->writeEndElement();
1949void DocBookGenerator::generateSimpleLink(
const QString &href,
const QString &text)
1951 m_writer->writeStartElement(dbNamespace,
"link");
1952 m_writer->writeAttribute(xlinkNamespace,
"href", href);
1953 m_writer->writeCharacters(text);
1954 m_writer->writeEndElement();
1966 startSection(
"obsolete",
"Obsolete Members for " + aggregate->plainFullName());
1968 m_writer->writeStartElement(dbNamespace,
"para");
1969 m_writer->writeStartElement(dbNamespace,
"emphasis");
1970 m_writer->writeAttribute(
"role",
"bold");
1971 m_writer->writeCharacters(
"The following members of class ");
1972 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
1973 m_writer->writeCharacters(
" are deprecated.");
1974 m_writer->writeEndElement();
1975 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
1976 m_writer->writeEndElement();
1979 for (
const Section *section : details_spv) {
1980 const QString &title =
"Obsolete " + section->title();
1981 startSection(title.toLower(), title);
1983 const NodeVector &members = section->obsoleteMembers();
1984 NodeVector::ConstIterator m = members.constBegin();
1985 while (m != members.constEnd()) {
1986 if ((*m)->access() != Access::Private)
1987 generateDetailedMember(*m, aggregate);
1998
1999
2000
2001
2002
2003
2004
2014 startSection(
"obsolete",
"Obsolete Members for " + aggregate->name());
2016 m_writer->writeStartElement(dbNamespace,
"para");
2017 m_writer->writeStartElement(dbNamespace,
"emphasis");
2018 m_writer->writeAttribute(
"role",
"bold");
2019 m_writer->writeCharacters(
"The following members of QML type ");
2020 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2021 m_writer->writeCharacters(
" are deprecated.");
2022 m_writer->writeEndElement();
2023 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2024 m_writer->writeEndElement();
2027 for (
const auto *section : details_spv) {
2028 const QString &title =
"Obsolete " + section->title();
2029 startSection(title.toLower(), title);
2031 const NodeVector &members = section->obsoleteMembers();
2032 NodeVector::ConstIterator m = members.constBegin();
2033 while (m != members.constEnd()) {
2034 if ((*m)->access() != Access::Private)
2035 generateDetailedQmlMember(*m, aggregate);
2049 return QStringLiteral(
"classsynopsis");
2051 return QStringLiteral(
"packagesynopsis");
2057 return QStringLiteral(
"enumsynopsis");
2059 return QStringLiteral(
"typedefsynopsis");
2062 const auto fn =
static_cast<
const FunctionNode *>(node);
2064 return QStringLiteral(
"constructorsynopsis");
2066 return QStringLiteral(
"destructorsynopsis");
2067 return QStringLiteral(
"methodsynopsis");
2070 return QStringLiteral(
"fieldsynopsis");
2072 node
->doc().location().warning(QString(
"Unknown node tag %1").arg(node->nodeTypeString()));
2073 return QStringLiteral(
"synopsis");
2078 m_writer->writeStartElement(dbNamespace,
"varlistentry");
2080 m_writer->writeTextElement(dbNamespace,
"term", description);
2082 m_writer->writeStartElement(dbNamespace,
"listitem");
2084 m_writer->writeStartElement(dbNamespace,
"para");
2090 m_writer->writeEndElement();
2093 m_writer->writeEndElement();
2095 m_writer->writeEndElement();
2099void DocBookGenerator::generateRequisite(
const QString &description,
const QString &value)
2101 generateStartRequisite(description);
2102 m_writer->writeCharacters(value);
2103 generateEndRequisite();
2107
2108
2109
2110void DocBookGenerator::generateCMakeRequisite(
const QString &findPackage,
const QString &linkLibraries)
2112 const QString description(
"CMake");
2113 generateStartRequisite(description);
2114 m_writer->writeCharacters(findPackage);
2115 m_writer->writeEndElement();
2118 m_writer->writeStartElement(dbNamespace,
"para");
2119 m_writer->writeCharacters(linkLibraries);
2120 generateEndRequisite();
2126 QMap<QString, ClassNode *> classMap;
2127 QList<RelatedClass>::ConstIterator r = rc.constBegin();
2128 while (r != rc.constEnd()) {
2131 && !rcn
->doc().isEmpty()) {
2132 classMap[rcn->plainFullName(cn).toLower()] = rcn;
2137 QStringList classNames = classMap.keys();
2141 for (
const QString &className : classNames) {
2142 generateFullName(classMap.value(className), cn);
2143 m_writer->writeCharacters(Utilities::comma(index++, classNames.size()));
2151 QMap<QString, Node *> classMap;
2152 QStringList typeNames(knownTypes);
2153 for (
const auto sub : subs)
2154 typeNames << sub->name();
2156 for (
auto sub : subs) {
2157 QString key{sub->plainFullName(base).toLower()};
2159 if (typeNames.count(sub->name()) > 1)
2160 key.append(
": (%1)"_L1.arg(sub->logicalModuleName()));
2161 classMap[key] = sub;
2164 QStringList names = classMap.keys();
2168 for (
const QString &name : names) {
2169 generateFullName(classMap.value(name), base);
2170 if (name.contains(
':'))
2171 m_writer->writeCharacters(name.section(
':', 1));
2172 m_writer->writeCharacters(Utilities::comma(index++, names.size()));
2177
2178
2187 QXmlStreamWriter* oldWriter = m_writer;
2189 m_writer =
new QXmlStreamWriter(&output);
2192 if (aggregate->includeFile()) generateRequisite(
"Header", *aggregate->includeFile());
2195 if (!aggregate->since().isEmpty())
2196 generateRequisite(
"Since", formatSince(aggregate));
2203 if (
const auto result = cmakeRequisite(cn)) {
2204 generateCMakeRequisite(result->first, result->second);
2207 if (cn && !cn->qtVariable().isEmpty())
2208 generateRequisite(
"qmake",
"QT += " + cn->qtVariable());
2215 generateStartRequisite(
"In QML");
2218 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2221 for (
const auto &item : std::as_const(nativeTypes)) {
2222 generateFullName(item, classe);
2223 m_writer->writeCharacters(
2224 Utilities::comma(idx++, nativeTypes.size()));
2226 generateEndRequisite();
2230 QList<RelatedClass>::ConstIterator r;
2231 if (!classe->baseClasses().isEmpty()) {
2232 generateStartRequisite(
"Inherits");
2234 r = classe->baseClasses().constBegin();
2236 while (r != classe->baseClasses().constEnd()) {
2238 generateFullName((*r).m_node, classe);
2240 if ((*r).m_access == Access::Protected)
2241 m_writer->writeCharacters(
" (protected)");
2242 else if ((*r).m_access == Access::Private)
2243 m_writer->writeCharacters(
" (private)");
2244 m_writer->writeCharacters(
2245 Utilities::comma(index++, classe->baseClasses().size()));
2250 generateEndRequisite();
2254 if (!classe->derivedClasses().isEmpty()) {
2255 generateStartRequisite(
"Inherited By");
2256 generateSortedNames(classe, classe->derivedClasses());
2257 generateEndRequisite();
2262 if (!aggregate->groupNames().empty()) {
2263 generateStartRequisite(
"Group");
2265 generateEndRequisite();
2269 if (
auto status = formatStatus(aggregate, m_qdb); status)
2270 generateRequisite(
"Status", status.value());
2274 m_writer = oldWriter;
2276 if (!output.isEmpty()) {
2279 static const QRegularExpression xmlTag(R"(<(/?)n\d+:)");
2280 static const QRegularExpression xmlnsDocBookDefinition(R"( xmlns:n\d+=")" + QString{dbNamespace} +
"\"");
2281 static const QRegularExpression xmlnsXLinkDefinition(R"( xmlns:n\d+=")" + QString{xlinkNamespace} +
"\"");
2282 static const QRegularExpression xmlAttr(R"( n\d+:)");
2284 const QString cleanOutput = output.replace(xmlTag, R"(<\1db:)")
2285 .replace(xmlnsDocBookDefinition,
"")
2286 .replace(xmlnsXLinkDefinition,
"")
2287 .replace(xmlAttr,
" xlink:");
2289 m_writer->writeStartElement(dbNamespace,
"variablelist");
2291 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2294 m_writer->device()->write(cleanOutput.toUtf8());
2296 m_writer->writeEndElement();
2302
2303
2311 const QString importText =
"Import Statement";
2312 const QString sinceText =
"Since";
2313 const QString inheritedByText =
"Inherited By";
2314 const QString inheritsText =
"Inherits";
2315 const QString nativeTypeText =
"In C++";
2316 const QString groupText =
"Group";
2317 const QString statusText =
"Status";
2330 const bool generate_import_statement = !qcn->logicalModuleName().isEmpty() && (!collection || !collection
->isInternal() ||
m_showInternal);
2332 const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base;
2334 if (!generates_something)
2337 QStringList knownTypeNames{qcn->name()};
2339 knownTypeNames << base->name();
2342 m_writer->writeStartElement(dbNamespace,
"variablelist");
2344 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2347 if (generate_import_statement) {
2348 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2349 generateRequisite(importText, parts.join(
' ').trimmed());
2353 if (!qcn->since().isEmpty())
2354 generateRequisite(sinceText, formatSince(qcn));
2359 generateStartRequisite(nativeTypeText);
2360 generateSimpleLink(fullDocumentLocation(cn), cn->name());
2361 generateEndRequisite();
2366 generateStartRequisite(inheritsText);
2367 generateSimpleLink(fullDocumentLocation(base), base->name());
2369 for (
const auto sub : std::as_const(subs)) {
2370 if (knownTypeNames.contains(sub->name())) {
2371 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
2375 generateEndRequisite();
2379 if (!subs.isEmpty()) {
2380 generateStartRequisite(inheritedByText);
2381 generateSortedQmlNames(qcn, knownTypeNames, subs);
2382 generateEndRequisite();
2386 if (!qcn->groupNames().empty()) {
2387 generateStartRequisite(groupText);
2389 generateEndRequisite();
2393 if (
auto status = formatStatus(qcn, m_qdb); status)
2394 generateRequisite(statusText, status.value());
2396 m_writer->writeEndElement();
2407 const QString &state =
static_cast<
const CollectionNode*>(node)->state();
2408 if (!state.isEmpty()) {
2409 m_writer->writeStartElement(dbNamespace,
"para");
2410 m_writer->writeCharacters(
"This " + typeString(node) +
" is in ");
2411 m_writer->writeStartElement(dbNamespace,
"emphasis");
2412 m_writer->writeCharacters(state);
2413 m_writer->writeEndElement();
2414 m_writer->writeCharacters(
" state.");
2415 m_writer->writeEndElement();
2420 if (
const auto version = node->deprecatedSince(); !version.isEmpty()) {
2421 m_writer->writeStartElement(dbNamespace,
"para");
2422 m_writer->writeCharacters(
"This " + typeString(node)
2423 +
" is scheduled for deprecation in version "
2425 m_writer->writeEndElement();
2430 case Node::Preliminary:
2431 m_writer->writeStartElement(dbNamespace,
"para");
2432 m_writer->writeStartElement(dbNamespace,
"emphasis");
2433 m_writer->writeAttribute(
"role",
"bold");
2434 m_writer->writeCharacters(
"This " + typeString(node)
2435 +
" is under development and is subject to change.");
2436 m_writer->writeEndElement();
2437 m_writer->writeEndElement();
2440 case Node::Deprecated:
2441 m_writer->writeStartElement(dbNamespace,
"para");
2443 m_writer->writeStartElement(dbNamespace,
"emphasis");
2444 m_writer->writeAttribute(
"role",
"bold");
2446 m_writer->writeCharacters(
"This " + typeString(node) +
" is deprecated");
2447 if (
const QString &version = node->deprecatedSince(); !version.isEmpty()) {
2448 m_writer->writeCharacters(
" since ");
2449 if (node->isQmlNode() && !node->logicalModuleName().isEmpty())
2450 m_writer->writeCharacters(node->logicalModuleName() +
" ");
2451 m_writer->writeCharacters(version);
2453 m_writer->writeCharacters(
". We strongly advise against using it in new code.");
2454 if (node->isAggregate())
2455 m_writer->writeEndElement();
2456 m_writer->writeEndElement();
2466
2467
2468
2472 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2475 NodeList::ConstIterator n = nodes.constBegin();
2476 while (n != nodes.constEnd()) {
2477 m_writer->writeStartElement(dbNamespace,
"listitem");
2479 m_writer->writeStartElement(dbNamespace,
"para");
2481 generateSimpleLink(currentGenerator()->fullDocumentLocation(*n),
2482 (*n)->signature(Node::SignaturePlain));
2484 m_writer->writeEndElement();
2486 m_writer->writeEndElement();
2491 m_writer->writeEndElement();
2496
2497
2498
2505 const auto aggregate =
static_cast<
const Aggregate *>(node);
2507 const QStringList &groups_names{aggregate->groupNames()};
2508 if (!groups_names.empty()) {
2509 m_writer->writeCharacters(aggregate->name() +
" is part of ");
2510 m_writer->writeStartElement(dbNamespace,
"simplelist");
2512 for (qsizetype index{0}; index < groups_names.size(); ++index) {
2516 m_writer->writeStartElement(dbNamespace,
"member");
2517 if (QString target{linkForNode(group,
nullptr)}; !target.isEmpty())
2518 generateSimpleLink(target, group->fullTitle());
2520 m_writer->writeCharacters(group->name());
2521 m_writer->writeEndElement();
2524 m_writer->writeEndElement();
2530
2531
2532
2538 const Node *reentrantNode;
2540 QString linkReentrant = getAutoLink(&reentrantAtom, node, &reentrantNode);
2541 const Node *threadSafeNode;
2543 QString linkThreadSafe = getAutoLink(&threadSafeAtom, node, &threadSafeNode);
2546 m_writer->writeStartElement(dbNamespace,
"warning");
2548 m_writer->writeStartElement(dbNamespace,
"para");
2549 m_writer->writeCharacters(
"This " + typeString(node) +
" is not ");
2550 generateSimpleLink(linkReentrant,
"reentrant");
2551 m_writer->writeCharacters(
".");
2552 m_writer->writeEndElement();
2554 m_writer->writeEndElement();
2558 m_writer->writeStartElement(dbNamespace,
"note");
2560 m_writer->writeStartElement(dbNamespace,
"para");
2563 m_writer->writeCharacters(
"All functions in this " + typeString(node) +
" are ");
2564 if (ts == Node::ThreadSafe)
2565 generateSimpleLink(linkThreadSafe,
"thread-safe");
2567 generateSimpleLink(linkReentrant,
"reentrant");
2573 if (!exceptions || (ts ==
Node::Reentrant && !threadsafe.isEmpty())) {
2574 m_writer->writeCharacters(
".");
2575 m_writer->writeEndElement();
2578 m_writer->writeCharacters(
" with the following exceptions:");
2579 m_writer->writeEndElement();
2581 m_writer->writeStartElement(dbNamespace,
"para");
2584 if (!nonreentrant.isEmpty()) {
2585 m_writer->writeCharacters(
"These functions are not ");
2586 generateSimpleLink(linkReentrant,
"reentrant");
2587 m_writer->writeCharacters(
":");
2588 m_writer->writeEndElement();
2590 generateSignatureList(nonreentrant);
2592 if (!threadsafe.isEmpty()) {
2593 m_writer->writeCharacters(
"These functions are also ");
2594 generateSimpleLink(linkThreadSafe,
"thread-safe");
2595 m_writer->writeCharacters(
":");
2596 m_writer->writeEndElement();
2598 generateSignatureList(threadsafe);
2601 if (!reentrant.isEmpty()) {
2602 m_writer->writeCharacters(
"These functions are only ");
2603 generateSimpleLink(linkReentrant,
"reentrant");
2604 m_writer->writeCharacters(
":");
2605 m_writer->writeEndElement();
2607 generateSignatureList(reentrant);
2609 if (!nonreentrant.isEmpty()) {
2610 m_writer->writeCharacters(
"These functions are not ");
2611 generateSimpleLink(linkReentrant,
"reentrant");
2612 m_writer->writeCharacters(
":");
2613 m_writer->writeEndElement();
2615 generateSignatureList(nonreentrant);
2620 m_writer->writeCharacters(
"This " + typeString(node) +
" is ");
2621 if (ts == Node::ThreadSafe)
2622 generateSimpleLink(linkThreadSafe,
"thread-safe");
2624 generateSimpleLink(linkReentrant,
"reentrant");
2625 m_writer->writeCharacters(
".");
2626 m_writer->writeEndElement();
2629 m_writer->writeEndElement();
2639
2640
2641
2649
2650
2651
2655 t =
"Destroys the instance of " + fn
->parent()->name() +
".";
2657 t +=
" The destructor is virtual.";
2659 t =
"Default constructs an instance of " + fn
->parent()->name() +
".";
2661 t =
"Copy constructor.";
2663 t =
"Move-copy constructor.";
2665 t =
"Copy-assignment constructor.";
2667 t =
"Move-assignment constructor.";
2671 m_writer->writeTextElement(dbNamespace,
"para", t);
2675 if (fn && !fn->overridesThis().isEmpty())
2676 generateReimplementsClause(fn);
2704 generateRequiredLinks(node);
2708
2709
2710
2711
2712
2719 const auto en =
static_cast<
const ExampleNode *>(node);
2722 if (exampleUrl.isEmpty()) {
2724 generateFileList(en,
false);
2725 generateFileList(en,
true);
2728 generateLinkToExample(en, exampleUrl);
2733
2734
2735
2736
2737
2741 QString exampleUrl(baseUrl);
2743#ifndef QT_BOOTSTRAPPED
2744 link = QUrl(exampleUrl).host();
2746 if (!link.isEmpty())
2747 link.prepend(
" @ ");
2748 link.prepend(
"Example project");
2750 const QLatin1Char separator(
'/');
2751 const QLatin1Char placeholder(
'\1');
2752 if (!exampleUrl.contains(placeholder)) {
2753 if (!exampleUrl.endsWith(separator))
2754 exampleUrl += separator;
2755 exampleUrl += placeholder;
2759 QStringList path = QStringList()
2761 path.removeAll(QString());
2765 startSection(
"Example project");
2767 m_writer->writeStartElement(dbNamespace,
"para");
2768 generateSimpleLink(exampleUrl.replace(placeholder, path.join(separator)), link);
2769 m_writer->writeEndElement();
2778
2779
2780
2781
2782
2783
2799 paths = en->images();
2802 paths = en->files();
2805 std::sort(paths.begin(), paths.end(), Generator::comparePaths);
2807 if (paths.isEmpty())
2810 startSection(
"",
"List of Files");
2812 m_writer->writeStartElement(dbNamespace,
"para");
2813 m_writer->writeCharacters(tag);
2814 m_writer->writeEndElement();
2817 startSection(
"List of Files");
2819 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2822 for (
const auto &path : std::as_const(paths)) {
2823 auto maybe_resolved_file{file_resolver.resolve(path)};
2824 if (!maybe_resolved_file) {
2826 QString details = std::transform_reduce(
2827 file_resolver.get_search_directories().cbegin(),
2828 file_resolver.get_search_directories().cend(),
2829 u"Searched directories:"_s,
2831 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
2834 en->location().warning(u"Cannot find file to quote from: %1"_s.arg(path), details);
2839 auto file{*maybe_resolved_file};
2840 if (images) addImageToCopy(en, file);
2841 else generateExampleFilePage(en, file);
2843 m_writer->writeStartElement(dbNamespace,
"listitem");
2845 m_writer->writeStartElement(dbNamespace,
"para");
2846 generateSimpleLink(file.get_query(), file.get_query());
2847 m_writer->writeEndElement();
2848 m_writer->writeEndElement();
2852 m_writer->writeEndElement();
2859
2860
2870 const auto en =
static_cast<
const ExampleNode *>(node);
2873 QXmlStreamWriter *currentWriter = m_writer;
2874 m_writer = startDocument(en, resolved_file.get_query());
2875 generateHeader(en->fullTitle(), en->subtitle(), en);
2880 QString code = quoter.quoteTo(en
->location(), QString(), QString());
2881 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
2887 m_writer = currentWriter;
2893 if (fn->overridesThis().isEmpty() || !fn
->parent()->isClassNode())
2898 if (
const FunctionNode *overrides = cn->findOverriddenFunction(fn);
2901 m_writer->writeStartElement(dbNamespace,
"para");
2902 m_writer->writeCharacters(
"Reimplements: ");
2905 generateFullName(overrides
->parent(), fullName, overrides);
2906 m_writer->writeCharacters(
".");
2907 m_writer->writeEndElement();
2913 if (
const PropertyNode *sameName = cn->findOverriddenProperty(fn); sameName && sameName
->hasDoc()) {
2914 m_writer->writeStartElement(dbNamespace,
"para");
2915 m_writer->writeCharacters(
"Reimplements an access function for property: ");
2916 QString fullName = sameName
->parent()->name() +
"::" + sameName->name();
2917 generateFullName(sameName
->parent(), fullName, sameName);
2918 m_writer->writeCharacters(
".");
2919 m_writer->writeEndElement();
2928 QList<Text> alsoList = node
->doc().alsoList();
2929 supplementAlsoList(node, alsoList);
2931 if (!alsoList.isEmpty()) {
2932 startSection(
"See Also");
2934 m_writer->writeStartElement(dbNamespace,
"para");
2935 m_writer->writeStartElement(dbNamespace,
"emphasis");
2936 m_writer->writeCharacters(
"See also ");
2937 m_writer->writeEndElement();
2940 m_writer->writeStartElement(dbNamespace,
"simplelist");
2941 m_writer->writeAttribute(
"type",
"vert");
2942 m_writer->writeAttribute(
"role",
"see-also");
2945 for (
const Text &text : alsoList) {
2946 m_writer->writeStartElement(dbNamespace,
"member");
2947 generateText(text, node);
2948 m_writer->writeEndElement();
2952 m_writer->writeEndElement();
2955 m_writer->writeEndElement();
2963
2964
2965
2966QXmlStreamWriter *
DocBookGenerator::startGenericDocument(
const Node *node,
const QString &fileName)
2969 QFile *outFile = openSubPageFile(
static_cast<
const PageNode*>(node), fileName);
2970 m_writer =
new QXmlStreamWriter(outFile);
2971 m_writer->setAutoFormatting(
false);
2973 m_writer->writeStartDocument();
2975 m_writer->writeNamespace(dbNamespace,
"db");
2976 m_writer->writeNamespace(xlinkNamespace,
"xlink");
2978 m_writer->writeNamespace(itsNamespace,
"its");
2979 m_writer->writeStartElement(dbNamespace,
"article");
2980 m_writer->writeAttribute(
"version",
"5.2");
2981 if (!m_naturalLanguage.isEmpty())
2982 m_writer->writeAttribute(
"xml:lang", m_naturalLanguage);
2986 sectionLevels.resize(0);
2995 m_hasSection =
false;
2998 QString fileName = Generator::fileName(node, fileExtension());
2999 return startGenericDocument(node, fileName);
3004 m_hasSection =
false;
3006 QString fileName = linkForExampleFile(file);
3007 return startGenericDocument(en, fileName);
3012 m_writer->writeEndElement();
3013 m_writer->writeEndDocument();
3015 m_writer->device()->close();
3016 delete m_writer->device();
3022
3023
3024
3029 const auto aggregate =
static_cast<
const Aggregate *>(node);
3032 QString subtitleText;
3033 const QString typeWord{aggregate->typeWord(
true)};
3035 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3037 auto templateDecl = node->templateDecl();
3039 subtitleText =
"%1 %2 %3"_L1.arg((*templateDecl).to_qstring(),
3040 aggregate->typeWord(
false),
3041 aggregate->plainFullName());
3042 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3044 title = aggregate->fullTitle();
3048 m_writer = startDocument(node);
3051 generateHeader(title, subtitleText, aggregate);
3060 if (!aggregate
->doc().isEmpty()) {
3061 startSection(
"details",
"Detailed Description");
3063 generateBody(aggregate);
3074 for (
const Section §ion : sectionVector) {
3075 if (section.members().isEmpty())
3078 startSection(section.title().toLower(), section.title());
3080 for (
const Node *member : section.members()) {
3081 if (member->access() == Access::Private)
3084 if (member->nodeType() != Node::Class) {
3086 generateDetailedMember(member, aggregate);
3088 startSectionBegin();
3089 m_writer->writeCharacters(
"class ");
3090 generateFullName(member, aggregate);
3093 generateBrief(member);
3102 generateObsoleteMembers(sections);
3107void DocBookGenerator::generateSynopsisInfo(
const QString &key,
const QString &value)
3109 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3110 m_writer->writeAttribute(
"role", key);
3111 m_writer->writeCharacters(value);
3112 m_writer->writeEndElement();
3118 m_writer->writeTextElement(dbNamespace,
"modifier", value);
3123
3124
3134 if (!m_useDocBook52)
3161 QString synopsisTag = nodeToSynopsisTag(node);
3162 m_writer->writeStartElement(dbNamespace, synopsisTag);
3167 m_writer->writeStartElement(dbNamespace,
"ooclass");
3168 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3169 m_writer->writeEndElement();
3172 m_writer->writeTextElement(dbNamespace,
"namespacename", node->plainName());
3175 m_writer->writeStartElement(dbNamespace,
"ooclass");
3176 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3177 m_writer->writeEndElement();
3179 if (!qcn->groupNames().isEmpty())
3180 m_writer->writeAttribute(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3182 m_writer->writeTextElement(dbNamespace,
"modifier",
"(Qt property)");
3184 m_writer->writeTextElement(dbNamespace,
"type", propertyNode->dataType());
3186 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3190 m_writer->writeTextElement(dbNamespace,
"modifier",
"static");
3193 m_writer->writeTextElement(dbNamespace,
"type", variableNode->dataType());
3195 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3199 m_writer->writeTextElement(dbNamespace,
"enumname", node->plainName());
3203 QString name = node->name();
3205 name.prepend(qpn->element() + QLatin1Char(
'.'));
3207 m_writer->writeTextElement(dbNamespace,
"type", qpn->dataType());
3209 m_writer->writeTextElement(dbNamespace,
"varname", name);
3213 m_writer->writeTextElement(dbNamespace,
"modifier",
"attached");
3217 m_writer->writeTextElement(dbNamespace,
"modifier",
"writable");
3221 m_writer->writeTextElement(dbNamespace,
"modifier",
"required");
3225 generateModifier(
"[read-only]");
3229 generateModifier(
"[default]");
3233 if (functionNode->virtualness() !=
"non")
3234 generateModifier(
"virtual");
3235 if (functionNode->isConst())
3236 generateModifier(
"const");
3237 if (functionNode->isStatic())
3238 generateModifier(
"static");
3243 if (functionNode->returnType() ==
"void")
3244 m_writer->writeEmptyElement(dbNamespace,
"void");
3246 m_writer->writeTextElement(dbNamespace,
"type", functionNode->returnTypeString());
3251 QString name = node->plainName();
3252 if (name.endsWith(
"()"))
3254 m_writer->writeTextElement(dbNamespace,
"methodname", name);
3258 m_writer->writeEmptyElement(dbNamespace,
"void");
3263 for (
int i = 0; i < lp
.count(); ++i) {
3265 m_writer->writeStartElement(dbNamespace,
"methodparam");
3267 m_writer->writeTextElement(dbNamespace,
"type", parameter.type());
3269 m_writer->writeTextElement(dbNamespace,
"parameter", parameter.name());
3271 if (!parameter.defaultValue().isEmpty()) {
3272 m_writer->writeTextElement(dbNamespace,
"initializer", parameter.defaultValue());
3275 m_writer->writeEndElement();
3279 if (functionNode->isDefault())
3280 generateModifier(
"default");
3281 if (functionNode->isFinal())
3282 generateModifier(
"final");
3283 if (functionNode->isOverride())
3284 generateModifier(
"override");
3286 m_writer->writeTextElement(dbNamespace,
"typedefname", node->plainName());
3290 QStringLiteral(
"Unexpected node type in generateDocBookSynopsis: %1")
3291 .arg(node->nodeTypeString()));
3297 for (
const EnumItem &item : enumNode->items()) {
3298 m_writer->writeStartElement(dbNamespace,
"enumitem");
3300 m_writer->writeTextElement(dbNamespace,
"enumidentifier", item.name());
3302 m_writer->writeTextElement(dbNamespace,
"enumvalue", item.value());
3304 m_writer->writeEndElement();
3308 if (enumNode->items().isEmpty()) {
3311 m_writer->writeStartElement(dbNamespace,
"enumitem");
3313 m_writer->writeEmptyElement(dbNamespace,
"enumidentifier");
3315 m_writer->writeEndElement();
3326 generateSynopsisInfo(
"meta", functionNode->metanessString());
3329 generateSynopsisInfo(
"overload",
"overload");
3330 generateSynopsisInfo(
"overload-number",
3331 QString::number(functionNode->overloadNumber()));
3334 if (functionNode->isRef())
3335 generateSynopsisInfo(
"refness", QString::number(1));
3336 else if (functionNode->isRefRef())
3337 generateSynopsisInfo(
"refness", QString::number(2));
3340 QStringList associatedProperties;
3341 const auto &nodes = functionNode->associatedProperties();
3342 for (
const Node *n : nodes) {
3343 const auto pn =
static_cast<
const PropertyNode *>(n);
3344 associatedProperties << pn->name();
3346 associatedProperties.sort();
3347 generateSynopsisInfo(
"associated-property",
3348 associatedProperties.join(QLatin1Char(
',')));
3354 signature +=
" final";
3356 signature +=
" override";
3358 signature +=
" = 0";
3360 signature +=
" = default";
3361 generateSynopsisInfo(
"signature", signature);
3367 case Access::Public:
3368 generateSynopsisInfo(
"access",
"public");
3370 case Access::Protected:
3371 generateSynopsisInfo(
"access",
"protected");
3373 case Access::Private:
3374 generateSynopsisInfo(
"access",
"private");
3379 if (node->isAbstract())
3380 generateSynopsisInfo(
"abstract",
"true");
3386 generateSynopsisInfo(
"status",
"active");
3388 case Node::Preliminary:
3389 generateSynopsisInfo(
"status",
"preliminary");
3391 case Node::Deprecated:
3392 generateSynopsisInfo(
"status",
"deprecated");
3394 case Node::Internal:
3395 generateSynopsisInfo(
"status",
"internal");
3398 generateSynopsisInfo(
"status",
"main");
3405 if (aggregate->includeFile()) generateSynopsisInfo(
"headers", *aggregate->includeFile());
3408 if (!aggregate->since().isEmpty())
3409 generateSynopsisInfo(
"since", formatSince(aggregate));
3413 if (!aggregate->physicalModuleName().isEmpty()) {
3417 if (
const auto result = cmakeRequisite(cn)) {
3418 generateSynopsisInfo(
"cmake-find-package", result->first);
3419 generateSynopsisInfo(
"cmake-target-link-libraries", result->second);
3422 if (cn && !cn->qtVariable().isEmpty())
3423 generateSynopsisInfo(
"qmake",
"QT += " + cn->qtVariable());
3431 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3432 m_writer->writeAttribute(
"role",
"nativeTypeFor");
3434 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
3437 for (
auto item : std::as_const(nativeTypes)) {
3438 const Node *otherNode{
nullptr};
3439 Atom a = Atom(Atom::LinkNode, CodeMarker::stringForNode(item));
3440 const QString &link = getAutoLink(&a, aggregate, &otherNode);
3441 generateSimpleLink(link, item->name());
3444 m_writer->writeEndElement();
3448 QList<RelatedClass>::ConstIterator r;
3449 if (!classe->baseClasses().isEmpty()) {
3450 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3451 m_writer->writeAttribute(
"role",
"inherits");
3453 r = classe->baseClasses().constBegin();
3455 while (r != classe->baseClasses().constEnd()) {
3457 generateFullName((*r).m_node, classe);
3459 if ((*r).m_access == Access::Protected) {
3460 m_writer->writeCharacters(
" (protected)");
3461 }
else if ((*r).m_access == Access::Private) {
3462 m_writer->writeCharacters(
" (private)");
3464 m_writer->writeCharacters(
3465 Utilities::comma(index++, classe->baseClasses().size()));
3470 m_writer->writeEndElement();
3475 if (!classe->derivedClasses().isEmpty()) {
3476 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3477 m_writer->writeAttribute(
"role",
"inheritedBy");
3478 generateSortedNames(classe, classe->derivedClasses());
3479 m_writer->writeEndElement();
3488 QString logicalModuleVersion;
3492 logicalModuleVersion = collection->logicalModuleVersion();
3494 logicalModuleVersion = qcn->logicalModuleVersion();
3496 QStringList importText;
3497 importText <<
"import " + qcn->logicalModuleName();
3498 if (!logicalModuleVersion.isEmpty())
3499 importText << logicalModuleVersion;
3500 generateSynopsisInfo(
"import", importText.join(
' '));
3503 if (!qcn->since().isEmpty())
3504 generateSynopsisInfo(
"since", formatSince(qcn));
3510 QStringList knownTypeNames{qcn->name()};
3512 knownTypeNames << base->name();
3517 if (!subs.isEmpty()) {
3518 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3519 m_writer->writeAttribute(
"role",
"inheritedBy");
3520 generateSortedQmlNames(qcn, knownTypeNames, subs);
3521 m_writer->writeEndElement();
3527 const Node *otherNode =
nullptr;
3529 QString link = getAutoLink(&a, base, &otherNode);
3531 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3532 m_writer->writeAttribute(
"role",
"inherits");
3533 generateSimpleLink(link, base->name());
3535 for (
const auto sub : std::as_const(subs)) {
3536 if (knownTypeNames.contains(sub->name())) {
3537 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
3541 m_writer->writeEndElement();
3549 const Node *otherNode =
nullptr;
3551 QString link = getAutoLink(&a, cn, &otherNode);
3553 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3554 m_writer->writeAttribute(
"role",
"nativeType");
3555 generateSimpleLink(link, cn->name());
3556 m_writer->writeEndElement();
3563 case Node::UnspecifiedSafeness:
3564 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3566 case Node::NonReentrant:
3567 generateSynopsisInfo(
"threadsafeness",
"non-reentrant");
3569 case Node::Reentrant:
3570 generateSynopsisInfo(
"threadsafeness",
"reentrant");
3572 case Node::ThreadSafe:
3573 generateSynopsisInfo(
"threadsafeness",
"thread safe");
3576 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3581 if (!node->physicalModuleName().isEmpty())
3582 generateSynopsisInfo(
"module", node->physicalModuleName());
3585 if (classNode && !classNode->groupNames().isEmpty()) {
3586 generateSynopsisInfo(
"groups", classNode->groupNames().join(QLatin1Char(
',')));
3587 }
else if (qcn && !qcn->groupNames().isEmpty()) {
3588 generateSynopsisInfo(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3593 for (
const Node *fnNode : propertyNode->getters()) {
3595 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3596 generateSynopsisInfo(
"getter", funcNode->name());
3599 for (
const Node *fnNode : propertyNode->setters()) {
3601 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3602 generateSynopsisInfo(
"setter", funcNode->name());
3605 for (
const Node *fnNode : propertyNode->resetters()) {
3607 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3608 generateSynopsisInfo(
"resetter", funcNode->name());
3611 for (
const Node *fnNode : propertyNode->notifiers()) {
3613 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3614 generateSynopsisInfo(
"notifier", funcNode->name());
3619 m_writer->writeEndElement();
3625 m_writer->writeStartElement(dbNamespace,
"typedefsynopsis");
3628 m_writer->writeTextElement(dbNamespace,
"typedefname",
3629 enumNode->flagsType()->fullDocumentName());
3632 m_writer->writeEndElement();
3643 return node->name().mid(4);
3644 return node->name();
3648
3649
3650
3651void DocBookGenerator::typified(
const QString &string,
const Node *relative,
bool trailingSpace,
3656 QString pendingWord;
3658 for (
int i = 0; i <= string.size(); ++i) {
3660 if (i != string.size())
3663 QChar lower = ch.toLower();
3664 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
3665 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
3668 if (!pendingWord.isEmpty()) {
3669 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
3670 if (generateType && isProbablyType) {
3672 m_writer->writeCharacters(result);
3681 href = linkForNode(n, relative);
3684 m_writer->writeStartElement(dbNamespace,
"type");
3686 m_writer->writeCharacters(pendingWord);
3688 generateSimpleLink(href, pendingWord);
3689 m_writer->writeEndElement();
3691 result += pendingWord;
3694 pendingWord.clear();
3696 if (ch.unicode() !=
'\0')
3701 if (trailingSpace && string.size()) {
3702 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
3703 result += QLatin1Char(
' ');
3706 m_writer->writeCharacters(result);
3710 bool generateNameLink)
3714 QString name = taggedNode(node);
3716 if (!generateNameLink) {
3717 m_writer->writeCharacters(name);
3721 m_writer->writeStartElement(dbNamespace,
"emphasis");
3722 m_writer->writeAttribute(
"role",
"bold");
3723 generateSimpleLink(linkForNode(node, relative), name);
3724 m_writer->writeEndElement();
3728 bool generateExtra,
bool generateType)
3730 const QString &pname = parameter.name();
3731 const QString &ptype = parameter.type();
3733 if (!pname.isEmpty()) {
3734 typified(ptype, relative,
true, generateType);
3740 if (generateExtra || pname.isEmpty()) {
3741 m_writer->writeStartElement(dbNamespace,
"emphasis");
3742 m_writer->writeCharacters(paramName);
3743 m_writer->writeEndElement();
3746 const QString &pvalue = parameter.defaultValue();
3747 if (generateExtra && !pvalue.isEmpty())
3748 m_writer->writeCharacters(
" = " + pvalue);
3760 const int MaxEnumValues = 6;
3762 if (generateExtra) {
3763 if (
auto extra = CodeMarker::extraSynopsis(node, style); !extra.isEmpty())
3764 m_writer->writeCharacters(extra +
" ");
3768 QString namePrefix {};
3772 namePrefix = taggedNode(node->parent()) +
"::";
3777 case Node::Namespace:
3778 m_writer->writeCharacters(
"namespace ");
3779 m_writer->writeCharacters(namePrefix);
3780 generateSynopsisName(node, relative, generateNameLink);
3783 m_writer->writeCharacters(
"class ");
3784 m_writer->writeCharacters(namePrefix);
3785 generateSynopsisName(node, relative, generateNameLink);
3792 if (!func->isNonvirtual())
3793 m_writer->writeCharacters(QStringLiteral(
"virtual "));
3797 if (style != Section::AllMembers && !func->returnType().isEmpty())
3798 typified(func->returnTypeString(), relative,
true, generateType);
3799 m_writer->writeCharacters(namePrefix);
3800 generateSynopsisName(node, relative, generateNameLink);
3803 m_writer->writeCharacters(QStringLiteral(
"("));
3806 for (
int i = 0; i < parameters
.count(); i++) {
3808 m_writer->writeCharacters(QStringLiteral(
", "));
3809 generateParameter(parameters
.at(i
), relative, generateExtra, generateType);
3812 m_writer->writeCharacters(QStringLiteral(
")"));
3815 if (func->isConst())
3816 m_writer->writeCharacters(QStringLiteral(
" const"));
3822 synopsis += QStringLiteral(
" final");
3824 synopsis += QStringLiteral(
" override");
3826 synopsis += QStringLiteral(
" = 0");
3828 synopsis += QStringLiteral(
" &");
3830 synopsis += QStringLiteral(
" &&");
3831 m_writer->writeCharacters(synopsis);
3833 if (!func->returnType().isEmpty() && func->returnType() !=
"void") {
3834 m_writer->writeCharacters(QStringLiteral(
" : "));
3835 typified(func->returnTypeString(), relative,
false, generateType);
3840 synopsis += QStringLiteral(
" &");
3842 synopsis += QStringLiteral(
" &&");
3843 m_writer->writeCharacters(synopsis);
3847 const auto enume =
static_cast<
const EnumNode *>(node);
3849 m_writer->writeCharacters(
"enum "_L1);
3850 m_writer->writeCharacters(namePrefix);
3851 generateSynopsisName(node, relative, generateNameLink);
3852 }
else if (generateNameLink) {
3853 m_writer->writeStartElement(dbNamespace,
"emphasis");
3854 m_writer->writeAttribute(
"role",
"bold");
3855 generateSimpleLink(linkForNode(node, relative),
"enum");
3856 m_writer->writeEndElement();
3858 m_writer->writeCharacters(
"enum"_L1);
3865 QStringList documentedItems = enume
->doc().enumItemNames();
3866 if (documentedItems.isEmpty()) {
3867 const auto &enumItems = enume->items();
3868 for (
const auto &item : enumItems)
3869 documentedItems << item.name();
3871 const QStringList omitItems = enume
->doc().omitEnumItemNames();
3872 for (
const auto &item : omitItems)
3873 documentedItems.removeAll(item);
3875 if (documentedItems.size() > MaxEnumValues) {
3877 const QString last = documentedItems.last();
3878 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
3879 documentedItems +=
"…";
3880 documentedItems += last;
3882 synopsis += documentedItems.join(QLatin1String(
", "));
3884 if (!documentedItems.isEmpty())
3885 synopsis += QLatin1Char(
' ');
3886 synopsis += QLatin1Char(
'}');
3888 m_writer->writeCharacters(synopsis);
3892 auto templateDecl = node->templateDecl();
3894 m_writer->writeCharacters((*templateDecl).to_qstring() + QLatin1Char(
' '));
3896 m_writer->writeCharacters(namePrefix);
3897 generateSynopsisName(node, relative, generateNameLink);
3900 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
3901 m_writer->writeCharacters(
"flags ");
3902 m_writer->writeCharacters(namePrefix);
3903 generateSynopsisName(node, relative, generateNameLink);
3906 const auto property =
static_cast<
const PropertyNode *>(node);
3907 m_writer->writeCharacters(namePrefix);
3908 generateSynopsisName(node, relative, generateNameLink);
3909 m_writer->writeCharacters(
" : ");
3910 typified(property->qualifiedDataType(), relative,
false, generateType);
3913 const auto variable =
static_cast<
const VariableNode *>(node);
3915 generateSynopsisName(node, relative, generateNameLink);
3916 m_writer->writeCharacters(
" : ");
3917 typified(variable->dataType(), relative,
false, generateType);
3919 typified(variable->leftType(), relative,
false, generateType);
3920 m_writer->writeCharacters(
" ");
3921 m_writer->writeCharacters(namePrefix);
3922 generateSynopsisName(node, relative, generateNameLink);
3923 m_writer->writeCharacters(variable->rightType());
3927 m_writer->writeCharacters(namePrefix);
3928 generateSynopsisName(node, relative, generateNameLink);
3941 if (qpn->enumNode() && !enumValue.startsWith(
"%1."_L1.arg(qpn->enumPrefix()))) {
3942 m_writer->writeCharacters(
"%1.%2"_L1.arg(qpn->enumPrefix(), enumValue));
3948 m_writer->writeCharacters(enumValue);
3952 QList<
const Node *> parents;
3954 parents.prepend(node);
3960 parents << relative;
3962 m_writer->writeStartElement(dbNamespace,
"code");
3963 for (
auto parent : parents) {
3964 generateSynopsisName(parent, relative,
true);
3965 m_writer->writeCharacters(
"::");
3968 m_writer->writeCharacters(enumValue);
3969 m_writer->writeEndElement();
3973
3974
3975
3976
3977
3978
3979
3983 QString code = getOverloadedSignalCode(node);
3987 m_writer->writeStartElement(dbNamespace,
"note");
3989 m_writer->writeStartElement(dbNamespace,
"para");
3990 m_writer->writeCharacters(
"Signal ");
3991 m_writer->writeTextElement(dbNamespace,
"emphasis", node->name());
3992 m_writer->writeCharacters(
" is overloaded in this class. To connect to this "
3993 "signal by using the function pointer syntax, Qt "
3994 "provides a convenient helper for obtaining the "
3995 "function pointer as shown in this example:");
3996 m_writer->writeTextElement(dbNamespace,
"code", code);
3997 m_writer->writeEndElement();
3999 m_writer->writeEndElement();
4004
4005
4006
4011 Q_ASSERT(node && !node->name().isEmpty());
4013 m_writer->writeStartElement(dbNamespace,
"note");
4018 m_writer->writeStartElement(dbNamespace,
"para");
4019 m_writer->writeCharacters(
4020 "This function can be invoked via the meta-object system and from QML. See ");
4021 generateSimpleLink(node->url(),
"Q_INVOKABLE");
4022 m_writer->writeCharacters(
".");
4023 m_writer->writeEndElement();
4027 m_writer->writeTextElement(
4028 dbNamespace,
"para",
4029 "This is a private signal. It can be used in signal connections but "
4030 "cannot be emitted by the user.");
4034 QString handler(node->name());
4035 int prefixLocation = handler.lastIndexOf(
'.', -2) + 1;
4036 handler[prefixLocation] = handler[prefixLocation].toTitleCase();
4037 handler.insert(prefixLocation, QLatin1String(
"on"));
4038 m_writer->writeStartElement(dbNamespace,
"para");
4039 m_writer->writeCharacters(
"The corresponding handler is ");
4040 m_writer->writeTextElement(dbNamespace,
"code", handler);
4041 m_writer->writeCharacters(
".");
4042 m_writer->writeEndElement();
4050 const auto *fn =
static_cast<
const FunctionNode *>(node);
4051 auto propertyNodes = fn->associatedProperties();
4052 if (propertyNodes.isEmpty())
4055 for (
const auto propertyNode : std::as_const(propertyNodes)) {
4057 const auto pn =
static_cast<
const PropertyNode *>(propertyNode);
4058 switch (pn->role(fn)) {
4059 case PropertyNode::FunctionRole::Getter:
4060 msg = QStringLiteral(
"Getter function");
4062 case PropertyNode::FunctionRole::Setter:
4063 msg = QStringLiteral(
"Setter function");
4065 case PropertyNode::FunctionRole::Resetter:
4066 msg = QStringLiteral(
"Resetter function");
4068 case PropertyNode::FunctionRole::Notifier:
4069 msg = QStringLiteral(
"Notifier signal");
4074 m_writer->writeStartElement(dbNamespace,
"para");
4075 m_writer->writeCharacters(msg +
" for property ");
4076 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4077 m_writer->writeCharacters(
". ");
4078 m_writer->writeEndElement();
4085 const Node *linkNode;
4087 QString link = getAutoLink(&linkAtom, node, &linkNode);
4088 m_writer->writeStartElement(dbNamespace,
"para");
4089 m_writer->writeCharacters(
"This property supports ");
4090 generateSimpleLink(link,
"QProperty");
4091 m_writer->writeCharacters(
" bindings.");
4092 m_writer->writeEndElement();
4101 m_writer->writeEndElement();
4109 bool closeSupplementarySection =
false;
4113 const QList<Node *> &collective = scn->collective();
4115 bool firstFunction =
true;
4116 for (
const auto *sharedNode : collective) {
4117 if (firstFunction) {
4118 startSectionBegin(sharedNode);
4120 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4121 m_writer->writeAttribute(
"renderas",
"sect2");
4122 writeXmlId(sharedNode);
4125 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4127 generateSynopsis(sharedNode, relative, Section::Details);
4129 if (firstFunction) {
4131 firstFunction =
false;
4133 m_writer->writeEndElement();
4140 startSectionBegin(node);
4142 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4146 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4147 m_writer->writeAttribute(
"renderas",
"sect2");
4149 m_writer->writeEndElement();
4152 startSectionBegin(node);
4154 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4159 Q_ASSERT(m_hasSection);
4168 closeSupplementarySection =
true;
4169 startSection(
"",
"Notes");
4172 generateOverloadedSignal(node);
4178 const auto property =
static_cast<
const PropertyNode *>(node);
4187 m_writer->writeStartElement(dbNamespace,
"para");
4189 m_writer->writeStartElement(dbNamespace,
"emphasis");
4190 m_writer->writeAttribute(
"role",
"bold");
4191 m_writer->writeCharacters(
"Access functions:");
4193 m_writer->writeEndElement();
4195 m_writer->writeEndElement();
4197 generateSectionList(section, node);
4204 m_writer->writeStartElement(dbNamespace,
"para");
4206 m_writer->writeStartElement(dbNamespace,
"emphasis");
4207 m_writer->writeAttribute(
"role",
"bold");
4208 m_writer->writeCharacters(
"Notifier signal:");
4210 m_writer->writeEndElement();
4212 m_writer->writeEndElement();
4214 generateSectionList(notifiers, node);
4218 const auto en =
static_cast<
const EnumNode *>(node);
4220 if (m_qflagsHref.isEmpty()) {
4221 Node *qflags =
m_qdb->findClassNode(QStringList(
"QFlags"));
4223 m_qflagsHref = linkForNode(qflags,
nullptr);
4227 m_writer->writeStartElement(dbNamespace,
"para");
4228 m_writer->writeCharacters(
"The ");
4229 m_writer->writeStartElement(dbNamespace,
"code");
4230 m_writer->writeCharacters(en->flagsType()->name());
4231 m_writer->writeEndElement();
4232 m_writer->writeCharacters(
" type is a typedef for ");
4233 m_writer->writeStartElement(dbNamespace,
"code");
4234 generateSimpleLink(m_qflagsHref,
"QFlags");
4235 m_writer->writeCharacters(
"<" + en->name() +
">. ");
4236 m_writer->writeEndElement();
4237 m_writer->writeCharacters(
"It stores an OR combination of ");
4238 m_writer->writeStartElement(dbNamespace,
"code");
4239 m_writer->writeCharacters(en->name());
4240 m_writer->writeEndElement();
4241 m_writer->writeCharacters(
" values.");
4242 m_writer->writeEndElement();
4247 if (closeSupplementarySection)
4258 bool useObsoleteMembers)
4263 if (!members.isEmpty()) {
4264 bool hasPrivateSignals =
false;
4265 bool isInvokable =
false;
4267 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4269 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4272 NodeVector::ConstIterator m = members.constBegin();
4273 while (m != members.constEnd()) {
4274 if ((*m)->access() == Access::Private) {
4279 m_writer->writeStartElement(dbNamespace,
"listitem");
4281 m_writer->writeStartElement(dbNamespace,
"para");
4284 generateSynopsis(*m, relative, section
.style());
4285 if ((*m)->isFunction()) {
4287 if (fn->isPrivateSignal())
4288 hasPrivateSignals =
true;
4289 else if (fn->isInvokable())
4293 m_writer->writeEndElement();
4295 m_writer->writeEndElement();
4301 m_writer->writeEndElement();
4304 if (hasPrivateSignals)
4311 && !section.inheritedMembers().isEmpty()) {
4312 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4314 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4317 generateSectionInheritedList(section, relative);
4319 m_writer->writeEndElement();
4327 QList<std::pair<Aggregate *,
int>>::ConstIterator p = section.inheritedMembers().constBegin();
4328 while (p != section.inheritedMembers().constEnd()) {
4329 m_writer->writeStartElement(dbNamespace,
"listitem");
4330 m_writer->writeCharacters(QString::number((*p).second) + u' ');
4331 if ((*p).second == 1)
4332 m_writer->writeCharacters(section.singular());
4334 m_writer->writeCharacters(section.plural());
4335 m_writer->writeCharacters(
" inherited from ");
4336 generateSimpleLink(fileName((*p).first) +
'#'
4337 + Generator::cleanRef(section.title().toLower()),
4338 (*p).first->plainFullName(relative));
4344
4345
4346
4350 Q_ASSERT(m_writer ==
nullptr);
4351 m_writer = startDocument(pn);
4353 generateHeader(pn->fullTitle(), pn->subtitle(), pn);
4362
4363
4368 Q_ASSERT(m_writer ==
nullptr);
4369 m_writer = startDocument(qcn);
4372 QString title = qcn->fullTitle();
4374 title.append(
" QML Value Type");
4376 title.append(
" QML Type");
4382 generateHeader(title, qcn->subtitle(), qcn);
4386 startSection(
"details",
"Detailed Description");
4394 for (
const auto §ion : sections.stdQmlTypeDetailsSections()) {
4395 if (!section.isEmpty()) {
4396 startSection(section.title().toLower(), section.title());
4398 for (
const auto &member : section.members())
4399 generateDetailedQmlMember(member, qcn);
4405 generateObsoleteQmlMembers(sections);
4414
4415
4416
4423 if (!title.isEmpty())
4427 title += n->element() + QLatin1Char(
'.');
4428 title += n->name() +
" : " + n->dataType();
4433 auto generateQmlMethodTitle = [&](
Node *node) {
4441 if (!scn->name().isEmpty())
4442 heading = scn->name() +
" group";
4444 heading = node->name();
4445 startSection(scn, heading);
4450 const QList<Node *> sharedNodes = scn->collective();
4451 for (
const auto &sharedNode : sharedNodes) {
4452 if (sharedNode->isQmlProperty()) {
4453 auto *qpn =
static_cast<QmlPropertyNode *>(sharedNode);
4455 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4456 m_writer->writeAttribute(
"renderas",
"sect2");
4458 m_writer->writeCharacters(getQmlPropertyTitle(qpn));
4459 m_writer->writeEndElement();
4462 generateDocBookSynopsis(qpn);
4467 startSection(qpn, getQmlPropertyTitle(qpn));
4471 const QList<Node *> &sharedNodes = scn->collective();
4476 for (
const auto &sharedNode : sharedNodes) {
4478 if (!sharedNode->isFunction(Node::QML) && !sharedNode->isQmlProperty()) {
4484 startSectionBegin(sharedNode);
4486 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4487 m_writer->writeAttribute(
"renderas",
"sect2");
4491 if (sharedNode->isFunction(Node::QML))
4492 generateQmlMethodTitle(sharedNode);
4493 else if (sharedNode->isQmlProperty())
4494 m_writer->writeCharacters(
4495 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(sharedNode)));
4501 m_writer->writeEndElement();
4502 generateDocBookSynopsis(sharedNode);
4508 startSectionBegin(refForNode(node));
4511 generateQmlMethodTitle(node);
4512 else if (node->isQmlProperty())
4513 m_writer->writeCharacters(
4514 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(node)));
4519 startSectionBegin(node);
4520 generateQmlMethodTitle(node);
4534
4535
4542 if (!node->url().isNull())
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4587 generateCppReferencePage(
static_cast<
Aggregate *>(node));
4597 auto *aggregate =
static_cast<
Aggregate *>(node);
4598 for (
auto c : aggregate->childNodes()) {
4599 if (node->isPageNode() && !node->isPrivate())
4600 generateDocumentation(c);
4611 Q_ASSERT(m_writer ==
nullptr);
4612 m_writer = startDocument(aggregate);
4615 generateHeader(aggregate->plainFullName(),
"", aggregate);
4620 if (!aggregate
->doc().isEmpty()) {
4621 startSection(
"details",
"Detailed Description");
4623 generateBody(aggregate);
4632 for (
const auto §ion : std::as_const(*detailsSections)) {
4633 if (section.isEmpty())
4636 startSection(section.title().toLower(), section.title());
4638 const QList<Node *> &members = section.members();
4639 for (
const auto &member : members) {
4640 if (!member->isPrivate()) {
4641 if (!member->isClassNode()) {
4642 generateDetailedMember(member, aggregate);
4644 startSectionBegin();
4645 generateFullName(member, aggregate);
4648 generateBrief(member);
4663
4664
4669 Q_ASSERT(m_writer ==
nullptr);
4670 m_writer = startDocument(cn);
4673 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4690 if (!nmm.isEmpty()) {
4691 startSection(
"namespaces",
"Namespaces");
4692 generateAnnotatedList(cn, nmm.values(),
"namespaces");
4696 if (!nmm.isEmpty()) {
4697 startSection(
"classes",
"Classes");
4698 generateAnnotatedList(cn, nmm.values(),
"classes");
4704 bool generatedTitle =
false;
4706 startSection(
"details",
"Detailed Description");
4707 generatedTitle =
true;
4712 !cn
->doc().body().isEmpty() ||
4714 !cn
->doc().alsoList().empty() ||
4717 writeAnchor(
"details");
4723 if (!cn->noAutoList() && (cn->isGroup() || cn->isQmlModule()))
4724 generateAnnotatedList(cn, cn->members(),
"members", AutoSection);
4735
4736
4737
4738
4743 QString name = cn->name().toLower();
4744 name.replace(QChar(
' '), QString(
"-"));
4745 QString filename = cn->tree()->physicalModuleName() +
"-" + name +
"." + fileExtension();
4748 Q_ASSERT(m_writer ==
nullptr);
4749 m_writer = startGenericDocument(cn, filename);
4752 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4758 m_writer->writeStartElement(dbNamespace,
"para");
4759 m_writer->writeCharacters(
"Each function or type documented here is related to a class or "
4760 "namespace that is documented in a different module. The reference "
4761 "page for that class or namespace will link to the function or type "
4763 m_writer->writeEndElement();
4767 for (
const auto &member : members)
4768 generateDetailedMember(member, cnc);
4781 m_writer->writeStartElement(dbNamespace,
"link");
4782 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(node));
4783 m_writer->writeAttribute(xlinkNamespace,
"role", targetType(node));
4784 m_writer->writeCharacters(node->fullName(relative));
4785 m_writer->writeEndElement();
4789 const Node *actualNode)
4791 Q_ASSERT(apparentNode);
4792 Q_ASSERT(actualNode);
4795 m_writer->writeStartElement(dbNamespace,
"link");
4796 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(actualNode));
4797 m_writer->writeAttribute(
"role", targetType(actualNode));
4798 m_writer->writeCharacters(fullName);
4799 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 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.
void generateSortedQmlNames(const Node *base, const QStringList &knownTypes, const NodeList &subs)
DocBookGenerator(FileResolver &file_resolver)
bool generateThreadSafeness(const Node *node)
Generates text that explains how threadsafe and/or reentrant node is.
void generateCollectionNode(CollectionNode *cn)
Generate the HTML page for a group, module, or QML module.
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.
static Text sectionHeading(const Atom *sectionBegin)
const Atom * firstAtom() const
Text & operator=(const Text &text)
const Atom * lastAtom() const
bool isStatic() const override
Returns true if the FunctionNode represents a static function.
static bool 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_PRODUCTNAME
#define CONFIG_BUILDVERSION
static const char xlinkNamespace[]
static QString nodeToSynopsisTag(const Node *node)
QString removeCodeMarkers(const QString &code)
static const char dbNamespace[]
QString taggedNode(const Node *node)
static const char itsNamespace[]
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.