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;
586 QString tag = atom->type() == Atom::Image ?
"mediaobject" :
"inlinemediaobject";
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(
1159 Text::sectionHeading(atom->next()->next()).toString());
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()));
2150 QMap<QString, Node *> classMap;
2152 for (
auto sub : subs)
2153 classMap[sub->plainFullName(base).toLower()] = sub;
2155 QStringList names = classMap.keys();
2159 for (
const QString &name : names) {
2160 generateFullName(classMap.value(name), base);
2161 m_writer->writeCharacters(Utilities::comma(index++, names.size()));
2166
2167
2176 QXmlStreamWriter* oldWriter = m_writer;
2178 m_writer =
new QXmlStreamWriter(&output);
2181 if (aggregate->includeFile()) generateRequisite(
"Header", *aggregate->includeFile());
2184 if (!aggregate->since().isEmpty())
2185 generateRequisite(
"Since", formatSince(aggregate));
2192 if (
const auto result = cmakeRequisite(cn)) {
2193 generateCMakeRequisite(result->first, result->second);
2196 if (cn && !cn->qtVariable().isEmpty())
2197 generateRequisite(
"qmake",
"QT += " + cn->qtVariable());
2204 generateStartRequisite(
"In QML");
2207 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2210 for (
const auto &item : std::as_const(nativeTypes)) {
2211 generateFullName(item, classe);
2212 m_writer->writeCharacters(
2213 Utilities::comma(idx++, nativeTypes.size()));
2215 generateEndRequisite();
2219 QList<RelatedClass>::ConstIterator r;
2220 if (!classe->baseClasses().isEmpty()) {
2221 generateStartRequisite(
"Inherits");
2223 r = classe->baseClasses().constBegin();
2225 while (r != classe->baseClasses().constEnd()) {
2227 generateFullName((*r).m_node, classe);
2229 if ((*r).m_access == Access::Protected)
2230 m_writer->writeCharacters(
" (protected)");
2231 else if ((*r).m_access == Access::Private)
2232 m_writer->writeCharacters(
" (private)");
2233 m_writer->writeCharacters(
2234 Utilities::comma(index++, classe->baseClasses().size()));
2239 generateEndRequisite();
2243 if (!classe->derivedClasses().isEmpty()) {
2244 generateStartRequisite(
"Inherited By");
2245 generateSortedNames(classe, classe->derivedClasses());
2246 generateEndRequisite();
2251 if (!aggregate->groupNames().empty()) {
2252 generateStartRequisite(
"Group");
2254 generateEndRequisite();
2258 if (
auto status = formatStatus(aggregate, m_qdb); status)
2259 generateRequisite(
"Status", status.value());
2263 m_writer = oldWriter;
2265 if (!output.isEmpty()) {
2268 static const QRegularExpression xmlTag(R"(<(/?)n\d+:)");
2269 static const QRegularExpression xmlnsDocBookDefinition(R"( xmlns:n\d+=")" + QString{dbNamespace} +
"\"");
2270 static const QRegularExpression xmlnsXLinkDefinition(R"( xmlns:n\d+=")" + QString{xlinkNamespace} +
"\"");
2271 static const QRegularExpression xmlAttr(R"( n\d+:)");
2273 const QString cleanOutput = output.replace(xmlTag, R"(<\1db:)")
2274 .replace(xmlnsDocBookDefinition,
"")
2275 .replace(xmlnsXLinkDefinition,
"")
2276 .replace(xmlAttr,
" xlink:");
2278 m_writer->writeStartElement(dbNamespace,
"variablelist");
2280 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2283 m_writer->device()->write(cleanOutput.toUtf8());
2285 m_writer->writeEndElement();
2291
2292
2311 const bool generate_import_statement = !qcn->logicalModuleName().isEmpty() && (!collection || !collection
->isInternal() ||
m_showInternal);
2313 const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base;
2315 if (!generates_something)
2319 m_writer->writeStartElement(dbNamespace,
"variablelist");
2321 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2324 if (generate_import_statement) {
2325 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2326 generateRequisite(
"Import Statement", parts.join(
' ').trimmed());
2330 if (!qcn->since().isEmpty())
2331 generateRequisite(
"Since:", formatSince(qcn));
2334 if (!subs.isEmpty()) {
2335 generateStartRequisite(
"Inherited By:");
2337 generateEndRequisite();
2342 const Node *otherNode =
nullptr;
2344 QString link = getAutoLink(&a, qcn, &otherNode);
2346 generateStartRequisite(
"Inherits:");
2347 generateSimpleLink(link, base->name());
2348 generateEndRequisite();
2354 generateStartRequisite(
"In C++:");
2355 generateSimpleLink(fullDocumentLocation(cn), cn->name());
2356 generateEndRequisite();
2360 if (!qcn->groupNames().empty()) {
2361 generateStartRequisite(
"Group");
2363 generateEndRequisite();
2367 if (
auto status = formatStatus(qcn, m_qdb); status)
2368 generateRequisite(
"Status:", status.value());
2370 m_writer->writeEndElement();
2381 const QString &state =
static_cast<
const CollectionNode*>(node)->state();
2382 if (!state.isEmpty()) {
2383 m_writer->writeStartElement(dbNamespace,
"para");
2384 m_writer->writeCharacters(
"This " + typeString(node) +
" is in ");
2385 m_writer->writeStartElement(dbNamespace,
"emphasis");
2386 m_writer->writeCharacters(state);
2387 m_writer->writeEndElement();
2388 m_writer->writeCharacters(
" state.");
2389 m_writer->writeEndElement();
2394 if (
const auto version = node->deprecatedSince(); !version.isEmpty()) {
2395 m_writer->writeStartElement(dbNamespace,
"para");
2396 m_writer->writeCharacters(
"This " + typeString(node)
2397 +
" is scheduled for deprecation in version "
2399 m_writer->writeEndElement();
2404 case Node::Preliminary:
2405 m_writer->writeStartElement(dbNamespace,
"para");
2406 m_writer->writeStartElement(dbNamespace,
"emphasis");
2407 m_writer->writeAttribute(
"role",
"bold");
2408 m_writer->writeCharacters(
"This " + typeString(node)
2409 +
" is under development and is subject to change.");
2410 m_writer->writeEndElement();
2411 m_writer->writeEndElement();
2414 case Node::Deprecated:
2415 m_writer->writeStartElement(dbNamespace,
"para");
2417 m_writer->writeStartElement(dbNamespace,
"emphasis");
2418 m_writer->writeAttribute(
"role",
"bold");
2420 m_writer->writeCharacters(
"This " + typeString(node) +
" is deprecated");
2421 if (
const QString &version = node->deprecatedSince(); !version.isEmpty()) {
2422 m_writer->writeCharacters(
" since ");
2423 if (node->isQmlNode() && !node->logicalModuleName().isEmpty())
2424 m_writer->writeCharacters(node->logicalModuleName() +
" ");
2425 m_writer->writeCharacters(version);
2427 m_writer->writeCharacters(
". We strongly advise against using it in new code.");
2428 if (node->isAggregate())
2429 m_writer->writeEndElement();
2430 m_writer->writeEndElement();
2440
2441
2442
2446 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2449 NodeList::ConstIterator n = nodes.constBegin();
2450 while (n != nodes.constEnd()) {
2451 m_writer->writeStartElement(dbNamespace,
"listitem");
2453 m_writer->writeStartElement(dbNamespace,
"para");
2455 generateSimpleLink(currentGenerator()->fullDocumentLocation(*n),
2456 (*n)->signature(Node::SignaturePlain));
2458 m_writer->writeEndElement();
2460 m_writer->writeEndElement();
2465 m_writer->writeEndElement();
2470
2471
2472
2479 const auto aggregate =
static_cast<
const Aggregate *>(node);
2481 const QStringList &groups_names{aggregate->groupNames()};
2482 if (!groups_names.empty()) {
2483 m_writer->writeCharacters(aggregate->name() +
" is part of ");
2484 m_writer->writeStartElement(dbNamespace,
"simplelist");
2486 for (qsizetype index{0}; index < groups_names.size(); ++index) {
2490 m_writer->writeStartElement(dbNamespace,
"member");
2491 if (QString target{linkForNode(group,
nullptr)}; !target.isEmpty())
2492 generateSimpleLink(target, group->fullTitle());
2494 m_writer->writeCharacters(group->name());
2495 m_writer->writeEndElement();
2498 m_writer->writeEndElement();
2504
2505
2506
2512 const Node *reentrantNode;
2514 QString linkReentrant = getAutoLink(&reentrantAtom, node, &reentrantNode);
2515 const Node *threadSafeNode;
2517 QString linkThreadSafe = getAutoLink(&threadSafeAtom, node, &threadSafeNode);
2520 m_writer->writeStartElement(dbNamespace,
"warning");
2522 m_writer->writeStartElement(dbNamespace,
"para");
2523 m_writer->writeCharacters(
"This " + typeString(node) +
" is not ");
2524 generateSimpleLink(linkReentrant,
"reentrant");
2525 m_writer->writeCharacters(
".");
2526 m_writer->writeEndElement();
2528 m_writer->writeEndElement();
2532 m_writer->writeStartElement(dbNamespace,
"note");
2534 m_writer->writeStartElement(dbNamespace,
"para");
2537 m_writer->writeCharacters(
"All functions in this " + typeString(node) +
" are ");
2538 if (ts == Node::ThreadSafe)
2539 generateSimpleLink(linkThreadSafe,
"thread-safe");
2541 generateSimpleLink(linkReentrant,
"reentrant");
2547 if (!exceptions || (ts ==
Node::Reentrant && !threadsafe.isEmpty())) {
2548 m_writer->writeCharacters(
".");
2549 m_writer->writeEndElement();
2552 m_writer->writeCharacters(
" with the following exceptions:");
2553 m_writer->writeEndElement();
2555 m_writer->writeStartElement(dbNamespace,
"para");
2558 if (!nonreentrant.isEmpty()) {
2559 m_writer->writeCharacters(
"These functions are not ");
2560 generateSimpleLink(linkReentrant,
"reentrant");
2561 m_writer->writeCharacters(
":");
2562 m_writer->writeEndElement();
2564 generateSignatureList(nonreentrant);
2566 if (!threadsafe.isEmpty()) {
2567 m_writer->writeCharacters(
"These functions are also ");
2568 generateSimpleLink(linkThreadSafe,
"thread-safe");
2569 m_writer->writeCharacters(
":");
2570 m_writer->writeEndElement();
2572 generateSignatureList(threadsafe);
2575 if (!reentrant.isEmpty()) {
2576 m_writer->writeCharacters(
"These functions are only ");
2577 generateSimpleLink(linkReentrant,
"reentrant");
2578 m_writer->writeCharacters(
":");
2579 m_writer->writeEndElement();
2581 generateSignatureList(reentrant);
2583 if (!nonreentrant.isEmpty()) {
2584 m_writer->writeCharacters(
"These functions are not ");
2585 generateSimpleLink(linkReentrant,
"reentrant");
2586 m_writer->writeCharacters(
":");
2587 m_writer->writeEndElement();
2589 generateSignatureList(nonreentrant);
2594 m_writer->writeCharacters(
"This " + typeString(node) +
" is ");
2595 if (ts == Node::ThreadSafe)
2596 generateSimpleLink(linkThreadSafe,
"thread-safe");
2598 generateSimpleLink(linkReentrant,
"reentrant");
2599 m_writer->writeCharacters(
".");
2600 m_writer->writeEndElement();
2603 m_writer->writeEndElement();
2613
2614
2615
2623
2624
2625
2629 t =
"Destroys the instance of " + fn
->parent()->name() +
".";
2631 t +=
" The destructor is virtual.";
2633 t =
"Default constructs an instance of " + fn
->parent()->name() +
".";
2635 t =
"Copy constructor.";
2637 t =
"Move-copy constructor.";
2639 t =
"Copy-assignment constructor.";
2641 t =
"Move-assignment constructor.";
2645 m_writer->writeTextElement(dbNamespace,
"para", t);
2649 if (fn && !fn->overridesThis().isEmpty())
2650 generateReimplementsClause(fn);
2678 generateRequiredLinks(node);
2682
2683
2684
2685
2686
2693 const auto en =
static_cast<
const ExampleNode *>(node);
2696 if (exampleUrl.isEmpty()) {
2698 generateFileList(en,
false);
2699 generateFileList(en,
true);
2702 generateLinkToExample(en, exampleUrl);
2707
2708
2709
2710
2711
2715 QString exampleUrl(baseUrl);
2717#ifndef QT_BOOTSTRAPPED
2718 link = QUrl(exampleUrl).host();
2720 if (!link.isEmpty())
2721 link.prepend(
" @ ");
2722 link.prepend(
"Example project");
2724 const QLatin1Char separator(
'/');
2725 const QLatin1Char placeholder(
'\1');
2726 if (!exampleUrl.contains(placeholder)) {
2727 if (!exampleUrl.endsWith(separator))
2728 exampleUrl += separator;
2729 exampleUrl += placeholder;
2733 QStringList path = QStringList()
2735 path.removeAll(QString());
2739 startSection(
"Example project");
2741 m_writer->writeStartElement(dbNamespace,
"para");
2742 generateSimpleLink(exampleUrl.replace(placeholder, path.join(separator)), link);
2743 m_writer->writeEndElement();
2752
2753
2754
2755
2756
2757
2773 paths = en->images();
2776 paths = en->files();
2779 std::sort(paths.begin(), paths.end(), Generator::comparePaths);
2781 if (paths.isEmpty())
2784 startSection(
"",
"List of Files");
2786 m_writer->writeStartElement(dbNamespace,
"para");
2787 m_writer->writeCharacters(tag);
2788 m_writer->writeEndElement();
2791 startSection(
"List of Files");
2793 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2796 for (
const auto &path : std::as_const(paths)) {
2797 auto maybe_resolved_file{file_resolver.resolve(path)};
2798 if (!maybe_resolved_file) {
2800 QString details = std::transform_reduce(
2801 file_resolver.get_search_directories().cbegin(),
2802 file_resolver.get_search_directories().cend(),
2803 u"Searched directories:"_s,
2805 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
2808 en->location().warning(u"Cannot find file to quote from: %1"_s.arg(path), details);
2813 auto file{*maybe_resolved_file};
2814 if (images) addImageToCopy(en, file);
2815 else generateExampleFilePage(en, file);
2817 m_writer->writeStartElement(dbNamespace,
"listitem");
2819 m_writer->writeStartElement(dbNamespace,
"para");
2820 generateSimpleLink(file.get_query(), file.get_query());
2821 m_writer->writeEndElement();
2822 m_writer->writeEndElement();
2826 m_writer->writeEndElement();
2833
2834
2844 const auto en =
static_cast<
const ExampleNode *>(node);
2847 QXmlStreamWriter *currentWriter = m_writer;
2848 m_writer = startDocument(en, resolved_file.get_query());
2849 generateHeader(en->fullTitle(), en->subtitle(), en);
2854 QString code = quoter.quoteTo(en->location(), QString(), QString());
2855 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
2861 m_writer = currentWriter;
2867 if (fn->overridesThis().isEmpty() || !fn
->parent()->isClassNode())
2872 if (
const FunctionNode *overrides = cn->findOverriddenFunction(fn);
2875 m_writer->writeStartElement(dbNamespace,
"para");
2876 m_writer->writeCharacters(
"Reimplements: ");
2878 overrides->parent()->name() +
"::" + overrides->signature(Node::SignaturePlain);
2879 generateFullName(overrides
->parent(), fullName, overrides);
2880 m_writer->writeCharacters(
".");
2881 m_writer->writeEndElement();
2887 if (
const PropertyNode *sameName = cn->findOverriddenProperty(fn); sameName && sameName
->hasDoc()) {
2888 m_writer->writeStartElement(dbNamespace,
"para");
2889 m_writer->writeCharacters(
"Reimplements an access function for property: ");
2890 QString fullName = sameName->parent()->name() +
"::" + sameName->name();
2891 generateFullName(sameName
->parent(), fullName, sameName);
2892 m_writer->writeCharacters(
".");
2893 m_writer->writeEndElement();
2902 QList<Text> alsoList = node->doc().alsoList();
2903 supplementAlsoList(node, alsoList);
2905 if (!alsoList.isEmpty()) {
2906 startSection(
"See Also");
2908 m_writer->writeStartElement(dbNamespace,
"para");
2909 m_writer->writeStartElement(dbNamespace,
"emphasis");
2910 m_writer->writeCharacters(
"See also ");
2911 m_writer->writeEndElement();
2914 m_writer->writeStartElement(dbNamespace,
"simplelist");
2915 m_writer->writeAttribute(
"type",
"vert");
2916 m_writer->writeAttribute(
"role",
"see-also");
2919 for (
const Text &text : alsoList) {
2920 m_writer->writeStartElement(dbNamespace,
"member");
2921 generateText(text, node);
2922 m_writer->writeEndElement();
2926 m_writer->writeEndElement();
2929 m_writer->writeEndElement();
2937
2938
2939
2940QXmlStreamWriter *
DocBookGenerator::startGenericDocument(
const Node *node,
const QString &fileName)
2943 QFile *outFile = openSubPageFile(
static_cast<
const PageNode*>(node), fileName);
2944 m_writer =
new QXmlStreamWriter(outFile);
2945 m_writer->setAutoFormatting(
false);
2947 m_writer->writeStartDocument();
2949 m_writer->writeNamespace(dbNamespace,
"db");
2950 m_writer->writeNamespace(xlinkNamespace,
"xlink");
2952 m_writer->writeNamespace(itsNamespace,
"its");
2953 m_writer->writeStartElement(dbNamespace,
"article");
2954 m_writer->writeAttribute(
"version",
"5.2");
2955 if (!m_naturalLanguage.isEmpty())
2956 m_writer->writeAttribute(
"xml:lang", m_naturalLanguage);
2960 sectionLevels.resize(0);
2969 m_hasSection =
false;
2972 QString fileName = Generator::fileName(node, fileExtension());
2973 return startGenericDocument(node, fileName);
2978 m_hasSection =
false;
2980 QString fileName = linkForExampleFile(file);
2981 return startGenericDocument(en, fileName);
2986 m_writer->writeEndElement();
2987 m_writer->writeEndDocument();
2989 m_writer->device()->close();
2990 delete m_writer->device();
2996
2997
2998
3003 const auto aggregate =
static_cast<
const Aggregate *>(node);
3006 QString subtitleText;
3007 const QString typeWord{aggregate->typeWord(
true)};
3009 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3011 auto templateDecl = node->templateDecl();
3013 subtitleText =
"%1 %2 %3"_L1.arg((*templateDecl).to_qstring(),
3014 aggregate->typeWord(
false),
3015 aggregate->plainFullName());
3016 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3018 title = aggregate->fullTitle();
3022 m_writer = startDocument(node);
3025 generateHeader(title, subtitleText, aggregate);
3034 if (!aggregate
->doc().isEmpty()) {
3035 startSection(
"details",
"Detailed Description");
3037 generateBody(aggregate);
3048 for (
const Section §ion : sectionVector) {
3049 if (section.members().isEmpty())
3052 startSection(section.title().toLower(), section.title());
3054 for (
const Node *member : section.members()) {
3055 if (member->access() == Access::Private)
3058 if (member->nodeType() != Node::Class) {
3060 generateDetailedMember(member, aggregate);
3062 startSectionBegin();
3063 m_writer->writeCharacters(
"class ");
3064 generateFullName(member, aggregate);
3067 generateBrief(member);
3076 generateObsoleteMembers(sections);
3081void DocBookGenerator::generateSynopsisInfo(
const QString &key,
const QString &value)
3083 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3084 m_writer->writeAttribute(
"role", key);
3085 m_writer->writeCharacters(value);
3086 m_writer->writeEndElement();
3092 m_writer->writeTextElement(dbNamespace,
"modifier", value);
3097
3098
3108 if (!m_useDocBook52)
3135 QString synopsisTag = nodeToSynopsisTag(node);
3136 m_writer->writeStartElement(dbNamespace, synopsisTag);
3141 m_writer->writeStartElement(dbNamespace,
"ooclass");
3142 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3143 m_writer->writeEndElement();
3146 m_writer->writeTextElement(dbNamespace,
"namespacename", node->plainName());
3149 m_writer->writeStartElement(dbNamespace,
"ooclass");
3150 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3151 m_writer->writeEndElement();
3153 if (!qcn->groupNames().isEmpty())
3154 m_writer->writeAttribute(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3156 m_writer->writeTextElement(dbNamespace,
"modifier",
"(Qt property)");
3158 m_writer->writeTextElement(dbNamespace,
"type", propertyNode->dataType());
3160 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3164 m_writer->writeTextElement(dbNamespace,
"modifier",
"static");
3167 m_writer->writeTextElement(dbNamespace,
"type", variableNode->dataType());
3169 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3172 m_writer->writeTextElement(dbNamespace,
"enumname", node->plainName());
3175 QString name = node->name();
3177 name.prepend(qpn->element() + QLatin1Char(
'.'));
3179 m_writer->writeTextElement(dbNamespace,
"type", qpn->dataType());
3181 m_writer->writeTextElement(dbNamespace,
"varname", name);
3185 m_writer->writeTextElement(dbNamespace,
"modifier",
"attached");
3189 m_writer->writeTextElement(dbNamespace,
"modifier",
"writable");
3193 m_writer->writeTextElement(dbNamespace,
"modifier",
"required");
3197 generateModifier(
"[read-only]");
3201 generateModifier(
"[default]");
3205 if (functionNode->virtualness() !=
"non")
3206 generateModifier(
"virtual");
3207 if (functionNode->isConst())
3208 generateModifier(
"const");
3209 if (functionNode->isStatic())
3210 generateModifier(
"static");
3215 if (functionNode->returnType() ==
"void")
3216 m_writer->writeEmptyElement(dbNamespace,
"void");
3218 m_writer->writeTextElement(dbNamespace,
"type", functionNode->returnTypeString());
3223 QString name = node->plainName();
3224 if (name.endsWith(
"()"))
3226 m_writer->writeTextElement(dbNamespace,
"methodname", name);
3230 m_writer->writeEmptyElement(dbNamespace,
"void");
3235 for (
int i = 0; i < lp
.count(); ++i) {
3237 m_writer->writeStartElement(dbNamespace,
"methodparam");
3239 m_writer->writeTextElement(dbNamespace,
"type", parameter.type());
3241 m_writer->writeTextElement(dbNamespace,
"parameter", parameter.name());
3243 if (!parameter.defaultValue().isEmpty()) {
3244 m_writer->writeTextElement(dbNamespace,
"initializer", parameter.defaultValue());
3247 m_writer->writeEndElement();
3251 if (functionNode->isDefault())
3252 generateModifier(
"default");
3253 if (functionNode->isFinal())
3254 generateModifier(
"final");
3255 if (functionNode->isOverride())
3256 generateModifier(
"override");
3258 m_writer->writeTextElement(dbNamespace,
"typedefname", node->plainName());
3262 QStringLiteral(
"Unexpected node type in generateDocBookSynopsis: %1")
3263 .arg(node->nodeTypeString()));
3269 for (
const EnumItem &item : enumNode->items()) {
3270 m_writer->writeStartElement(dbNamespace,
"enumitem");
3272 m_writer->writeTextElement(dbNamespace,
"enumidentifier", item.name());
3274 m_writer->writeTextElement(dbNamespace,
"enumvalue", item.value());
3276 m_writer->writeEndElement();
3280 if (enumNode->items().isEmpty()) {
3283 m_writer->writeStartElement(dbNamespace,
"enumitem");
3285 m_writer->writeEmptyElement(dbNamespace,
"enumidentifier");
3287 m_writer->writeEndElement();
3298 generateSynopsisInfo(
"meta", functionNode->metanessString());
3301 generateSynopsisInfo(
"overload",
"overload");
3302 generateSynopsisInfo(
"overload-number",
3303 QString::number(functionNode->overloadNumber()));
3306 if (functionNode->isRef())
3307 generateSynopsisInfo(
"refness", QString::number(1));
3308 else if (functionNode->isRefRef())
3309 generateSynopsisInfo(
"refness", QString::number(2));
3312 QStringList associatedProperties;
3313 const auto &nodes = functionNode->associatedProperties();
3314 for (
const Node *n : nodes) {
3315 const auto pn =
static_cast<
const PropertyNode *>(n);
3316 associatedProperties << pn->name();
3318 associatedProperties.sort();
3319 generateSynopsisInfo(
"associated-property",
3320 associatedProperties.join(QLatin1Char(
',')));
3323 QString signature = functionNode->signature(Node::SignatureReturnType);
3326 signature +=
" final";
3328 signature +=
" override";
3330 signature +=
" = 0";
3332 signature +=
" = default";
3333 generateSynopsisInfo(
"signature", signature);
3339 case Access::Public:
3340 generateSynopsisInfo(
"access",
"public");
3342 case Access::Protected:
3343 generateSynopsisInfo(
"access",
"protected");
3345 case Access::Private:
3346 generateSynopsisInfo(
"access",
"private");
3351 if (node->isAbstract())
3352 generateSynopsisInfo(
"abstract",
"true");
3358 generateSynopsisInfo(
"status",
"active");
3360 case Node::Preliminary:
3361 generateSynopsisInfo(
"status",
"preliminary");
3363 case Node::Deprecated:
3364 generateSynopsisInfo(
"status",
"deprecated");
3366 case Node::Internal:
3367 generateSynopsisInfo(
"status",
"internal");
3370 generateSynopsisInfo(
"status",
"main");
3377 if (aggregate->includeFile()) generateSynopsisInfo(
"headers", *aggregate->includeFile());
3380 if (!aggregate->since().isEmpty())
3381 generateSynopsisInfo(
"since", formatSince(aggregate));
3385 if (!aggregate->physicalModuleName().isEmpty()) {
3389 if (
const auto result = cmakeRequisite(cn)) {
3390 generateSynopsisInfo(
"cmake-find-package", result->first);
3391 generateSynopsisInfo(
"cmake-target-link-libraries", result->second);
3394 if (cn && !cn->qtVariable().isEmpty())
3395 generateSynopsisInfo(
"qmake",
"QT += " + cn->qtVariable());
3403 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3404 m_writer->writeAttribute(
"role",
"nativeTypeFor");
3406 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
3409 for (
auto item : std::as_const(nativeTypes)) {
3410 const Node *otherNode{
nullptr};
3411 Atom a = Atom(Atom::LinkNode, CodeMarker::stringForNode(item));
3412 const QString &link = getAutoLink(&a, aggregate, &otherNode);
3413 generateSimpleLink(link, item->name());
3416 m_writer->writeEndElement();
3420 QList<RelatedClass>::ConstIterator r;
3421 if (!classe->baseClasses().isEmpty()) {
3422 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3423 m_writer->writeAttribute(
"role",
"inherits");
3425 r = classe->baseClasses().constBegin();
3427 while (r != classe->baseClasses().constEnd()) {
3429 generateFullName((*r).m_node, classe);
3431 if ((*r).m_access == Access::Protected) {
3432 m_writer->writeCharacters(
" (protected)");
3433 }
else if ((*r).m_access == Access::Private) {
3434 m_writer->writeCharacters(
" (private)");
3436 m_writer->writeCharacters(
3437 Utilities::comma(index++, classe->baseClasses().size()));
3442 m_writer->writeEndElement();
3447 if (!classe->derivedClasses().isEmpty()) {
3448 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3449 m_writer->writeAttribute(
"role",
"inheritedBy");
3450 generateSortedNames(classe, classe->derivedClasses());
3451 m_writer->writeEndElement();
3460 QString logicalModuleVersion;
3464 logicalModuleVersion = collection->logicalModuleVersion();
3466 logicalModuleVersion = qcn->logicalModuleVersion();
3468 QStringList importText;
3469 importText <<
"import " + qcn->logicalModuleName();
3470 if (!logicalModuleVersion.isEmpty())
3471 importText << logicalModuleVersion;
3472 generateSynopsisInfo(
"import", importText.join(
' '));
3475 if (!qcn->since().isEmpty())
3476 generateSynopsisInfo(
"since", formatSince(qcn));
3481 if (!subs.isEmpty()) {
3482 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3483 m_writer->writeAttribute(
"role",
"inheritedBy");
3485 m_writer->writeEndElement();
3494 const Node *otherNode =
nullptr;
3496 QString link = getAutoLink(&a, base, &otherNode);
3498 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3499 m_writer->writeAttribute(
"role",
"inherits");
3500 generateSimpleLink(link, base->name());
3501 m_writer->writeEndElement();
3509 const Node *otherNode =
nullptr;
3511 QString link = getAutoLink(&a, cn, &otherNode);
3513 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3514 m_writer->writeAttribute(
"role",
"nativeType");
3515 generateSimpleLink(link, cn->name());
3516 m_writer->writeEndElement();
3523 case Node::UnspecifiedSafeness:
3524 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3526 case Node::NonReentrant:
3527 generateSynopsisInfo(
"threadsafeness",
"non-reentrant");
3529 case Node::Reentrant:
3530 generateSynopsisInfo(
"threadsafeness",
"reentrant");
3532 case Node::ThreadSafe:
3533 generateSynopsisInfo(
"threadsafeness",
"thread safe");
3536 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3541 if (!node->physicalModuleName().isEmpty())
3542 generateSynopsisInfo(
"module", node->physicalModuleName());
3545 if (classNode && !classNode->groupNames().isEmpty()) {
3546 generateSynopsisInfo(
"groups", classNode->groupNames().join(QLatin1Char(
',')));
3547 }
else if (qcn && !qcn->groupNames().isEmpty()) {
3548 generateSynopsisInfo(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3553 for (
const Node *fnNode : propertyNode->getters()) {
3555 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3556 generateSynopsisInfo(
"getter", funcNode->name());
3559 for (
const Node *fnNode : propertyNode->setters()) {
3561 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3562 generateSynopsisInfo(
"setter", funcNode->name());
3565 for (
const Node *fnNode : propertyNode->resetters()) {
3567 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3568 generateSynopsisInfo(
"resetter", funcNode->name());
3571 for (
const Node *fnNode : propertyNode->notifiers()) {
3573 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3574 generateSynopsisInfo(
"notifier", funcNode->name());
3579 m_writer->writeEndElement();
3585 m_writer->writeStartElement(dbNamespace,
"typedefsynopsis");
3588 m_writer->writeTextElement(dbNamespace,
"typedefname",
3589 enumNode->flagsType()->fullDocumentName());
3592 m_writer->writeEndElement();
3603 return node->name().mid(4);
3604 return node->name();
3608
3609
3610
3611void DocBookGenerator::typified(
const QString &string,
const Node *relative,
bool trailingSpace,
3616 QString pendingWord;
3618 for (
int i = 0; i <= string.size(); ++i) {
3620 if (i != string.size())
3623 QChar lower = ch.toLower();
3624 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
3625 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
3628 if (!pendingWord.isEmpty()) {
3629 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
3630 if (generateType && isProbablyType) {
3632 m_writer->writeCharacters(result);
3641 href = linkForNode(n, relative);
3644 m_writer->writeStartElement(dbNamespace,
"type");
3646 m_writer->writeCharacters(pendingWord);
3648 generateSimpleLink(href, pendingWord);
3649 m_writer->writeEndElement();
3651 result += pendingWord;
3654 pendingWord.clear();
3656 if (ch.unicode() !=
'\0')
3661 if (trailingSpace && string.size()) {
3662 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
3663 result += QLatin1Char(
' ');
3666 m_writer->writeCharacters(result);
3670 bool generateNameLink)
3674 QString name = taggedNode(node);
3676 if (!generateNameLink) {
3677 m_writer->writeCharacters(name);
3681 m_writer->writeStartElement(dbNamespace,
"emphasis");
3682 m_writer->writeAttribute(
"role",
"bold");
3683 generateSimpleLink(linkForNode(node, relative), name);
3684 m_writer->writeEndElement();
3688 bool generateExtra,
bool generateType)
3690 const QString &pname = parameter.name();
3691 const QString &ptype = parameter.type();
3693 if (!pname.isEmpty()) {
3694 typified(ptype, relative,
true, generateType);
3700 if (generateExtra || pname.isEmpty()) {
3701 m_writer->writeStartElement(dbNamespace,
"emphasis");
3702 m_writer->writeCharacters(paramName);
3703 m_writer->writeEndElement();
3706 const QString &pvalue = parameter.defaultValue();
3707 if (generateExtra && !pvalue.isEmpty())
3708 m_writer->writeCharacters(
" = " + pvalue);
3720 const int MaxEnumValues = 6;
3722 if (generateExtra) {
3723 if (
auto extra = CodeMarker::extraSynopsis(node, style); !extra.isEmpty())
3724 m_writer->writeCharacters(extra +
" ");
3728 QString namePrefix {};
3732 namePrefix = taggedNode(node->parent()) +
"::";
3737 case Node::Namespace:
3738 m_writer->writeCharacters(
"namespace ");
3739 m_writer->writeCharacters(namePrefix);
3740 generateSynopsisName(node, relative, generateNameLink);
3743 m_writer->writeCharacters(
"class ");
3744 m_writer->writeCharacters(namePrefix);
3745 generateSynopsisName(node, relative, generateNameLink);
3752 if (!func->isNonvirtual())
3753 m_writer->writeCharacters(QStringLiteral(
"virtual "));
3757 if (style != Section::AllMembers && !func->returnType().isEmpty())
3758 typified(func->returnTypeString(), relative,
true, generateType);
3759 m_writer->writeCharacters(namePrefix);
3760 generateSynopsisName(node, relative, generateNameLink);
3763 m_writer->writeCharacters(QStringLiteral(
"("));
3766 for (
int i = 0; i < parameters
.count(); i++) {
3768 m_writer->writeCharacters(QStringLiteral(
", "));
3769 generateParameter(parameters
.at(i
), relative, generateExtra, generateType);
3772 m_writer->writeCharacters(QStringLiteral(
")"));
3775 if (func->isConst())
3776 m_writer->writeCharacters(QStringLiteral(
" const"));
3782 synopsis += QStringLiteral(
" final");
3784 synopsis += QStringLiteral(
" override");
3786 synopsis += QStringLiteral(
" = 0");
3788 synopsis += QStringLiteral(
" &");
3790 synopsis += QStringLiteral(
" &&");
3791 m_writer->writeCharacters(synopsis);
3793 if (!func->returnType().isEmpty() && func->returnType() !=
"void") {
3794 m_writer->writeCharacters(QStringLiteral(
" : "));
3795 typified(func->returnTypeString(), relative,
false, generateType);
3800 synopsis += QStringLiteral(
" &");
3802 synopsis += QStringLiteral(
" &&");
3803 m_writer->writeCharacters(synopsis);
3807 const auto enume =
static_cast<
const EnumNode *>(node);
3808 m_writer->writeCharacters(QStringLiteral(
"enum "));
3809 m_writer->writeCharacters(namePrefix);
3810 generateSynopsisName(node, relative, generateNameLink);
3816 QStringList documentedItems = enume->doc().enumItemNames();
3817 if (documentedItems.isEmpty()) {
3818 const auto &enumItems = enume->items();
3819 for (
const auto &item : enumItems)
3820 documentedItems << item.name();
3822 const QStringList omitItems = enume->doc().omitEnumItemNames();
3823 for (
const auto &item : omitItems)
3824 documentedItems.removeAll(item);
3826 if (documentedItems.size() > MaxEnumValues) {
3828 const QString last = documentedItems.last();
3829 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
3830 documentedItems +=
"…";
3831 documentedItems += last;
3833 synopsis += documentedItems.join(QLatin1String(
", "));
3835 if (!documentedItems.isEmpty())
3836 synopsis += QLatin1Char(
' ');
3837 synopsis += QLatin1Char(
'}');
3839 m_writer->writeCharacters(synopsis);
3843 auto templateDecl = node->templateDecl();
3845 m_writer->writeCharacters((*templateDecl).to_qstring() + QLatin1Char(
' '));
3847 m_writer->writeCharacters(namePrefix);
3848 generateSynopsisName(node, relative, generateNameLink);
3851 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
3852 m_writer->writeCharacters(
"flags ");
3853 m_writer->writeCharacters(namePrefix);
3854 generateSynopsisName(node, relative, generateNameLink);
3857 const auto property =
static_cast<
const PropertyNode *>(node);
3858 m_writer->writeCharacters(namePrefix);
3859 generateSynopsisName(node, relative, generateNameLink);
3860 m_writer->writeCharacters(
" : ");
3861 typified(property->qualifiedDataType(), relative,
false, generateType);
3864 const auto variable =
static_cast<
const VariableNode *>(node);
3866 generateSynopsisName(node, relative, generateNameLink);
3867 m_writer->writeCharacters(
" : ");
3868 typified(variable->dataType(), relative,
false, generateType);
3870 typified(variable->leftType(), relative,
false, generateType);
3871 m_writer->writeCharacters(
" ");
3872 m_writer->writeCharacters(namePrefix);
3873 generateSynopsisName(node, relative, generateNameLink);
3874 m_writer->writeCharacters(variable->rightType());
3878 m_writer->writeCharacters(namePrefix);
3879 generateSynopsisName(node, relative, generateNameLink);
3892 if (qpn->enumNode() && !enumValue.startsWith(
"%1."_L1.arg(qpn->enumPrefix()))) {
3893 m_writer->writeCharacters(
"%1.%2"_L1.arg(qpn->enumPrefix(), enumValue));
3899 m_writer->writeCharacters(enumValue);
3903 QList<
const Node *> parents;
3905 parents.prepend(node);
3911 parents << relative;
3913 m_writer->writeStartElement(dbNamespace,
"code");
3914 for (
auto parent : parents) {
3915 generateSynopsisName(parent, relative,
true);
3916 m_writer->writeCharacters(
"::");
3919 m_writer->writeCharacters(enumValue);
3920 m_writer->writeEndElement();
3924
3925
3926
3927
3928
3929
3930
3934 QString code = getOverloadedSignalCode(node);
3938 m_writer->writeStartElement(dbNamespace,
"note");
3940 m_writer->writeStartElement(dbNamespace,
"para");
3941 m_writer->writeCharacters(
"Signal ");
3942 m_writer->writeTextElement(dbNamespace,
"emphasis", node->name());
3943 m_writer->writeCharacters(
" is overloaded in this class. To connect to this "
3944 "signal by using the function pointer syntax, Qt "
3945 "provides a convenient helper for obtaining the "
3946 "function pointer as shown in this example:");
3947 m_writer->writeTextElement(dbNamespace,
"code", code);
3948 m_writer->writeEndElement();
3950 m_writer->writeEndElement();
3955
3956
3957
3962 Q_ASSERT(node && !node->name().isEmpty());
3964 m_writer->writeStartElement(dbNamespace,
"note");
3969 m_writer->writeStartElement(dbNamespace,
"para");
3970 m_writer->writeCharacters(
3971 "This function can be invoked via the meta-object system and from QML. See ");
3972 generateSimpleLink(node->url(),
"Q_INVOKABLE");
3973 m_writer->writeCharacters(
".");
3974 m_writer->writeEndElement();
3978 m_writer->writeTextElement(
3979 dbNamespace,
"para",
3980 "This is a private signal. It can be used in signal connections but "
3981 "cannot be emitted by the user.");
3985 QString handler(node->name());
3986 int prefixLocation = handler.lastIndexOf(
'.', -2) + 1;
3987 handler[prefixLocation] = handler[prefixLocation].toTitleCase();
3988 handler.insert(prefixLocation, QLatin1String(
"on"));
3989 m_writer->writeStartElement(dbNamespace,
"para");
3990 m_writer->writeCharacters(
"The corresponding handler is ");
3991 m_writer->writeTextElement(dbNamespace,
"code", handler);
3992 m_writer->writeCharacters(
".");
3993 m_writer->writeEndElement();
4001 const auto *fn =
static_cast<
const FunctionNode *>(node);
4002 auto propertyNodes = fn->associatedProperties();
4003 if (propertyNodes.isEmpty())
4006 for (
const auto propertyNode : std::as_const(propertyNodes)) {
4008 const auto pn =
static_cast<
const PropertyNode *>(propertyNode);
4009 switch (pn->role(fn)) {
4010 case PropertyNode::FunctionRole::Getter:
4011 msg = QStringLiteral(
"Getter function");
4013 case PropertyNode::FunctionRole::Setter:
4014 msg = QStringLiteral(
"Setter function");
4016 case PropertyNode::FunctionRole::Resetter:
4017 msg = QStringLiteral(
"Resetter function");
4019 case PropertyNode::FunctionRole::Notifier:
4020 msg = QStringLiteral(
"Notifier signal");
4025 m_writer->writeStartElement(dbNamespace,
"para");
4026 m_writer->writeCharacters(msg +
" for property ");
4027 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4028 m_writer->writeCharacters(
". ");
4029 m_writer->writeEndElement();
4036 const Node *linkNode;
4038 QString link = getAutoLink(&linkAtom, node, &linkNode);
4039 m_writer->writeStartElement(dbNamespace,
"para");
4040 m_writer->writeCharacters(
"This property supports ");
4041 generateSimpleLink(link,
"QProperty");
4042 m_writer->writeCharacters(
" bindings.");
4043 m_writer->writeEndElement();
4052 m_writer->writeEndElement();
4060 bool closeSupplementarySection =
false;
4064 const QList<Node *> &collective = scn->collective();
4066 bool firstFunction =
true;
4067 for (
const auto *sharedNode : collective) {
4068 if (firstFunction) {
4069 startSectionBegin(sharedNode);
4071 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4072 m_writer->writeAttribute(
"renderas",
"sect2");
4073 writeXmlId(sharedNode);
4076 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4078 generateSynopsis(sharedNode, relative, Section::Details);
4080 if (firstFunction) {
4082 firstFunction =
false;
4084 m_writer->writeEndElement();
4091 startSectionBegin(node);
4093 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4097 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4098 m_writer->writeAttribute(
"renderas",
"sect2");
4100 m_writer->writeEndElement();
4103 startSectionBegin(node);
4105 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4110 Q_ASSERT(m_hasSection);
4119 closeSupplementarySection =
true;
4120 startSection(
"",
"Notes");
4123 generateOverloadedSignal(node);
4129 const auto property =
static_cast<
const PropertyNode *>(node);
4138 m_writer->writeStartElement(dbNamespace,
"para");
4140 m_writer->writeStartElement(dbNamespace,
"emphasis");
4141 m_writer->writeAttribute(
"role",
"bold");
4142 m_writer->writeCharacters(
"Access functions:");
4144 m_writer->writeEndElement();
4146 m_writer->writeEndElement();
4148 generateSectionList(section, node);
4155 m_writer->writeStartElement(dbNamespace,
"para");
4157 m_writer->writeStartElement(dbNamespace,
"emphasis");
4158 m_writer->writeAttribute(
"role",
"bold");
4159 m_writer->writeCharacters(
"Notifier signal:");
4161 m_writer->writeEndElement();
4163 m_writer->writeEndElement();
4165 generateSectionList(notifiers, node);
4169 const auto en =
static_cast<
const EnumNode *>(node);
4171 if (m_qflagsHref.isEmpty()) {
4172 Node *qflags =
m_qdb->findClassNode(QStringList(
"QFlags"));
4174 m_qflagsHref = linkForNode(qflags,
nullptr);
4178 m_writer->writeStartElement(dbNamespace,
"para");
4179 m_writer->writeCharacters(
"The ");
4180 m_writer->writeStartElement(dbNamespace,
"code");
4181 m_writer->writeCharacters(en->flagsType()->name());
4182 m_writer->writeEndElement();
4183 m_writer->writeCharacters(
" type is a typedef for ");
4184 m_writer->writeStartElement(dbNamespace,
"code");
4185 generateSimpleLink(m_qflagsHref,
"QFlags");
4186 m_writer->writeCharacters(
"<" + en->name() +
">. ");
4187 m_writer->writeEndElement();
4188 m_writer->writeCharacters(
"It stores an OR combination of ");
4189 m_writer->writeStartElement(dbNamespace,
"code");
4190 m_writer->writeCharacters(en->name());
4191 m_writer->writeEndElement();
4192 m_writer->writeCharacters(
" values.");
4193 m_writer->writeEndElement();
4198 if (closeSupplementarySection)
4209 bool useObsoleteMembers)
4214 if (!members.isEmpty()) {
4215 bool hasPrivateSignals =
false;
4216 bool isInvokable =
false;
4218 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4220 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4223 NodeVector::ConstIterator m = members.constBegin();
4224 while (m != members.constEnd()) {
4225 if ((*m)->access() == Access::Private) {
4230 m_writer->writeStartElement(dbNamespace,
"listitem");
4232 m_writer->writeStartElement(dbNamespace,
"para");
4235 generateSynopsis(*m, relative, section
.style());
4236 if ((*m)->isFunction()) {
4238 if (fn->isPrivateSignal())
4239 hasPrivateSignals =
true;
4240 else if (fn->isInvokable())
4244 m_writer->writeEndElement();
4246 m_writer->writeEndElement();
4252 m_writer->writeEndElement();
4255 if (hasPrivateSignals)
4262 && !section.inheritedMembers().isEmpty()) {
4263 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4265 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4268 generateSectionInheritedList(section, relative);
4270 m_writer->writeEndElement();
4278 QList<std::pair<Aggregate *,
int>>::ConstIterator p = section.inheritedMembers().constBegin();
4279 while (p != section.inheritedMembers().constEnd()) {
4280 m_writer->writeStartElement(dbNamespace,
"listitem");
4281 m_writer->writeCharacters(QString::number((*p).second) + u' ');
4282 if ((*p).second == 1)
4283 m_writer->writeCharacters(section.singular());
4285 m_writer->writeCharacters(section.plural());
4286 m_writer->writeCharacters(
" inherited from ");
4287 generateSimpleLink(fileName((*p).first) +
'#'
4288 + Generator::cleanRef(section.title().toLower()),
4289 (*p).first->plainFullName(relative));
4295
4296
4297
4301 Q_ASSERT(m_writer ==
nullptr);
4302 m_writer = startDocument(pn);
4304 generateHeader(pn->fullTitle(), pn->subtitle(), pn);
4313
4314
4319 Q_ASSERT(m_writer ==
nullptr);
4320 m_writer = startDocument(qcn);
4323 QString title = qcn->fullTitle();
4325 title.append(
" QML Value Type");
4327 title.append(
" QML Type");
4333 generateHeader(title, qcn->subtitle(), qcn);
4337 startSection(
"details",
"Detailed Description");
4345 for (
const auto §ion : sections.stdQmlTypeDetailsSections()) {
4346 if (!section.isEmpty()) {
4347 startSection(section.title().toLower(), section.title());
4349 for (
const auto &member : section.members())
4350 generateDetailedQmlMember(member, qcn);
4356 generateObsoleteQmlMembers(sections);
4365
4366
4367
4373 QString title{CodeMarker::extraSynopsis(n, Section::Details)};
4374 if (!title.isEmpty())
4378 title += n->element() + QLatin1Char(
'.');
4379 title += n->name() +
" : " + n->dataType();
4384 auto generateQmlMethodTitle = [&](
Node *node) {
4392 if (!scn->name().isEmpty())
4393 heading = scn->name() +
" group";
4395 heading = node->name();
4396 startSection(scn, heading);
4401 const QList<Node *> sharedNodes = scn->collective();
4402 for (
const auto &sharedNode : sharedNodes) {
4403 if (sharedNode->isQmlProperty()) {
4404 auto *qpn =
static_cast<QmlPropertyNode *>(sharedNode);
4406 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4407 m_writer->writeAttribute(
"renderas",
"sect2");
4409 m_writer->writeCharacters(getQmlPropertyTitle(qpn));
4410 m_writer->writeEndElement();
4413 generateDocBookSynopsis(qpn);
4418 startSection(qpn, getQmlPropertyTitle(qpn));
4422 const QList<Node *> &sharedNodes = scn->collective();
4427 for (
const auto &sharedNode : sharedNodes) {
4429 if (!sharedNode->isFunction(Node::QML) && !sharedNode->isQmlProperty()) {
4435 startSectionBegin(sharedNode);
4437 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4438 m_writer->writeAttribute(
"renderas",
"sect2");
4442 if (sharedNode->isFunction(Node::QML))
4443 generateQmlMethodTitle(sharedNode);
4444 else if (sharedNode->isQmlProperty())
4445 m_writer->writeCharacters(
4446 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(sharedNode)));
4452 m_writer->writeEndElement();
4453 generateDocBookSynopsis(sharedNode);
4459 startSectionBegin(refForNode(node));
4462 generateQmlMethodTitle(node);
4463 else if (node->isQmlProperty())
4464 m_writer->writeCharacters(
4465 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(node)));
4470 startSectionBegin(node);
4471 generateQmlMethodTitle(node);
4485
4486
4493 if (!node->url().isNull())
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4538 generateCppReferencePage(
static_cast<
Aggregate *>(node));
4548 auto *aggregate =
static_cast<
Aggregate *>(node);
4549 for (
auto c : aggregate->childNodes()) {
4550 if (node->isPageNode() && !node->isPrivate())
4551 generateDocumentation(c);
4562 Q_ASSERT(m_writer ==
nullptr);
4563 m_writer = startDocument(aggregate);
4566 generateHeader(aggregate->plainFullName(),
"", aggregate);
4571 if (!aggregate
->doc().isEmpty()) {
4572 startSection(
"details",
"Detailed Description");
4574 generateBody(aggregate);
4583 for (
const auto §ion : std::as_const(*detailsSections)) {
4584 if (section.isEmpty())
4587 startSection(section.title().toLower(), section.title());
4589 const QList<Node *> &members = section.members();
4590 for (
const auto &member : members) {
4591 if (!member->isPrivate()) {
4592 if (!member->isClassNode()) {
4593 generateDetailedMember(member, aggregate);
4595 startSectionBegin();
4596 generateFullName(member, aggregate);
4599 generateBrief(member);
4614
4615
4620 Q_ASSERT(m_writer ==
nullptr);
4621 m_writer = startDocument(cn);
4624 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4641 if (!nmm.isEmpty()) {
4642 startSection(
"namespaces",
"Namespaces");
4643 generateAnnotatedList(cn, nmm.values(),
"namespaces");
4647 if (!nmm.isEmpty()) {
4648 startSection(
"classes",
"Classes");
4649 generateAnnotatedList(cn, nmm.values(),
"classes");
4655 bool generatedTitle =
false;
4657 startSection(
"details",
"Detailed Description");
4658 generatedTitle =
true;
4663 !cn
->doc().body().isEmpty() ||
4665 !cn
->doc().alsoList().empty() ||
4668 writeAnchor(
"details");
4674 if (!cn->noAutoList() && (cn->isGroup() || cn->isQmlModule()))
4675 generateAnnotatedList(cn, cn->members(),
"members", AutoSection);
4686
4687
4688
4689
4694 QString name = cn->name().toLower();
4695 name.replace(QChar(
' '), QString(
"-"));
4696 QString filename = cn->tree()->physicalModuleName() +
"-" + name +
"." + fileExtension();
4699 Q_ASSERT(m_writer ==
nullptr);
4700 m_writer = startGenericDocument(cn, filename);
4703 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4709 m_writer->writeStartElement(dbNamespace,
"para");
4710 m_writer->writeCharacters(
"Each function or type documented here is related to a class or "
4711 "namespace that is documented in a different module. The reference "
4712 "page for that class or namespace will link to the function or type "
4714 m_writer->writeEndElement();
4717 const QList<Node *> members = cn->members();
4718 for (
const auto &member : members)
4719 generateDetailedMember(member, cnc);
4732 m_writer->writeStartElement(dbNamespace,
"link");
4733 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(node));
4734 m_writer->writeAttribute(xlinkNamespace,
"role", targetType(node));
4735 m_writer->writeCharacters(node->fullName(relative));
4736 m_writer->writeEndElement();
4740 const Node *actualNode)
4742 Q_ASSERT(apparentNode);
4743 Q_ASSERT(actualNode);
4746 m_writer->writeStartElement(dbNamespace,
"link");
4747 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(actualNode));
4748 m_writer->writeAttribute(
"role", targetType(actualNode));
4749 m_writer->writeCharacters(fullName);
4750 m_writer->writeEndElement();
#define ATOM_FORMATTING_TELETYPE
#define ATOM_LIST_LOWERALPHA
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_LIST_UPPERALPHA
#define ATOM_LIST_LOWERROMAN
#define ATOM_FORMATTING_SUBSCRIPT
#define ATOM_FORMATTING_BOLD
#define ATOM_FORMATTING_TRADEMARK
#define ATOM_FORMATTING_ITALIC
#define ATOM_LIST_UPPERROMAN
#define ATOM_FORMATTING_LINK
#define ATOM_FORMATTING_SUPERSCRIPT
#define ATOM_FORMATTING_UICONTROL
#define ATOM_FORMATTING_PARAMETER
The Atom class is the fundamental unit for representing documents internally.
AtomType type() const
Return the type of this atom.
const Atom * next() const
Return the next atom in the atom list.
The ClassNode represents a C++ class.
virtual Atom::AtomType atomType() const
A class for holding the members of a collection of doc pages.
const NodeList & members() const
NodeMap getMembers(Node::NodeType type) const
Returns a map containing this collection node's member nodes with a specified node type.
bool wasSeen() const override
Returns the seen flag data member of this node if it is a NamespaceNode or a CollectionNode.
void generatePageNode(PageNode *pn)
Generate the DocBook page for an entity that doesn't map to any underlying parsable C++ or QML elemen...
void generateQmlTypePage(QmlTypeNode *qcn)
Generate the DocBook page for a QML type.
void generateAlsoList(const Node *node) override
void generateQmlRequisites(const QmlTypeNode *qcn)
Lists the required imports and includes.
void generateSortedQmlNames(const Node *base, const NodeList &subs)
void initializeGenerator() override
Initializes the DocBook output generator's data structures from the configuration (Config).
void generateExampleFilePage(const Node *en, ResolvedFile resolved_file, CodeMarker *=nullptr) override
Generate a file with the contents of a C++ or QML source file.
bool generateText(const Text &text, const Node *relative) override
Generate the documentation for relative.
void generateCppReferencePage(Node *node)
Generate a reference page for the C++ class, namespace, or header file documented in node.
void generateHeader(const QString &title, const QString &subtitle, const Node *node)
Generate the DocBook header for the file, including the abstract.
DocBookGenerator(FileResolver &file_resolver)
bool generateThreadSafeness(const Node *node)
Generates text that explains how threadsafe and/or reentrant node is.
void generateCollectionNode(CollectionNode *cn)
Generate the HTML page for a group, module, or QML module.
QString format() override
void generateDocBookSynopsis(const Node *node)
Generate the metadata for the given node in DocBook.
void generateGenericCollectionPage(CollectionNode *cn)
Generate the HTML page for a generic collection.
void generateList(const Node *relative, const QString &selector, Qt::SortOrder sortOrder=Qt::AscendingOrder)
void generateBody(const Node *node)
Generate the body of the documentation from the qdoc comment found with the entity represented by the...
qsizetype generateAtom(const Atom *atom, const Node *relative, CodeMarker *) override
Generate DocBook from an instance of Atom.
void generateProxyPage(Aggregate *aggregate)
bool generateStatus(const Node *node)
void generateRequisites(const Aggregate *inner)
Lists the required imports and includes.
void generateSortedNames(const ClassNode *cn, const QList< RelatedClass > &rc)
void generateDocumentation(Node *node) override
Recursive writing of DocBook files from the root node.
void generateGroupReferenceText(const Node *node)
Return a string representing a text that exposes information about the groups that the node is part o...
void generateAddendum(const Node *node, Generator::Addendum type, CodeMarker *marker, bool generateNote) override
Generates an addendum note of type type for node.
QString fileExtension() const override
Returns "xml" for this subclass of Generator.
bool generateSince(const Node *node)
const Location & location() const
Returns the starting location of a qdoc comment.
static void quoteFromFile(const Location &location, Quoter "er, ResolvedFile resolved_file)
const Text & body() const
Text briefText(bool inclusive=false) const
const TypedefNode * flagsType() const
Encapsulate the logic that QDoc uses to find files whose path is provided by the user and that are re...
This node is used to represent any kind of function being documented.
bool isMacroWithoutParams() const
bool isPrivateSignal() const
const Parameters & parameters() const
bool isDefault() const override
Returns true if the QML property node is marked as default.
bool isPureVirtual() const
bool isMacro() const override
returns true if either FunctionNode::isMacroWithParams() or FunctionNode::isMacroWithoutParams() retu...
bool hasAssociatedProperties() const
bool generateComparisonCategory(const Node *node, CodeMarker *marker=nullptr)
static bool hasExceptions(const Node *node, NodeList &reentrant, NodeList &threadsafe, NodeList &nonreentrant)
void generateEnumValuesForQmlProperty(const Node *node, CodeMarker *marker)
FileResolver & file_resolver
static void setQmlTypeContext(QmlTypeNode *t)
const Atom * generateAtomList(const Atom *atom, const Node *relative, CodeMarker *marker, bool generate, int &numGeneratedAtoms)
bool generateComparisonList(const Node *node)
Generates a list of types that compare to node with the comparison category that applies for the rela...
void unknownAtom(const Atom *atom)
static bool matchAhead(const Atom *atom, Atom::AtomType expectedAtomType)
virtual int skipAtoms(const Atom *atom, Atom::AtomType type) const
bool m_threeColumnEnumValueTable
virtual void initializeGenerator()
Updates the generator's m_showInternal from the Config.
void initializeTextOutput()
Resets the variables used during text output.
This class represents a C++ namespace.
NamespaceNode * docNode() const
Returns a pointer to the NamespaceNode that represents where the namespace documentation is actually ...
bool isGenericCollection() const
Returns true if the node type is Collection.
bool isExternalPage() const
Returns true if the node type is ExternalPage.
const Doc & doc() const
Returns a reference to the node's Doc data member.
bool isQmlNode() const
Returns true if this node's Genus value is QML.
bool isGroup() const
Returns true if the node type is Group.
virtual bool docMustBeGenerated() const
This function is called to perform a test to decide if the node must have documentation generated.
bool isPrivate() const
Returns true if this node's access is Private.
NodeType
An unsigned char value that identifies an object as a particular subclass of Node.
bool isNamespace() const
Returns true if the node type is Namespace.
bool isTypedef() const
Returns true if the node type is Typedef.
bool isQmlBasicType() const
Returns true if the node type is QmlBasicType.
bool isFunction(Genus g=DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
bool isSharedCommentNode() const
Returns true if the node type is SharedComment.
virtual bool isInternal() const
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
bool isHeader() const
Returns true if the node type is HeaderFile.
virtual bool isPageNode() const
Returns true if this node represents something that generates a documentation page.
bool isEnumType() const
Returns true if the node type is Enum.
virtual bool isTextPageNode() const
Returns true if the node is a PageNode but not an Aggregate.
Aggregate * parent() const
Returns the node's parent pointer.
bool isVariable() const
Returns true if the node type is Variable.
virtual bool isDeprecated() const
Returns true if this node's status is Deprecated.
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
NodeType nodeType() const
Returns this node's type.
static bool nodeNameLessThan(const Node *first, const Node *second)
Returns true if the node n1 is less than node n2.
const Location & location() const
If this node's definition location is empty, this function returns this node's declaration location.
bool isProxyNode() const
Returns true if the node type is Proxy.
Access access() const
Returns the node's Access setting, which can be Public, Protected, or Private.
ThreadSafeness threadSafeness() const
Returns the thread safeness value for whatever this node represents.
Genus
An unsigned char value that specifies whether the Node represents a C++ element, a QML element,...
virtual bool isMarkedReimp() const
Returns true if the FunctionNode is marked as a reimplemented function.
bool isProperty() const
Returns true if the node type is Property.
bool isModule() const
Returns true if the node type is Module.
bool isClass() const
Returns true if the node type is Class.
virtual bool isPropertyGroup() const
Returns true if the node is a SharedCommentNode for documenting multiple C++ properties or multiple Q...
Genus genus() const
Returns this node's Genus.
ThreadSafeness
An unsigned char that specifies the degree of thread-safeness of the element.
bool isSharingComment() const
This function returns true if the node is sharing a comment with other nodes.
bool hasDoc() const
Returns true if this node is documented, or it represents a documented node read from the index ('had...
LinkType
An unsigned char value that probably should be moved out of the Node base class.
bool isRelatedNonmember() const
Returns true if this is a related nonmember of something.
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
virtual bool isCollectionNode() const
Returns true if this is an instance of CollectionNode.
static bool nodeSortKeyOrNameLessThan(const Node *n1, const Node *n2)
Returns true if node n1 is less than node n2 when comparing the sort keys, defined with.
bool isQmlModule() const
Returns true if the node type is QmlModule.
bool isExample() const
Returns true if the node type is Example.
bool isIndexNode() const
Returns true if this node was created from something in an index file.
Status status() const
Returns the node's status value.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.
A PageNode is a Node that generates a documentation page.
bool noAutoList() const
Returns the value of the no auto-list flag.
The Parameter class describes one function parameter.
A class for parsing and managing a function parameter list.
const Parameter & at(int i) const
This class describes one instance of using the Q_PROPERTY macro.
const NodeList & getters() const
const NodeList & resetters() const
const NodeList & setters() const
PropertyType propertyType() const
const NodeList & notifiers() const
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
NodeMapMap & getFunctionIndex()
Returns the function index.
TextToNodeMap & getLegaleseTexts()
Returns a reference to the collection of legalese texts.
NodeMultiMap & getAttributions()
Returns a reference to the multimap of attribution nodes.
NodeMultiMap & getQmlTypesWithObsoleteMembers()
Returns a reference to the map of QML types with obsolete members.
NodeMultiMap & getObsoleteQmlTypes()
Returns a reference to the map of obsolete QML types.
static QDocDatabase * qdocDB()
Creates the singleton.
NodeMultiMap & getQmlTypes()
Returns a reference to the multimap of QML types.
NodeMultiMap & getClassesWithObsoleteMembers()
Returns a reference to the map of C++ classes with obsolete members.
NodeMultiMap & getQmlValueTypes()
Returns a reference to the map of QML basic types.
NodeMultiMap & getCppClasses()
Returns a reference to the map of all C++ classes.
NodeMultiMap & getNamespaces()
Returns a reference to the namespace map.
NodeMultiMap & getExamples()
Returns a reference to the multimap of example nodes.
NodeMultiMap & getObsoleteClasses()
Returns a reference to the map of obsolete C++ clases.
void mergeCollections(Node::NodeType type, CNMap &cnm, const Node *relative)
Finds all the collection nodes of the specified type and merges them into the collection node map cnm...
void mergeCollections(CollectionNode *c)
Finds all the collection nodes with the same name and type as c and merges their members into the mem...
const CNMap & groups()
Returns a const reference to the collection of all group nodes in the primary tree.
bool isDefault() const override
Returns true if the QML property node is marked as default.
bool isReadOnly() const
Returns true if this QML property node is marked as a read-only property.
bool isRequired()
Returns true if this QML property is marked with \required or the corresponding C++ property uses the...
bool isReadOnly()
Returns true if this QML property or attached property is read-only.
bool isAttached() const override
Returns true if the QML property or QML method node is marked as attached.
ClassNode * classNode() override
If this is a QmlTypeNode, this function returns the pointer to the C++ ClassNode that this QML type r...
bool isInternal() const override
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
static void subclasses(const Node *base, NodeList &subs)
Loads the list subs with the nodes of all the subclasses of base.
QmlTypeNode * qmlBaseNode() const override
If this Aggregate is a QmlTypeNode, this function returns a pointer to the QmlTypeNode that is its ba...
CollectionNode * logicalModule() const override
If this is a QmlTypeNode, a pointer to its QML module is returned, which is a pointer to a Collection...
A class for containing the elements of one documentation section.
const NodeVector & obsoleteMembers() const
void appendMembers(const NodeVector &nv)
const NodeVector & members() const
A class for creating vectors of collections for documentation.
Aggregate * aggregate() const
Sections(Aggregate *aggregate)
This constructor builds the vectors of sections based on the type of the aggregate node.
SectionVector & stdDetailsSections()
SectionVector & stdCppClassDetailsSections()
bool hasObsoleteMembers(SectionPtrVector *summary_spv, SectionPtrVector *details_spv) const
Returns true if any sections in this object contain obsolete members.
const Atom * firstAtom() const
Text & operator=(const Text &text)
const Atom * lastAtom() const
bool isStatic() const override
Returns true if the FunctionNode represents a static function.
static bool isThreeColumnEnumValueTable(const Atom *atom)
Determines whether the list atom should be shown with three columns (constant-value-description).
static Node::NodeType typeFromString(const Atom *atom)
Returns the type of this atom as an enumeration.
static bool isOneColumnValueTable(const Atom *atom)
Determines whether the list atom should be shown with just one column (value).
static void rewritePropertyBrief(const Atom *atom, const Node *relative)
Rewrites the brief of this node depending on its first word.
static int hOffset(const Node *node)
Header offset depending on the type of the node.
static bool hasBrief(const Node *node)
Do not display.
XmlGenerator(FileResolver &file_resolver)
static const QRegularExpression m_funcLeftParen
#define CONFIG_DOCBOOKEXTENSIONS
#define CONFIG_DESCRIPTION
#define CONFIG_EXAMPLESINSTALLPATH
#define CONFIG_NATURALLANGUAGE
#define CONFIG_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.