31#include <QtCore/qlist.h>
32#include <QtCore/qmap.h>
33#include <QtCore/quuid.h>
34#include <QtCore/qurl.h>
35#include <QtCore/qregularexpression.h>
36#include <QtCore/qversionnumber.h>
42using namespace Qt::StringLiterals;
44static const char dbNamespace[] =
"http://docbook.org/ns/docbook";
52 m_writer->writeCharacters(
"\n");
60 m_writer->writeAttribute(
"xml:id", registerRef(id,
true));
73 QString id = Generator::cleanRef(refForNode(node),
true);
75 m_writer->writeAttribute(
"xml:id", id);
82 m_writer->writeStartElement(dbNamespace,
"section");
85 m_writer->writeStartElement(dbNamespace,
"title");
90 m_writer->writeStartElement(dbNamespace,
"section");
93 m_writer->writeStartElement(dbNamespace,
"title");
98 m_writer->writeEndElement();
104 startSectionBegin(id);
105 m_writer->writeCharacters(title);
111 startSectionBegin(node);
112 m_writer->writeCharacters(title);
119 startSection(
"", title);
124 m_writer->writeEndElement();
133 m_writer->writeEmptyElement(dbNamespace,
"anchor");
139
140
141
146 m_config = &Config::instance();
152 if (m_projectDescription.isEmpty() && !m_project.isEmpty())
153 m_projectDescription = m_project + QLatin1String(
" Reference Documentation");
156 if (m_naturalLanguage.isEmpty())
157 m_naturalLanguage = QLatin1String(
"en");
161 m_config->get(format() + Config::dot +
"usedocbookextensions").asBool();
162 m_useITS = m_config->get(format() + Config::dot +
"its").asBool();
171
172
179
180
181
182
197 QString rewritten = code;
198 static const QRegularExpression re(
"(<@[^>&]*>)|(<\\/@[^&>]*>)");
199 rewritten.replace(re,
"");
204
205
211 qsizetype skipAhead = 0;
212 Genus genus = Genus::DontCare;
221 const Node *node =
nullptr;
222 QString link = getAutoLink(atom, relative, &node, genus);
227 if (link.isEmpty()) {
228 m_writer->writeCharacters(atom->string());
230 beginLink(link, node, relative);
235 m_writer->writeCharacters(atom->string());
245 m_writer->writeStartElement(dbNamespace,
"para");
251 m_writer->writeEndElement();
261 m_writer->writeCharacters(plainCode(atom->string()));
263 m_writer->writeTextElement(dbNamespace,
"code", plainCode(atom->string()));
265 case Atom::CaptionLeft:
266 m_writer->writeStartElement(dbNamespace,
"title");
270 m_writer->writeEndElement();
274 m_writer->writeStartElement(dbNamespace,
"programlisting");
275 m_writer->writeAttribute(
"language",
"qml");
277 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
278 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
279 m_writer->writeEndElement();
283 m_writer->writeStartElement(dbNamespace,
"programlisting");
284 m_writer->writeAttribute(
"language",
"cpp");
286 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
287 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
288 m_writer->writeEndElement();
292 m_writer->writeStartElement(dbNamespace,
"programlisting");
293 m_writer->writeAttribute(
"language",
"cpp");
294 m_writer->writeAttribute(
"role",
"bad");
296 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
297 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
298 m_writer->writeEndElement();
307 case Atom::FootnoteLeft:
308 m_writer->writeStartElement(dbNamespace,
"footnote");
310 m_writer->writeStartElement(dbNamespace,
"para");
313 case Atom::FootnoteRight:
314 m_writer->writeEndElement();
317 m_writer->writeEndElement();
325 m_writer->writeStartElement(dbNamespace,
"emphasis");
326 m_writer->writeAttribute(
"role",
"bold");
328 m_writer->writeStartElement(dbNamespace,
"emphasis");
330 m_writer->writeStartElement(dbNamespace,
"emphasis");
331 m_writer->writeAttribute(
"role",
"underline");
333 m_writer->writeStartElement(dbNamespace,
"subscript");
335 m_writer->writeStartElement(dbNamespace,
"superscript");
338 m_writer->writeStartElement(dbNamespace,
"code");
340 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
343 m_writer->writeAttribute(
"role",
"parameter");
347 m_writer->writeStartElement(dbNamespace,
"guilabel");
349 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
351 m_writer->writeStartElement(dbNamespace,
352 appendTrademark(atom->find(Atom::FormattingRight)) ?
353 "trademark" :
"phrase");
355 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
357 m_writer->writeStartElement(dbNamespace,
"phrase");
359 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
361 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
374 m_writer->writeEndElement();
377 m_inTeletype =
false;
380 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
384 if (
const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group))
385 generateList(cn, atom->string(), Generator::sortOrder(atom->strings().last()));
388 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
389 bool hasGeneratedSomething =
false;
390 if (atom->string() == QLatin1String(
"annotatedclasses")
391 || atom->string() == QLatin1String(
"attributions")
392 || atom->string() == QLatin1String(
"namespaces")) {
393 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedclasses")
397 generateAnnotatedList(relative, things.values(), atom->string(), Auto, sortOrder);
398 hasGeneratedSomething = !things.isEmpty();
399 }
else if (atom->string() == QLatin1String(
"annotatedexamples")
400 || atom->string() == QLatin1String(
"annotatedattributions")) {
401 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedexamples")
404 generateAnnotatedLists(relative, things, atom->string());
405 hasGeneratedSomething = !things.isEmpty();
406 }
else if (atom->string() == QLatin1String(
"classes")
407 || atom->string() == QLatin1String(
"qmlbasictypes")
408 || atom->string() == QLatin1String(
"qmlvaluetypes")
409 || atom->string() == QLatin1String(
"qmltypes")) {
410 const NodeMultiMap things = atom->string() == QLatin1String(
"classes")
412 : (atom->string() == QLatin1String(
"qmlvaluetypes")
413 || atom->string() == QLatin1String(
"qmlbasictypes"))
416 generateCompactList(relative, things,
true, QString(), atom->string());
417 hasGeneratedSomething = !things.isEmpty();
418 }
else if (atom->string().contains(
"classes ")) {
419 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
422 hasGeneratedSomething = !things.isEmpty();
423 generateCompactList(relative, things,
true, rootName, atom->string());
424 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
425 QString moduleName = atom->string().mid(idx + 8).trimmed();
428 if (
const CollectionNode *cn = qdb->getCollectionNode(moduleName, moduleType)) {
430 switch (moduleType) {
436 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
442 generateAnnotatedList(relative, cn->members(), atom->string(), Auto, sortOrder);
446 if (!map.isEmpty()) {
447 generateAnnotatedList(relative, map.values(), atom->string(), Auto, sortOrder);
448 hasGeneratedSomething =
true;
451 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
454 }
else if (atom->string().startsWith(
"obsolete")) {
455 QString prefix = atom->string().contains(
"cpp") ? QStringLiteral(
"Q") : QString();
456 const NodeMultiMap &things = atom->string() == QLatin1String(
"obsoleteclasses")
458 : atom->string() == QLatin1String(
"obsoleteqmltypes")
460 : atom->string() == QLatin1String(
"obsoletecppmembers")
463 generateCompactList(relative, things,
false, prefix, atom->string());
464 hasGeneratedSomething = !things.isEmpty();
465 }
else if (atom->string() == QLatin1String(
"functionindex")) {
466 generateFunctionIndex(relative);
468 }
else if (atom->string() == QLatin1String(
"legalese")) {
469 generateLegaleseList(relative);
471 }
else if (atom->string() == QLatin1String(
"overviews")
472 || atom->string() == QLatin1String(
"cpp-modules")
473 || atom->string() == QLatin1String(
"qml-modules")
474 || atom->string() == QLatin1String(
"related")) {
475 generateList(relative, atom->string());
476 hasGeneratedSomething =
true;
479 generateAnnotatedList(cn, cn->members(), atom->string(), ItemizedList, sortOrder);
480 hasGeneratedSomething =
true;
485 if (!hasGeneratedSomething && !m_inPara) {
486 m_writer->writeEmptyElement(dbNamespace,
"para");
518 m_writer->writeStartElement(dbNamespace,
"figure");
525 generateAtom(current, relative,
nullptr);
530 generateAtom(current, relative,
nullptr);
536 generateAtom(current, relative,
nullptr);
540 m_closeFigureWrapper =
true;
551 m_writer->writeStartElement(dbNamespace,
"figure");
558 generateAtom(current, relative,
nullptr);
563 generateAtom(current, relative,
nullptr);
569 generateAtom(current, relative,
nullptr);
573 m_closeFigureWrapper =
true;
596 m_writer->writeStartElement(dbNamespace, tag);
599 auto maybe_resolved_file{
file_resolver.resolve(atom->string())};
600 if (!maybe_resolved_file) {
602 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
604 m_writer->writeStartElement(dbNamespace,
"textobject");
606 m_writer->writeStartElement(dbNamespace,
"para");
607 m_writer->writeTextElement(dbNamespace,
"emphasis",
608 "[Missing image " + atom->string() +
"]");
609 m_writer->writeEndElement();
611 m_writer->writeEndElement();
615 QString file_name{QFileInfo{file.get_path()}.fileName()};
618 Config::copyFile(relative->doc().location(), file.get_path(), file_name,
619 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
623 m_writer->writeTextElement(dbNamespace,
"alt", atom->next()->string());
627 m_writer->writeStartElement(dbNamespace,
"imageobject");
629 m_writer->writeEmptyElement(dbNamespace,
"imagedata");
630 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
632 m_writer->writeAttribute(
"fileref", imgPath);
634 m_writer->writeEndElement();
638 setImageFileName(relative, imgPath);
641 m_writer->writeEndElement();
645 if (m_closeFigureWrapper) {
646 m_writer->writeEndElement();
648 m_closeFigureWrapper =
false;
656 QString admonType = atom->typeString().toLower();
659 m_writer->writeStartElement(dbNamespace, admonType);
661 m_writer->writeStartElement(dbNamespace,
"para");
664 case Atom::ImportantRight:
665 case Atom::NoteRight:
666 case Atom::WarningRight:
667 m_writer->writeEndElement();
670 m_writer->writeEndElement();
678 const Node *node =
nullptr;
679 QString link = getLink(atom, relative, &node);
680 beginLink(link, node, relative);
684 const Node *node =
static_cast<
const Node*>(Utilities::nodeForString(atom->string()));
685 beginLink(linkForNode(node, relative), node, relative);
695 m_writer->writeEndElement();
701 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
704 m_writer->writeStartElement(dbNamespace,
"variablelist");
707 m_writer->writeStartElement(dbNamespace,
"informaltable");
709 m_writer->writeStartElement(dbNamespace,
"thead");
711 m_writer->writeStartElement(dbNamespace,
"tr");
713 m_writer->writeTextElement(dbNamespace,
"th",
"Constant");
719 m_writer->writeTextElement(dbNamespace,
"th",
"Value");
724 m_writer->writeTextElement(dbNamespace,
"th",
"Description");
728 m_writer->writeEndElement();
730 m_writer->writeEndElement();
733 m_writer->writeStartElement(dbNamespace,
"orderedlist");
735 if (atom->next() !=
nullptr && atom->next()->string().toInt() > 1)
736 m_writer->writeAttribute(
"startingnumber", atom->next()->string());
739 m_writer->writeAttribute(
"numeration",
"upperalpha");
741 m_writer->writeAttribute(
"numeration",
"loweralpha");
743 m_writer->writeAttribute(
"numeration",
"upperroman");
745 m_writer->writeAttribute(
"numeration",
"lowerroman");
747 m_writer->writeAttribute(
"numeration",
"arabic");
757 m_writer->writeStartElement(dbNamespace,
"varlistentry");
759 m_writer->writeStartElement(dbNamespace,
"item");
761 std::pair<QString,
int> pair = getAtomListValue(atom);
762 skipAhead = pair.second;
764 m_writer->writeStartElement(dbNamespace,
"tr");
766 m_writer->writeStartElement(dbNamespace,
"td");
768 m_writer->writeStartElement(dbNamespace,
"para");
770 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
771 generateEnumValue(pair.first, relative);
772 m_writer->writeEndElement();
774 m_writer->writeEndElement();
778 const auto enume =
static_cast<
const EnumNode *>(relative);
779 QString itemValue = enume->itemValue(atom
->next()->string());
781 m_writer->writeStartElement(dbNamespace,
"td");
782 if (itemValue.isEmpty())
783 m_writer->writeCharacters(
"?");
785 m_writer->writeStartElement(dbNamespace,
"code");
787 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
788 m_writer->writeCharacters(itemValue);
789 m_writer->writeEndElement();
791 m_writer->writeEndElement();
799 m_writer->writeEndElement();
805 m_writer->writeEndElement();
812 m_inListItemLineOpen =
false;
814 m_writer->writeStartElement(dbNamespace,
"listitem");
816 m_writer->writeStartElement(dbNamespace,
"para");
821 m_writer->writeEmptyElement(dbNamespace,
"td");
823 m_inListItemLineOpen =
false;
825 m_writer->writeStartElement(dbNamespace,
"td");
827 m_inListItemLineOpen =
true;
831 m_writer->writeStartElement(dbNamespace,
"listitem");
840 m_writer->writeEndElement();
843 m_writer->writeEndElement();
845 m_writer->writeEndElement();
848 if (m_inListItemLineOpen) {
849 m_writer->writeEndElement();
851 m_inListItemLineOpen =
false;
853 m_writer->writeEndElement();
856 m_writer->writeEndElement();
861 case Atom::ListRight:
867 m_writer->writeEndElement();
874 m_writer->writeStartElement(dbNamespace,
"para");
880 m_writer->writeEndElement();
885 case Atom::QuotationLeft:
886 m_writer->writeStartElement(dbNamespace,
"blockquote");
887 m_inBlockquote =
true;
889 case Atom::QuotationRight:
890 m_writer->writeEndElement();
892 m_inBlockquote =
false;
895 m_writer->device()->write(atom->string().toUtf8());
901 currentSectionLevel = atom->string().toInt() +
hOffset(relative
);
903 if (currentSectionLevel > 1) {
906 while (!sectionLevels.empty() && sectionLevels.top() >= currentSectionLevel) {
908 m_writer->writeEndElement();
912 sectionLevels.push(currentSectionLevel);
914 m_writer->writeStartElement(dbNamespace,
"section");
915 writeXmlId(Tree::refForAtom(atom));
928 generateAtom(atom->next(), relative,
nullptr);
929 generateAtom(atom->next()->next(), relative,
nullptr);
930 generateAtom(atom->next()->next()->next(), relative,
nullptr);
932 m_closeSectionAfterGeneratedList =
true;
939 m_writer->writeTextElement(dbNamespace,
"title",
"");
948 if (currentSectionLevel > 1) {
949 m_writer->writeStartElement(dbNamespace,
"title");
955 if (currentSectionLevel > 1) {
956 m_writer->writeEndElement();
961 case Atom::SidebarLeft:
962 m_writer->writeStartElement(dbNamespace,
"sidebar");
964 case Atom::SidebarRight:
965 m_writer->writeEndElement();
972 m_writer->writeCharacters(atom->string());
975 std::pair<QString, QString> pair = getTableWidthAttr(atom);
976 QString attr = pair.second;
977 QString width = pair.first;
980 m_writer->writeEndElement();
985 m_tableHeaderAlreadyOutput =
false;
987 m_writer->writeStartElement(dbNamespace,
"informaltable");
988 m_writer->writeAttribute(
"style", attr);
989 if (!width.isEmpty())
990 m_writer->writeAttribute(
"width", width);
993 case Atom::TableRight:
994 m_tableWidthAttr = {
"",
""};
995 m_writer->writeEndElement();
1004 if (m_tableHeaderAlreadyOutput) {
1007 m_writer->writeEndElement();
1010 const QString &attr = m_tableWidthAttr.second;
1011 const QString &width = m_tableWidthAttr.first;
1013 m_writer->writeStartElement(dbNamespace,
"informaltable");
1014 m_writer->writeAttribute(
"style", attr);
1015 if (!width.isEmpty())
1016 m_writer->writeAttribute(
"width", width);
1019 m_tableHeaderAlreadyOutput =
true;
1025 id = Utilities::asAsciiPrintable(next->string());
1030 m_writer->writeStartElement(dbNamespace,
"thead");
1032 m_writer->writeStartElement(dbNamespace,
"tr");
1038 m_closeTableCell =
true;
1039 m_writer->writeStartElement(dbNamespace,
"td");
1045 if (m_closeTableCell) {
1046 m_closeTableCell =
false;
1047 m_writer->writeEndElement();
1051 m_writer->writeEndElement();
1055 m_writer->writeStartElement(dbNamespace,
"tr");
1058 m_writer->writeEndElement();
1070 bool hasTarget {
false};
1072 id = Utilities::asAsciiPrintable(atom
->next()->string());
1077 m_writer->writeStartElement(dbNamespace,
"tr");
1080 if (atom->string().isEmpty()) {
1081 m_writer->writeAttribute(
"valign",
"top");
1086 QStringList args = atom->string().split(
"\"", Qt::SkipEmptyParts);
1089 const int nArgs = args.size();
1094 QStringLiteral(
"Error when parsing attributes for the table: got \"%1\"")
1095 .arg(atom->string()));
1097 for (
int i = 0; i + 1 < nArgs; i += 2) {
1100 const QString &attr = args.at(i).chopped(1);
1103 writeXmlId(args.at(i + 1));
1105 m_writer->writeAttribute(attr, args.at(i + 1));
1121 m_closeTableRow =
true;
1122 m_writer->writeEndElement();
1128 if (m_closeTableRow) {
1129 m_closeTableRow =
false;
1130 m_writer->writeEndElement();
1134 m_writer->writeEndElement();
1137 case Atom::TableItemLeft:
1138 m_writer->writeStartElement(dbNamespace, m_inTableHeader ?
"th" :
"td");
1140 for (
int i = 0; i < atom->count(); ++i) {
1141 const QString &p = atom->string(i);
1142 if (p.contains(
'=')) {
1143 QStringList lp = p.split(QLatin1Char(
'='));
1144 m_writer->writeAttribute(lp.at(0), lp.at(1));
1146 QStringList spans = p.split(QLatin1Char(
','));
1147 if (spans.size() == 2) {
1148 if (spans.at(0) !=
"1")
1149 m_writer->writeAttribute(
"colspan", spans.at(0).trimmed());
1150 if (spans.at(1) !=
"1")
1151 m_writer->writeAttribute(
"rowspan", spans.at(1).trimmed());
1158 case Atom::TableItemRight:
1159 m_writer->writeEndElement();
1171 QString nextId = Utilities::asAsciiPrintable(
1173 QString ownId = Utilities::asAsciiPrintable(atom->string());
1174 if (nextId == ownId)
1178 writeAnchor(Utilities::asAsciiPrintable(atom->string()));
1180 case Atom::UnhandledFormat:
1181 m_writer->writeStartElement(dbNamespace,
"emphasis");
1182 m_writer->writeAttribute(
"role",
"bold");
1183 m_writer->writeCharacters(
"<Missing DocBook>");
1184 m_writer->writeEndElement();
1186 case Atom::UnknownCommand:
1187 m_writer->writeStartElement(dbNamespace,
"emphasis");
1188 m_writer->writeAttribute(
"role",
"bold");
1190 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1191 m_writer->writeCharacters(
"<Unknown command>");
1192 m_writer->writeStartElement(dbNamespace,
"code");
1193 m_writer->writeCharacters(atom->string());
1194 m_writer->writeEndElement();
1195 m_writer->writeEndElement();
1215 if (classMap.isEmpty())
1218 std::function<
void(
ClassNode *)> generateClassAndChildren
1219 = [
this, &relative, &generateClassAndChildren](ClassNode * classe) {
1220 m_writer->writeStartElement(dbNamespace,
"listitem");
1224 m_writer->writeStartElement(dbNamespace,
"para");
1225 generateFullName(classe, relative);
1226 m_writer->writeEndElement();
1230 bool hasChild =
false;
1231 for (
const RelatedClass &relatedClass : classe->derivedClasses()) {
1232 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1239 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1242 for (
const RelatedClass &relatedClass: classe->derivedClasses()) {
1243 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1244 generateClassAndChildren(relatedClass.m_node);
1248 m_writer->writeEndElement();
1253 m_writer->writeEndElement();
1257 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1260 for (
const auto &it : classMap) {
1261 auto *classe =
static_cast<ClassNode *>(it);
1262 if (classe->baseClasses().isEmpty())
1263 generateClassAndChildren(classe);
1266 m_writer->writeEndElement();
1277 if (match.hasMatch()) {
1279 qsizetype leftParenLoc = match.capturedStart(1);
1280 m_writer->writeCharacters(atom->string().left(leftParenLoc));
1282 m_writer->writeCharacters(atom->string().mid(leftParenLoc));
1286 m_writer->writeCharacters(atom->string());
1290
1291
1292
1296 m_writer->writeStartElement(dbNamespace,
"link");
1297 m_writer->writeAttribute(xlinkNamespace,
"href", link);
1298 if (node && !(relative && node->status() == relative->status())
1299 && node->isDeprecated())
1300 m_writer->writeAttribute(
"role",
"deprecated");
1309 m_writer->writeEndElement();
1315 Qt::SortOrder sortOrder)
1320 if (selector == QLatin1String(
"overviews"))
1322 else if (selector == QLatin1String(
"cpp-modules"))
1324 else if (selector == QLatin1String(
"qml-modules"))
1330 const QList<CollectionNode *> collectionList = cnm.values();
1331 nodeList.reserve(collectionList.size());
1332 for (
auto *collectionNode : collectionList)
1333 nodeList.append(collectionNode);
1334 generateAnnotatedList(relative, nodeList, selector, Auto, sortOrder);
1337
1338
1339
1340 Node *n =
const_cast<
Node *>(relative);
1343 generateAnnotatedList(cn, cn->members(), selector, Auto, sortOrder);
1348
1349
1350
1352 const QString &selector, GeneratedListType type,
1353 Qt::SortOrder sortOrder)
1355 if (nodeList.isEmpty())
1359 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1360 if (
std::all_of(nodeList.cbegin(), nodeList.cend(), [&policy](
const Node *n) {
1362 return !InclusionFilter::isIncluded(policy, context) || n->isDeprecated();
1369 bool noItemsHaveTitle =
1370 type == ItemizedList ||
std::all_of(nodeList.begin(), nodeList.end(),
1371 [](
const Node* node) {
1372 return node->doc().briefText().toString().isEmpty();
1376 if (type == AutoSection && m_hasSection)
1377 startSection(
"",
"Contents");
1380 if (!nodeList.isEmpty()) {
1381 m_writer->writeStartElement(dbNamespace, noItemsHaveTitle ?
"itemizedlist" :
"variablelist");
1382 m_writer->writeAttribute(
"role", selector);
1386 if (sortOrder == Qt::DescendingOrder)
1390 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1391 for (
const auto &node : std::as_const(members)) {
1392 const NodeContext context = node->createContext();
1393 if (!InclusionFilter::isIncluded(policy, context) || node->isDeprecated())
1396 if (noItemsHaveTitle) {
1397 m_writer->writeStartElement(dbNamespace,
"listitem");
1399 m_writer->writeStartElement(dbNamespace,
"para");
1401 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1403 m_writer->writeStartElement(dbNamespace,
"term");
1405 generateFullName(node, relative);
1406 if (noItemsHaveTitle) {
1407 m_writer->writeEndElement();
1409 m_writer->writeEndElement();
1411 m_writer->writeEndElement();
1413 m_writer->writeStartElement(dbNamespace,
"listitem");
1415 m_writer->writeStartElement(dbNamespace,
"para");
1416 m_writer->writeCharacters(node->doc().briefText().toString());
1417 m_writer->writeEndElement();
1419 m_writer->writeEndElement();
1421 m_writer->writeEndElement();
1426 m_writer->writeEndElement();
1430 if (type == AutoSection && m_hasSection)
1435
1436
1437
1439 const QString &selector)
1442 for (
const QString &name : nmm.uniqueKeys()) {
1443 if (!name.isEmpty())
1444 startSection(name.toLower(), name);
1445 generateAnnotatedList(relative, nmm.values(name), selector);
1446 if (!name.isEmpty())
1452
1453
1454
1455
1456
1457
1458
1459
1460
1462 bool includeAlphabet,
const QString &commonPrefix,
1463 const QString &selector)
1473 const int NumParagraphs = 37;
1474 qsizetype commonPrefixLen = commonPrefix.size();
1477
1478
1479
1480
1481
1483 QString paragraphName[NumParagraphs + 1];
1484 QSet<
char> usedParagraphNames;
1486 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
1487 QStringList pieces = c.key().split(
"::");
1488 int idx = commonPrefixLen;
1489 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
1491 QString last = pieces.last().toLower();
1492 QString key = last.mid(idx);
1494 int paragraphNr = NumParagraphs - 1;
1496 if (key[0].digitValue() != -1) {
1497 paragraphNr = key[0].digitValue();
1498 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
1499 paragraphNr = 10 + key[0].unicode() -
'a';
1502 paragraphName[paragraphNr] = key[0].toUpper();
1503 usedParagraphNames.insert(key[0].toLower().cell());
1504 paragraph[paragraphNr].insert(last, c.value());
1508
1509
1510
1511
1512
1513
1514
1515 int paragraphOffset[NumParagraphs + 1];
1516 paragraphOffset[0] = 0;
1517 for (
int i = 0; i < NumParagraphs; i++)
1518 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
1521 if (includeAlphabet && !usedParagraphNames.isEmpty()) {
1522 m_writer->writeStartElement(dbNamespace,
"simplelist");
1525 for (
int i = 0; i < 26; i++) {
1527 if (usedParagraphNames.contains(
char(
'a' + i))) {
1528 m_writer->writeStartElement(dbNamespace,
"member");
1529 generateSimpleLink(ch, ch.toUpper());
1530 m_writer->writeEndElement();
1535 m_writer->writeEndElement();
1540 QHash<QString,
int> nameOccurrences;
1541 for (
const auto &[key, node] : nmm.asKeyValueRange()) {
1542 QStringList pieces{node->fullName(relative).split(
"::"_L1)};
1543 const QString &name{pieces.last()};
1544 nameOccurrences[name]++;
1549 int curParOffset = 0;
1551 m_writer->writeStartElement(dbNamespace,
"variablelist");
1552 m_writer->writeAttribute(
"role", selector);
1555 for (
int i = 0; i < nmm.size(); i++) {
1556 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
1563 if (curParOffset == 0) {
1565 m_writer->writeEndElement();
1567 m_writer->writeEndElement();
1569 m_writer->writeEndElement();
1573 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1574 if (includeAlphabet)
1575 writeXmlId(paragraphName[curParNr][0].toLower());
1578 m_writer->writeStartElement(dbNamespace,
"term");
1579 m_writer->writeStartElement(dbNamespace,
"emphasis");
1580 m_writer->writeAttribute(
"role",
"bold");
1581 m_writer->writeCharacters(paragraphName[curParNr]);
1582 m_writer->writeEndElement();
1583 m_writer->writeEndElement();
1586 m_writer->writeStartElement(dbNamespace,
"listitem");
1588 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1593 m_writer->writeStartElement(dbNamespace,
"listitem");
1595 m_writer->writeStartElement(dbNamespace,
"para");
1597 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
1598 NodeMultiMap::Iterator it;
1599 NodeMultiMap::Iterator next;
1600 it = paragraph[curParNr].begin();
1601 for (
int j = 0; j < curParOffset; j++)
1606 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
1607 const auto &name{pieces.last()};
1610 if (nameOccurrences[name] > 1) {
1611 const QString moduleName = it.value()->isQmlNode() ? it.value()->logicalModuleName()
1612 : it.value()->tree()->camelCaseModuleName();
1613 pieces.last().append(
": %1"_L1.arg(moduleName));
1617 m_writer->writeStartElement(dbNamespace,
"link");
1618 m_writer->writeAttribute(xlinkNamespace,
"href", linkForNode(*it, relative));
1619 if (
const QString type = targetType(it.value()); !type.isEmpty())
1620 m_writer->writeAttribute(
"role", type);
1621 m_writer->writeCharacters(pieces.last());
1622 m_writer->writeEndElement();
1625 if (pieces.size() > 1) {
1626 m_writer->writeCharacters(
" (");
1627 generateFullName(it.value()->parent(), relative);
1628 m_writer->writeCharacters(
")");
1632 m_writer->writeEndElement();
1634 m_writer->writeEndElement();
1639 m_writer->writeEndElement();
1641 m_writer->writeEndElement();
1643 m_writer->writeEndElement();
1646 m_writer->writeEndElement();
1655 m_writer->writeStartElement(dbNamespace,
"simplelist");
1656 m_writer->writeAttribute(
"role",
"functionIndex");
1658 for (
int i = 0; i < 26; i++) {
1660 m_writer->writeStartElement(dbNamespace,
"member");
1661 m_writer->writeAttribute(xlinkNamespace,
"href", QString(
"#") + ch);
1662 m_writer->writeCharacters(ch.toUpper());
1663 m_writer->writeEndElement();
1666 m_writer->writeEndElement();
1673 char nextLetter =
'a';
1676 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1680 QMap<QString, NodeMap>::ConstIterator f = funcIndex.constBegin();
1681 while (f != funcIndex.constEnd()) {
1682 m_writer->writeStartElement(dbNamespace,
"listitem");
1684 m_writer->writeStartElement(dbNamespace,
"para");
1685 m_writer->writeCharacters(f.key() +
": ");
1687 currentLetter = f.key()[0].unicode();
1688 while (islower(currentLetter) && currentLetter >= nextLetter) {
1689 writeAnchor(QString(nextLetter));
1693 NodeMap::ConstIterator s = (*f).constBegin();
1694 while (s != (*f).constEnd()) {
1695 m_writer->writeCharacters(
" ");
1696 generateFullName((*s)->parent(), relative);
1700 m_writer->writeEndElement();
1702 m_writer->writeEndElement();
1706 m_writer->writeEndElement();
1714 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
1715 Text text = it.key();
1717 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1720 m_writer->writeStartElement(dbNamespace,
"listitem");
1722 m_writer->writeStartElement(dbNamespace,
"para");
1723 generateFullName(it.value(), relative);
1724 m_writer->writeEndElement();
1726 m_writer->writeEndElement();
1729 }
while (it != legaleseTexts.constEnd() && it.key() == text);
1730 m_writer->writeEndElement();
1745 m_writer->writeStartElement(dbNamespace,
"para");
1747 m_writer->writeEndElement();
1755 if (!node->since().isEmpty()) {
1756 m_writer->writeStartElement(dbNamespace,
"para");
1758 const auto &collective =
static_cast<
const SharedCommentNode *>(node)->collective();
1759 QString typeStr = collective.size() > 1 ? typeString(collective.first()) +
"s" : typeString(node);
1760 m_writer->writeCharacters(
"These " + typeStr +
" were introduced in ");
1762 m_writer->writeCharacters(
"This " + typeString(node) +
" was introduced in ");
1764 m_writer->writeCharacters(formatSince(node) +
".");
1765 m_writer->writeEndElement();
1775
1776
1777
1784 m_writer->writeStartElement(dbNamespace,
"info");
1786 m_writer->writeStartElement(dbNamespace,
"title");
1787 if (isApiGenus(node->genus()) && m_useITS)
1788 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1789 m_writer->writeCharacters(title);
1790 m_writer->writeEndElement();
1793 if (!subTitle.isEmpty()) {
1794 m_writer->writeStartElement(dbNamespace,
"subtitle");
1795 if (isApiGenus(node->genus()) && m_useITS)
1796 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1797 m_writer->writeCharacters(subTitle);
1798 m_writer->writeEndElement();
1802 if (!m_productName.isEmpty() || !m_project.isEmpty()) {
1803 m_writer->writeTextElement(dbNamespace,
"productname", m_productName.isEmpty() ?
1804 m_project : m_productName);
1808 if (!m_buildVersion.isEmpty()) {
1809 m_writer->writeTextElement(dbNamespace,
"edition", m_buildVersion);
1813 if (!m_projectDescription.isEmpty()) {
1814 m_writer->writeTextElement(dbNamespace,
"titleabbrev", m_projectDescription);
1822 if (node && !node->links().empty()) {
1823 std::pair<QString, QString> linkPair;
1824 std::pair<QString, QString> anchorPair;
1825 const Node *linkNode;
1827 if (node->links().contains(Node::PreviousLink)) {
1828 linkPair = node->links()[Node::PreviousLink];
1829 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1830 if (!linkNode || linkNode == node)
1831 anchorPair = linkPair;
1833 anchorPair = anchorForNode(linkNode);
1835 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1836 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1837 m_writer->writeEmptyElement(dbNamespace,
"link");
1838 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1839 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1840 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"prev");
1841 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1842 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1844 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1845 m_writer->writeEndElement();
1848 if (node->links().contains(Node::NextLink)) {
1849 linkPair = node->links()[Node::NextLink];
1850 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1851 if (!linkNode || linkNode == node)
1852 anchorPair = linkPair;
1854 anchorPair = anchorForNode(linkNode);
1856 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1857 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1858 m_writer->writeEmptyElement(dbNamespace,
"link");
1859 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1860 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1861 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"next");
1862 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1863 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1865 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1866 m_writer->writeEndElement();
1869 if (node->links().contains(Node::StartLink)) {
1870 linkPair = node->links()[Node::StartLink];
1871 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1872 if (!linkNode || linkNode == node)
1873 anchorPair = linkPair;
1875 anchorPair = anchorForNode(linkNode);
1877 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1878 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1879 m_writer->writeEmptyElement(dbNamespace,
"link");
1880 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1881 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1882 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"start");
1883 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1884 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1886 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1887 m_writer->writeEndElement();
1899 m_writer->writeStartElement(dbNamespace,
"abstract");
1902 bool generatedSomething =
false;
1909 brief <<
"The " << ns->name()
1910 <<
" namespace includes the following elements from module "
1911 << ns
->tree()->camelCaseModuleName() <<
". The full namespace is "
1912 <<
"documented in module " << NS
->tree()->camelCaseModuleName();
1913 addNodeLink(brief, fullDocumentLocation(NS),
" here.");
1922 m_writer->writeStartElement(dbNamespace,
"para");
1924 m_writer->writeEndElement();
1927 generatedSomething =
true;
1938 if (!generatedSomething)
1939 m_writer->writeTextElement(dbNamespace,
"para", m_projectDescription +
".");
1941 m_writer->writeEndElement();
1946 m_writer->writeEndElement();
1952 while (!sectionLevels.isEmpty()) {
1953 sectionLevels.pop();
1960 if (m_closeSectionAfterGeneratedList) {
1961 m_closeSectionAfterGeneratedList =
false;
1964 if (m_closeSectionAfterRawTitle) {
1965 m_closeSectionAfterRawTitle =
false;
1970 m_writer->writeEndElement();
1973void DocBookGenerator::generateSimpleLink(
const QString &href,
const QString &text)
1975 m_writer->writeStartElement(dbNamespace,
"link");
1976 m_writer->writeAttribute(xlinkNamespace,
"href", href);
1977 m_writer->writeCharacters(text);
1978 m_writer->writeEndElement();
1990 startSection(
"obsolete",
"Obsolete Members for " + aggregate->plainFullName());
1992 m_writer->writeStartElement(dbNamespace,
"para");
1993 m_writer->writeStartElement(dbNamespace,
"emphasis");
1994 m_writer->writeAttribute(
"role",
"bold");
1995 m_writer->writeCharacters(
"The following members of class ");
1996 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
1997 m_writer->writeCharacters(
" are deprecated.");
1998 m_writer->writeEndElement();
1999 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2000 m_writer->writeEndElement();
2003 for (
const Section *section : details_spv) {
2004 const QString &title =
"Obsolete " + section->title();
2005 startSection(title.toLower(), title);
2007 const NodeVector &members = section->obsoleteMembers();
2008 NodeVector::ConstIterator m = members.constBegin();
2009 while (m != members.constEnd()) {
2010 if ((*m)->access() != Access::Private)
2011 generateDetailedMember(*m, aggregate);
2022
2023
2024
2025
2026
2027
2028
2038 startSection(
"obsolete",
"Obsolete Members for " + aggregate->name());
2040 m_writer->writeStartElement(dbNamespace,
"para");
2041 m_writer->writeStartElement(dbNamespace,
"emphasis");
2042 m_writer->writeAttribute(
"role",
"bold");
2043 m_writer->writeCharacters(
"The following members of QML type ");
2044 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2045 m_writer->writeCharacters(
" are deprecated.");
2046 m_writer->writeEndElement();
2047 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2048 m_writer->writeEndElement();
2051 for (
const auto *section : details_spv) {
2052 const QString &title =
"Obsolete " + section->title();
2053 startSection(title.toLower(), title);
2055 const NodeVector &members = section->obsoleteMembers();
2056 NodeVector::ConstIterator m = members.constBegin();
2057 while (m != members.constEnd()) {
2058 if ((*m)->access() != Access::Private)
2059 generateDetailedQmlMember(*m, aggregate);
2073 return QStringLiteral(
"classsynopsis");
2075 return QStringLiteral(
"packagesynopsis");
2081 return QStringLiteral(
"enumsynopsis");
2083 return QStringLiteral(
"typedefsynopsis");
2086 const auto fn =
static_cast<
const FunctionNode *>(node);
2088 return QStringLiteral(
"constructorsynopsis");
2090 return QStringLiteral(
"destructorsynopsis");
2091 return QStringLiteral(
"methodsynopsis");
2094 return QStringLiteral(
"fieldsynopsis");
2096 node
->doc().location().warning(QString(
"Unknown node tag %1").arg(node->nodeTypeString()));
2097 return QStringLiteral(
"synopsis");
2102 m_writer->writeStartElement(dbNamespace,
"varlistentry");
2104 m_writer->writeTextElement(dbNamespace,
"term", description);
2106 m_writer->writeStartElement(dbNamespace,
"listitem");
2108 m_writer->writeStartElement(dbNamespace,
"para");
2114 m_writer->writeEndElement();
2117 m_writer->writeEndElement();
2119 m_writer->writeEndElement();
2123void DocBookGenerator::generateRequisite(
const QString &description,
const QString &value)
2125 generateStartRequisite(description);
2126 m_writer->writeCharacters(value);
2127 generateEndRequisite();
2131
2132
2133
2134void DocBookGenerator::generateCMakeRequisite(
const QString &findPackage,
const QString &linkLibraries)
2136 const QString description(
"CMake");
2137 generateStartRequisite(description);
2138 m_writer->writeCharacters(findPackage);
2139 m_writer->writeEndElement();
2142 m_writer->writeStartElement(dbNamespace,
"para");
2143 m_writer->writeCharacters(linkLibraries);
2144 generateEndRequisite();
2150 QMap<QString, ClassNode *> classMap;
2151 QList<RelatedClass>::ConstIterator r = rc.constBegin();
2152 while (r != rc.constEnd()) {
2155 && !rcn
->doc().isEmpty()) {
2156 classMap[rcn->plainFullName(cn).toLower()] = rcn;
2161 QStringList classNames = classMap.keys();
2165 for (
const QString &className : classNames) {
2166 generateFullName(classMap.value(className), cn);
2167 m_writer->writeCharacters(Utilities::comma(index++, classNames.size()));
2175 QMap<QString, Node *> classMap;
2176 QStringList typeNames(knownTypes);
2177 for (
const auto sub : subs)
2178 typeNames << sub->name();
2180 for (
auto sub : subs) {
2181 QString key{sub->plainFullName(base).toLower()};
2183 if (typeNames.count(sub->name()) > 1)
2184 key.append(
": (%1)"_L1.arg(sub->logicalModuleName()));
2185 classMap[key] = sub;
2188 QStringList names = classMap.keys();
2192 for (
const QString &name : names) {
2193 generateFullName(classMap.value(name), base);
2194 if (name.contains(
':'))
2195 m_writer->writeCharacters(name.section(
':', 1));
2196 m_writer->writeCharacters(Utilities::comma(index++, names.size()));
2201
2202
2211 QXmlStreamWriter* oldWriter = m_writer;
2213 m_writer =
new QXmlStreamWriter(&output);
2216 if (aggregate->includeFile()) generateRequisite(
"Header", *aggregate->includeFile());
2219 if (!aggregate->since().isEmpty())
2220 generateRequisite(
"Since", formatSince(aggregate));
2227 if (
const auto result = cmakeRequisite(cn)) {
2228 generateCMakeRequisite(result->first, result->second);
2231 if (cn && !cn->qtVariable().isEmpty())
2232 generateRequisite(
"qmake",
"QT += " + cn->qtVariable());
2239 generateStartRequisite(
"In QML");
2242 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2245 for (
const auto &item : std::as_const(nativeTypes)) {
2246 generateFullName(item, classe);
2247 m_writer->writeCharacters(
2248 Utilities::comma(idx++, nativeTypes.size()));
2250 generateEndRequisite();
2254 QList<RelatedClass>::ConstIterator r;
2255 if (classe && !classe->baseClasses().isEmpty()) {
2256 generateStartRequisite(
"Inherits");
2258 r = classe->baseClasses().constBegin();
2260 while (r != classe->baseClasses().constEnd()) {
2262 generateFullName((*r).m_node, classe);
2264 if ((*r).m_access == Access::Protected)
2265 m_writer->writeCharacters(
" (protected)");
2266 else if ((*r).m_access == Access::Private)
2267 m_writer->writeCharacters(
" (private)");
2268 m_writer->writeCharacters(
2269 Utilities::comma(index++, classe->baseClasses().size()));
2274 generateEndRequisite();
2278 if (!classe->derivedClasses().isEmpty()) {
2279 generateStartRequisite(
"Inherited By");
2280 generateSortedNames(classe, classe->derivedClasses());
2281 generateEndRequisite();
2286 if (!aggregate->groupNames().empty()) {
2287 generateStartRequisite(
"Group");
2289 generateEndRequisite();
2293 if (
auto status = formatStatus(aggregate, m_qdb); status)
2294 generateRequisite(
"Status", status.value());
2298 m_writer = oldWriter;
2300 if (!output.isEmpty()) {
2303 static const QRegularExpression xmlTag(R"(<(/?)n\d+:)");
2304 static const QRegularExpression xmlnsDocBookDefinition(R"( xmlns:n\d+=")" + QString{dbNamespace} +
"\"");
2305 static const QRegularExpression xmlnsXLinkDefinition(R"( xmlns:n\d+=")" + QString{xlinkNamespace} +
"\"");
2306 static const QRegularExpression xmlAttr(R"( n\d+:)");
2308 const QString cleanOutput = output.replace(xmlTag, R"(<\1db:)")
2309 .replace(xmlnsDocBookDefinition,
"")
2310 .replace(xmlnsXLinkDefinition,
"")
2311 .replace(xmlAttr,
" xlink:");
2313 m_writer->writeStartElement(dbNamespace,
"variablelist");
2315 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2318 m_writer->device()->write(cleanOutput.toUtf8());
2320 m_writer->writeEndElement();
2326
2327
2335 const QString importText =
"Import Statement";
2336 const QString sinceText =
"Since";
2337 const QString inheritedByText =
"Inherited By";
2338 const QString inheritsText =
"Inherits";
2339 const QString nativeTypeText =
"In C++";
2340 const QString groupText =
"Group";
2341 const QString statusText =
"Status";
2349 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2358 bool generate_import_statement = !qcn->logicalModuleName().isEmpty();
2359 if (generate_import_statement && collection) {
2364 const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base;
2366 if (!generates_something)
2369 QStringList knownTypeNames{qcn->name()};
2371 knownTypeNames << base->name();
2374 m_writer->writeStartElement(dbNamespace,
"variablelist");
2376 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2379 if (generate_import_statement) {
2380 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2381 generateRequisite(importText, parts.join(
' ').trimmed());
2385 if (!qcn->since().isEmpty())
2386 generateRequisite(sinceText, formatSince(qcn));
2391 generateStartRequisite(nativeTypeText);
2392 generateSimpleLink(fullDocumentLocation(cn), cn->name());
2393 generateEndRequisite();
2398 generateStartRequisite(inheritsText);
2399 generateSimpleLink(fullDocumentLocation(base), base->name());
2401 for (
const auto sub : std::as_const(subs)) {
2402 if (knownTypeNames.contains(sub->name())) {
2403 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
2407 generateEndRequisite();
2411 if (!subs.isEmpty()) {
2412 generateStartRequisite(inheritedByText);
2413 generateSortedQmlNames(qcn, knownTypeNames, subs);
2414 generateEndRequisite();
2418 if (!qcn->groupNames().empty()) {
2419 generateStartRequisite(groupText);
2421 generateEndRequisite();
2425 if (
auto status = formatStatus(qcn, m_qdb); status)
2426 generateRequisite(statusText, status.value());
2428 m_writer->writeEndElement();
2439 const QString &state =
static_cast<
const CollectionNode*>(node)->state();
2440 if (!state.isEmpty()) {
2441 m_writer->writeStartElement(dbNamespace,
"para");
2442 m_writer->writeCharacters(
"This " + typeString(node) +
" is in ");
2443 m_writer->writeStartElement(dbNamespace,
"emphasis");
2444 m_writer->writeCharacters(state);
2445 m_writer->writeEndElement();
2446 m_writer->writeCharacters(
" state.");
2447 m_writer->writeEndElement();
2452 if (
const auto &version = node->deprecatedSince(); !version.isEmpty()) {
2453 m_writer->writeStartElement(dbNamespace,
"para");
2454 m_writer->writeCharacters(
"This " + typeString(node)
2455 +
" is scheduled for deprecation in version "
2457 m_writer->writeEndElement();
2462 case Node::Preliminary:
2463 m_writer->writeStartElement(dbNamespace,
"para");
2464 m_writer->writeStartElement(dbNamespace,
"emphasis");
2465 m_writer->writeAttribute(
"role",
"bold");
2466 m_writer->writeCharacters(
"This " + typeString(node)
2467 +
" is under development and is subject to change.");
2468 m_writer->writeEndElement();
2469 m_writer->writeEndElement();
2472 case Node::Deprecated:
2473 m_writer->writeStartElement(dbNamespace,
"para");
2475 m_writer->writeStartElement(dbNamespace,
"emphasis");
2476 m_writer->writeAttribute(
"role",
"bold");
2478 m_writer->writeCharacters(
"This " + typeString(node) +
" is deprecated");
2479 if (
const QString &version = node->deprecatedSince(); !version.isEmpty()) {
2480 m_writer->writeCharacters(
" since ");
2481 if (node->isQmlNode() && !node->logicalModuleName().isEmpty())
2482 m_writer->writeCharacters(node->logicalModuleName() +
" ");
2483 m_writer->writeCharacters(version);
2485 m_writer->writeCharacters(
". We strongly advise against using it in new code.");
2486 if (node->isAggregate())
2487 m_writer->writeEndElement();
2488 m_writer->writeEndElement();
2498
2499
2500
2504 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2507 NodeList::ConstIterator n = nodes.constBegin();
2508 while (n != nodes.constEnd()) {
2509 m_writer->writeStartElement(dbNamespace,
"listitem");
2511 m_writer->writeStartElement(dbNamespace,
"para");
2513 generateSimpleLink(currentGenerator()->fullDocumentLocation(*n),
2514 (*n)->signature(Node::SignaturePlain));
2516 m_writer->writeEndElement();
2518 m_writer->writeEndElement();
2523 m_writer->writeEndElement();
2528
2529
2530
2537 const auto aggregate =
static_cast<
const Aggregate *>(node);
2539 const QStringList &groups_names{aggregate->groupNames()};
2540 if (!groups_names.empty()) {
2541 m_writer->writeCharacters(aggregate->name() +
" is part of ");
2542 m_writer->writeStartElement(dbNamespace,
"simplelist");
2544 for (qsizetype index{0}; index < groups_names.size(); ++index) {
2548 m_writer->writeStartElement(dbNamespace,
"member");
2549 if (QString target{linkForNode(group,
nullptr)}; !target.isEmpty())
2550 generateSimpleLink(target, group->fullTitle());
2552 m_writer->writeCharacters(group->name());
2553 m_writer->writeEndElement();
2556 m_writer->writeEndElement();
2562
2563
2564
2570 const Node *reentrantNode;
2572 QString linkReentrant = getAutoLink(&reentrantAtom, node, &reentrantNode);
2573 const Node *threadSafeNode;
2575 QString linkThreadSafe = getAutoLink(&threadSafeAtom, node, &threadSafeNode);
2578 m_writer->writeStartElement(dbNamespace,
"warning");
2580 m_writer->writeStartElement(dbNamespace,
"para");
2581 m_writer->writeCharacters(
"This " + typeString(node) +
" is not ");
2582 generateSimpleLink(linkReentrant,
"reentrant");
2583 m_writer->writeCharacters(
".");
2584 m_writer->writeEndElement();
2586 m_writer->writeEndElement();
2590 m_writer->writeStartElement(dbNamespace,
"note");
2592 m_writer->writeStartElement(dbNamespace,
"para");
2595 m_writer->writeCharacters(
"All functions in this " + typeString(node) +
" are ");
2596 if (ts == Node::ThreadSafe)
2597 generateSimpleLink(linkThreadSafe,
"thread-safe");
2599 generateSimpleLink(linkReentrant,
"reentrant");
2604 bool exceptions = hasExceptions(node, reentrant, threadsafe, nonreentrant);
2605 if (!exceptions || (ts ==
Node::Reentrant && !threadsafe.isEmpty())) {
2606 m_writer->writeCharacters(
".");
2607 m_writer->writeEndElement();
2610 m_writer->writeCharacters(
" with the following exceptions:");
2611 m_writer->writeEndElement();
2613 m_writer->writeStartElement(dbNamespace,
"para");
2616 if (!nonreentrant.isEmpty()) {
2617 m_writer->writeCharacters(
"These functions are not ");
2618 generateSimpleLink(linkReentrant,
"reentrant");
2619 m_writer->writeCharacters(
":");
2620 m_writer->writeEndElement();
2622 generateSignatureList(nonreentrant);
2624 if (!threadsafe.isEmpty()) {
2625 m_writer->writeCharacters(
"These functions are also ");
2626 generateSimpleLink(linkThreadSafe,
"thread-safe");
2627 m_writer->writeCharacters(
":");
2628 m_writer->writeEndElement();
2630 generateSignatureList(threadsafe);
2633 if (!reentrant.isEmpty()) {
2634 m_writer->writeCharacters(
"These functions are only ");
2635 generateSimpleLink(linkReentrant,
"reentrant");
2636 m_writer->writeCharacters(
":");
2637 m_writer->writeEndElement();
2639 generateSignatureList(reentrant);
2641 if (!nonreentrant.isEmpty()) {
2642 m_writer->writeCharacters(
"These functions are not ");
2643 generateSimpleLink(linkReentrant,
"reentrant");
2644 m_writer->writeCharacters(
":");
2645 m_writer->writeEndElement();
2647 generateSignatureList(nonreentrant);
2652 m_writer->writeCharacters(
"This " + typeString(node) +
" is ");
2653 if (ts == Node::ThreadSafe)
2654 generateSimpleLink(linkThreadSafe,
"thread-safe");
2656 generateSimpleLink(linkReentrant,
"reentrant");
2657 m_writer->writeCharacters(
".");
2658 m_writer->writeEndElement();
2661 m_writer->writeEndElement();
2671
2672
2673
2681
2682
2683
2687 t =
"Destroys the instance of " + fn
->parent()->name() +
".";
2689 t +=
" The destructor is virtual.";
2691 t =
"Default constructs an instance of " + fn
->parent()->name() +
".";
2693 t =
"Copy constructor.";
2695 t =
"Move-copy constructor.";
2697 t =
"Copy-assignment constructor.";
2699 t =
"Move-assignment constructor.";
2703 m_writer->writeTextElement(dbNamespace,
"para", t);
2707 if (fn && !fn->overridesThis().isEmpty())
2708 generateReimplementsClause(fn);
2739 generateRequiredLinks(node);
2743
2744
2745
2746
2747
2754 const auto en =
static_cast<
const ExampleNode *>(node);
2757 if (exampleUrl.isEmpty()) {
2759 generateFileList(en,
false);
2760 generateFileList(en,
true);
2763 generateLinkToExample(en, exampleUrl);
2768
2769
2770
2771
2772
2776 QString exampleUrl(baseUrl);
2778#ifndef QT_BOOTSTRAPPED
2779 link = QUrl(exampleUrl).host();
2781 if (!link.isEmpty())
2782 link.prepend(
" @ ");
2783 link.prepend(
"Example project");
2785 const QLatin1Char separator(
'/');
2786 const QLatin1Char placeholder(
'\1');
2787 if (!exampleUrl.contains(placeholder)) {
2788 if (!exampleUrl.endsWith(separator))
2789 exampleUrl += separator;
2790 exampleUrl += placeholder;
2794 QStringList path = QStringList()
2796 path.removeAll(QString());
2800 startSection(
"Example project");
2802 m_writer->writeStartElement(dbNamespace,
"para");
2803 generateSimpleLink(exampleUrl.replace(placeholder, path.join(separator)), link);
2804 m_writer->writeEndElement();
2813
2814
2815
2816
2817
2818
2834 paths = en->images();
2837 paths = en->files();
2840 std::sort(paths.begin(), paths.end(), Generator::comparePaths);
2842 if (paths.isEmpty())
2845 startSection(
"",
"List of Files");
2847 m_writer->writeStartElement(dbNamespace,
"para");
2848 m_writer->writeCharacters(tag);
2849 m_writer->writeEndElement();
2852 startSection(
"List of Files");
2854 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2857 for (
const auto &path : std::as_const(paths)) {
2858 auto maybe_resolved_file{file_resolver.resolve(path)};
2859 if (!maybe_resolved_file) {
2861 QString details = std::transform_reduce(
2862 file_resolver.get_search_directories().cbegin(),
2863 file_resolver.get_search_directories().cend(),
2864 u"Searched directories:"_s,
2866 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
2869 en->location().warning(u"Cannot find file to quote from: %1"_s.arg(path), details);
2874 const auto &file{*maybe_resolved_file};
2875 if (images) addImageToCopy(en, file);
2876 else generateExampleFilePage(en, file);
2878 m_writer->writeStartElement(dbNamespace,
"listitem");
2880 m_writer->writeStartElement(dbNamespace,
"para");
2881 generateSimpleLink(file.get_query(), file.get_query());
2882 m_writer->writeEndElement();
2883 m_writer->writeEndElement();
2887 m_writer->writeEndElement();
2894
2895
2905 const auto en =
static_cast<
const ExampleNode *>(node);
2908 QXmlStreamWriter *currentWriter = m_writer;
2909 m_writer = startDocument(en, resolved_file.get_query());
2910 generateHeader(en->fullTitle(), en->subtitle(), en);
2915 QString code = quoter.quoteTo(en
->location(), QString(), QString());
2916 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
2922 m_writer = currentWriter;
2928 if (fn->overridesThis().isEmpty() || !fn
->parent()->isClassNode())
2933 if (
const FunctionNode *overrides = cn->findOverriddenFunction(fn);
2936 m_writer->writeStartElement(dbNamespace,
"para");
2937 m_writer->writeCharacters(
"Reimplements: ");
2940 generateFullName(overrides
->parent(), fullName, overrides);
2941 m_writer->writeCharacters(
".");
2942 m_writer->writeEndElement();
2948 if (
const PropertyNode *sameName = cn->findOverriddenProperty(fn); sameName && sameName
->hasDoc()) {
2949 m_writer->writeStartElement(dbNamespace,
"para");
2950 m_writer->writeCharacters(
"Reimplements an access function for property: ");
2951 QString fullName = sameName
->parent()->name() +
"::" + sameName->name();
2952 generateFullName(sameName
->parent(), fullName, sameName);
2953 m_writer->writeCharacters(
".");
2954 m_writer->writeEndElement();
2963 QList<Text> alsoList = node
->doc().alsoList();
2964 supplementAlsoList(node, alsoList);
2966 if (!alsoList.isEmpty()) {
2967 startSection(
"See Also");
2969 m_writer->writeStartElement(dbNamespace,
"para");
2970 m_writer->writeStartElement(dbNamespace,
"emphasis");
2971 m_writer->writeCharacters(
"See also ");
2972 m_writer->writeEndElement();
2975 m_writer->writeStartElement(dbNamespace,
"simplelist");
2976 m_writer->writeAttribute(
"type",
"vert");
2977 m_writer->writeAttribute(
"role",
"see-also");
2980 for (
const Text &text : alsoList) {
2981 m_writer->writeStartElement(dbNamespace,
"member");
2982 generateText(text, node);
2983 m_writer->writeEndElement();
2987 m_writer->writeEndElement();
2990 m_writer->writeEndElement();
2998
2999
3000
3001QXmlStreamWriter *
DocBookGenerator::startGenericDocument(
const Node *node,
const QString &fileName)
3004 QFile *outFile = openSubPageFile(
static_cast<
const PageNode*>(node), fileName);
3005 m_writer =
new QXmlStreamWriter(outFile);
3006 m_writer->setAutoFormatting(
false);
3008 m_writer->writeStartDocument();
3010 m_writer->writeNamespace(dbNamespace,
"db");
3011 m_writer->writeNamespace(xlinkNamespace,
"xlink");
3013 m_writer->writeNamespace(itsNamespace,
"its");
3014 m_writer->writeStartElement(dbNamespace,
"article");
3015 m_writer->writeAttribute(
"version",
"5.2");
3016 if (!m_naturalLanguage.isEmpty())
3017 m_writer->writeAttribute(
"xml:lang", m_naturalLanguage);
3021 sectionLevels.resize(0);
3030 m_hasSection =
false;
3033 QString fileName = Generator::fileName(node, fileExtension());
3034 return startGenericDocument(node, fileName);
3039 m_hasSection =
false;
3041 QString fileName = linkForExampleFile(file);
3042 return startGenericDocument(en, fileName);
3047 m_writer->writeEndElement();
3048 m_writer->writeEndDocument();
3050 m_writer->device()->close();
3051 delete m_writer->device();
3057
3058
3059
3064 const auto aggregate =
static_cast<
const Aggregate *>(node);
3067 QString subtitleText;
3068 const QString typeWord{aggregate->typeWord(
true)};
3070 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3072 auto templateDecl = node->templateDecl();
3074 subtitleText =
"%1 %2 %3"_L1.arg((*templateDecl).to_qstring(),
3075 aggregate->typeWord(
false),
3076 aggregate->plainFullName());
3077 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3079 title = aggregate->fullTitle();
3083 m_writer = startDocument(node);
3086 generateHeader(title, subtitleText, aggregate);
3095 if (!aggregate
->doc().isEmpty()) {
3096 startSection(
"details",
"Detailed Description");
3098 generateBody(aggregate);
3109 for (
const Section §ion : sectionVector) {
3110 if (section.members().isEmpty())
3113 startSection(section.title().toLower(), section.title());
3115 for (
const Node *member : section.members()) {
3116 if (member->nodeType() != NodeType::Class) {
3118 generateDetailedMember(member, aggregate);
3120 startSectionBegin();
3121 m_writer->writeCharacters(
"class ");
3122 generateFullName(member, aggregate);
3125 generateBrief(member);
3134 generateObsoleteMembers(sections);
3139void DocBookGenerator::generateSynopsisInfo(
const QString &key,
const QString &value)
3141 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3142 m_writer->writeAttribute(
"role", key);
3143 m_writer->writeCharacters(value);
3144 m_writer->writeEndElement();
3150 m_writer->writeTextElement(dbNamespace,
"modifier", value);
3155
3156
3166 if (!m_useDocBook52)
3193 QString synopsisTag = nodeToSynopsisTag(node);
3194 m_writer->writeStartElement(dbNamespace, synopsisTag);
3199 m_writer->writeStartElement(dbNamespace,
"ooclass");
3200 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3201 m_writer->writeEndElement();
3204 m_writer->writeTextElement(dbNamespace,
"namespacename", node->plainName());
3207 m_writer->writeStartElement(dbNamespace,
"ooclass");
3208 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3209 m_writer->writeEndElement();
3211 if (!qcn->groupNames().isEmpty())
3212 m_writer->writeAttribute(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3214 m_writer->writeTextElement(dbNamespace,
"modifier",
"(Qt property)");
3216 m_writer->writeTextElement(dbNamespace,
"type", propertyNode->dataType());
3218 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3222 m_writer->writeTextElement(dbNamespace,
"modifier",
"static");
3225 m_writer->writeTextElement(dbNamespace,
"type", variableNode->dataType());
3227 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3231 m_writer->writeTextElement(dbNamespace,
"enumname", node->plainName());
3235 QString name = node->name();
3237 name.prepend(qpn->element() + QLatin1Char(
'.'));
3239 m_writer->writeTextElement(dbNamespace,
"type", qpn->dataType());
3241 m_writer->writeTextElement(dbNamespace,
"varname", name);
3245 m_writer->writeTextElement(dbNamespace,
"modifier",
"attached");
3249 m_writer->writeTextElement(dbNamespace,
"modifier",
"writable");
3253 m_writer->writeTextElement(dbNamespace,
"modifier",
"required");
3257 generateModifier(
"[read-only]");
3261 generateModifier(
"[default]");
3265 if (functionNode->virtualness() !=
"non")
3266 generateModifier(
"virtual");
3267 if (functionNode->isConst())
3268 generateModifier(
"const");
3269 if (functionNode->isStatic())
3270 generateModifier(
"static");
3275 if (functionNode->returnType() ==
"void")
3276 m_writer->writeEmptyElement(dbNamespace,
"void");
3278 m_writer->writeTextElement(dbNamespace,
"type", functionNode->returnTypeString());
3283 QString name = node->plainName();
3284 if (name.endsWith(
"()"))
3286 m_writer->writeTextElement(dbNamespace,
"methodname", name);
3290 m_writer->writeEmptyElement(dbNamespace,
"void");
3295 for (
int i = 0; i < lp
.count(); ++i) {
3297 m_writer->writeStartElement(dbNamespace,
"methodparam");
3299 m_writer->writeTextElement(dbNamespace,
"type", parameter.type());
3301 m_writer->writeTextElement(dbNamespace,
"parameter", parameter.name());
3303 if (!parameter.defaultValue().isEmpty()) {
3304 m_writer->writeTextElement(dbNamespace,
"initializer", parameter.defaultValue());
3307 m_writer->writeEndElement();
3311 if (functionNode->isDefault())
3312 generateModifier(
"default");
3313 if (functionNode->isFinal())
3314 generateModifier(
"final");
3315 if (functionNode->isOverride())
3316 generateModifier(
"override");
3318 m_writer->writeTextElement(dbNamespace,
"typedefname", node->plainName());
3322 QStringLiteral(
"Unexpected node type in generateDocBookSynopsis: %1")
3323 .arg(node->nodeTypeString()));
3329 for (
const EnumItem &item : enumNode->items()) {
3330 m_writer->writeStartElement(dbNamespace,
"enumitem");
3332 m_writer->writeTextElement(dbNamespace,
"enumidentifier", item.name());
3334 m_writer->writeTextElement(dbNamespace,
"enumvalue", item.value());
3336 m_writer->writeEndElement();
3340 if (enumNode->items().isEmpty()) {
3343 m_writer->writeStartElement(dbNamespace,
"enumitem");
3345 m_writer->writeEmptyElement(dbNamespace,
"enumidentifier");
3347 m_writer->writeEndElement();
3358 generateSynopsisInfo(
"meta", functionNode->metanessString());
3361 generateSynopsisInfo(
"overload",
"overload");
3362 generateSynopsisInfo(
"overload-number",
3363 QString::number(functionNode->overloadNumber()));
3366 if (functionNode->isRef())
3367 generateSynopsisInfo(
"refness", QString::number(1));
3368 else if (functionNode->isRefRef())
3369 generateSynopsisInfo(
"refness", QString::number(2));
3372 QStringList associatedProperties;
3373 const auto &nodes = functionNode->associatedProperties();
3374 for (
const Node *n : nodes) {
3375 const auto pn =
static_cast<
const PropertyNode *>(n);
3376 associatedProperties << pn->name();
3378 associatedProperties.sort();
3379 generateSynopsisInfo(
"associated-property",
3380 associatedProperties.join(QLatin1Char(
',')));
3386 signature +=
" final";
3388 signature +=
" override";
3390 signature +=
" = 0";
3392 signature +=
" = default";
3393 generateSynopsisInfo(
"signature", signature);
3399 case Access::Public:
3400 generateSynopsisInfo(
"access",
"public");
3402 case Access::Protected:
3403 generateSynopsisInfo(
"access",
"protected");
3405 case Access::Private:
3406 generateSynopsisInfo(
"access",
"private");
3411 if (node->isAbstract())
3412 generateSynopsisInfo(
"abstract",
"true");
3418 generateSynopsisInfo(
"status",
"active");
3420 case Node::Preliminary:
3421 generateSynopsisInfo(
"status",
"preliminary");
3423 case Node::Deprecated:
3424 generateSynopsisInfo(
"status",
"deprecated");
3426 case Node::Internal:
3427 generateSynopsisInfo(
"status",
"internal");
3430 generateSynopsisInfo(
"status",
"main");
3437 if (aggregate->includeFile()) generateSynopsisInfo(
"headers", *aggregate->includeFile());
3440 if (!aggregate->since().isEmpty())
3441 generateSynopsisInfo(
"since", formatSince(aggregate));
3445 if (!aggregate->physicalModuleName().isEmpty()) {
3449 if (
const auto result = cmakeRequisite(cn)) {
3450 generateSynopsisInfo(
"cmake-find-package", result->first);
3451 generateSynopsisInfo(
"cmake-target-link-libraries", result->second);
3454 if (cn && !cn->qtVariable().isEmpty())
3455 generateSynopsisInfo(
"qmake",
"QT += " + cn->qtVariable());
3463 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3464 m_writer->writeAttribute(
"role",
"nativeTypeFor");
3466 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
3469 for (
auto item : std::as_const(nativeTypes)) {
3470 const Node *otherNode{
nullptr};
3471 Atom a = Atom(Atom::LinkNode, Utilities::stringForNode(item));
3472 const QString &link = getAutoLink(&a, aggregate, &otherNode);
3473 generateSimpleLink(link, item->name());
3476 m_writer->writeEndElement();
3480 QList<RelatedClass>::ConstIterator r;
3481 if (!classe->baseClasses().isEmpty()) {
3482 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3483 m_writer->writeAttribute(
"role",
"inherits");
3485 r = classe->baseClasses().constBegin();
3487 while (r != classe->baseClasses().constEnd()) {
3489 generateFullName((*r).m_node, classe);
3492 m_writer->writeCharacters(
" (protected)");
3494 m_writer->writeCharacters(
" (private)");
3496 m_writer->writeCharacters(
3497 Utilities::comma(index++, classe->baseClasses().size()));
3502 m_writer->writeEndElement();
3507 if (!classe->derivedClasses().isEmpty()) {
3508 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3509 m_writer->writeAttribute(
"role",
"inheritedBy");
3510 generateSortedNames(classe, classe->derivedClasses());
3511 m_writer->writeEndElement();
3520 QString logicalModuleVersion;
3524 logicalModuleVersion = collection->logicalModuleVersion();
3526 logicalModuleVersion = qcn->logicalModuleVersion();
3528 QStringList importText;
3529 importText <<
"import " + qcn->logicalModuleName();
3530 if (!logicalModuleVersion.isEmpty())
3531 importText << logicalModuleVersion;
3532 generateSynopsisInfo(
"import", importText.join(
' '));
3535 if (!qcn->since().isEmpty())
3536 generateSynopsisInfo(
"since", formatSince(qcn));
3539 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
3547 QStringList knownTypeNames{qcn->name()};
3549 knownTypeNames << base->name();
3554 if (!subs.isEmpty()) {
3555 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3556 m_writer->writeAttribute(
"role",
"inheritedBy");
3557 generateSortedQmlNames(qcn, knownTypeNames, subs);
3558 m_writer->writeEndElement();
3564 const Node *otherNode =
nullptr;
3566 QString link = getAutoLink(&a, base, &otherNode);
3568 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3569 m_writer->writeAttribute(
"role",
"inherits");
3570 generateSimpleLink(link, base->name());
3572 for (
const auto sub : std::as_const(subs)) {
3573 if (knownTypeNames.contains(sub->name())) {
3574 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
3578 m_writer->writeEndElement();
3586 const Node *otherNode =
nullptr;
3588 QString link = getAutoLink(&a, cn, &otherNode);
3590 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3591 m_writer->writeAttribute(
"role",
"nativeType");
3592 generateSimpleLink(link, cn->name());
3593 m_writer->writeEndElement();
3600 case Node::UnspecifiedSafeness:
3601 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3603 case Node::NonReentrant:
3604 generateSynopsisInfo(
"threadsafeness",
"non-reentrant");
3606 case Node::Reentrant:
3607 generateSynopsisInfo(
"threadsafeness",
"reentrant");
3609 case Node::ThreadSafe:
3610 generateSynopsisInfo(
"threadsafeness",
"thread safe");
3613 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3618 if (!node->physicalModuleName().isEmpty())
3619 generateSynopsisInfo(
"module", node->physicalModuleName());
3622 if (classNode && !classNode->groupNames().isEmpty()) {
3623 generateSynopsisInfo(
"groups", classNode->groupNames().join(QLatin1Char(
',')));
3624 }
else if (qcn && !qcn->groupNames().isEmpty()) {
3625 generateSynopsisInfo(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3630 for (
const Node *fnNode : propertyNode->getters()) {
3632 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3633 generateSynopsisInfo(
"getter", funcNode->name());
3636 for (
const Node *fnNode : propertyNode->setters()) {
3638 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3639 generateSynopsisInfo(
"setter", funcNode->name());
3642 for (
const Node *fnNode : propertyNode->resetters()) {
3644 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3645 generateSynopsisInfo(
"resetter", funcNode->name());
3648 for (
const Node *fnNode : propertyNode->notifiers()) {
3650 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3651 generateSynopsisInfo(
"notifier", funcNode->name());
3656 m_writer->writeEndElement();
3662 m_writer->writeStartElement(dbNamespace,
"typedefsynopsis");
3665 m_writer->writeTextElement(dbNamespace,
"typedefname",
3666 enumNode->flagsType()->fullDocumentName());
3669 m_writer->writeEndElement();
3680 return node->name().mid(4);
3681 return node->name();
3685
3686
3687
3688void DocBookGenerator::typified(
const QString &string,
const Node *relative,
bool trailingSpace,
3693 QString pendingWord;
3695 for (
int i = 0; i <= string.size(); ++i) {
3697 if (i != string.size())
3700 QChar lower = ch.toLower();
3701 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
3702 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
3705 if (!pendingWord.isEmpty()) {
3706 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
3707 if (generateType && isProbablyType) {
3709 m_writer->writeCharacters(result);
3713 const Node *n =
m_qdb->findTypeNode(pendingWord, relative, Genus::DontCare);
3718 href = linkForNode(n, relative);
3721 m_writer->writeStartElement(dbNamespace,
"type");
3723 m_writer->writeCharacters(pendingWord);
3725 generateSimpleLink(href, pendingWord);
3726 m_writer->writeEndElement();
3728 result += pendingWord;
3731 pendingWord.clear();
3733 if (ch.unicode() !=
'\0')
3738 if (trailingSpace && string.size()) {
3739 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
3740 result += QLatin1Char(
' ');
3743 m_writer->writeCharacters(result);
3747 bool generateNameLink)
3751 QString name = taggedNode(node);
3753 if (!generateNameLink) {
3754 m_writer->writeCharacters(name);
3758 m_writer->writeStartElement(dbNamespace,
"emphasis");
3759 m_writer->writeAttribute(
"role",
"bold");
3760 generateSimpleLink(linkForNode(node, relative), name);
3761 m_writer->writeEndElement();
3765 bool generateExtra,
bool generateType)
3767 const QString &pname = parameter.name();
3768 const QString &ptype = parameter.type();
3770 if (!pname.isEmpty()) {
3771 typified(ptype, relative,
true, generateType);
3777 if (generateExtra || pname.isEmpty()) {
3778 m_writer->writeStartElement(dbNamespace,
"emphasis");
3779 m_writer->writeCharacters(paramName);
3780 m_writer->writeEndElement();
3783 const QString &pvalue = parameter.defaultValue();
3784 if (generateExtra && !pvalue.isEmpty())
3785 m_writer->writeCharacters(
" = " + pvalue);
3797 const int MaxEnumValues = 6;
3799 if (generateExtra) {
3800 if (
auto extra = CodeMarker::extraSynopsis(node, style); !extra.isEmpty())
3801 m_writer->writeCharacters(extra +
" ");
3805 QString namePrefix {};
3809 namePrefix = taggedNode(node->parent()) +
"::";
3814 case NodeType::Namespace:
3815 m_writer->writeCharacters(
"namespace ");
3816 m_writer->writeCharacters(namePrefix);
3817 generateSynopsisName(node, relative, generateNameLink);
3819 case NodeType::Class:
3820 m_writer->writeCharacters(
"class ");
3821 m_writer->writeCharacters(namePrefix);
3822 generateSynopsisName(node, relative, generateNameLink);
3829 if (!func->isNonvirtual())
3830 m_writer->writeCharacters(QStringLiteral(
"virtual "));
3834 if (style != Section::AllMembers && !func->returnType().isEmpty())
3835 typified(func->returnTypeString(), relative,
true, generateType);
3836 m_writer->writeCharacters(namePrefix);
3837 generateSynopsisName(node, relative, generateNameLink);
3840 m_writer->writeCharacters(QStringLiteral(
"("));
3843 for (
int i = 0; i < parameters
.count(); i++) {
3845 m_writer->writeCharacters(QStringLiteral(
", "));
3846 generateParameter(parameters
.at(i
), relative, generateExtra, generateType);
3849 m_writer->writeCharacters(QStringLiteral(
")"));
3852 if (func->isConst())
3853 m_writer->writeCharacters(QStringLiteral(
" const"));
3859 synopsis += QStringLiteral(
" final");
3861 synopsis += QStringLiteral(
" override");
3863 synopsis += QStringLiteral(
" = 0");
3865 synopsis += QStringLiteral(
" &");
3867 synopsis += QStringLiteral(
" &&");
3868 m_writer->writeCharacters(synopsis);
3870 if (!func->returnType().isEmpty() && func->returnType() !=
"void") {
3871 m_writer->writeCharacters(QStringLiteral(
" : "));
3872 typified(func->returnTypeString(), relative,
false, generateType);
3877 synopsis += QStringLiteral(
" &");
3879 synopsis += QStringLiteral(
" &&");
3880 m_writer->writeCharacters(synopsis);
3884 const auto enume =
static_cast<
const EnumNode *>(node);
3886 m_writer->writeCharacters(
"enum "_L1);
3887 m_writer->writeCharacters(namePrefix);
3888 generateSynopsisName(node, relative, generateNameLink);
3889 }
else if (generateNameLink) {
3890 m_writer->writeStartElement(dbNamespace,
"emphasis");
3891 m_writer->writeAttribute(
"role",
"bold");
3892 generateSimpleLink(linkForNode(node, relative),
"enum");
3893 m_writer->writeEndElement();
3895 m_writer->writeCharacters(
"enum"_L1);
3902 QStringList documentedItems = enume
->doc().enumItemNames();
3903 if (documentedItems.isEmpty()) {
3904 const auto &enumItems = enume->items();
3905 for (
const auto &item : enumItems)
3906 documentedItems << item.name();
3908 const QStringList omitItems = enume
->doc().omitEnumItemNames();
3909 for (
const auto &item : omitItems)
3910 documentedItems.removeAll(item);
3912 if (documentedItems.size() > MaxEnumValues) {
3914 const QString last = documentedItems.last();
3915 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
3916 documentedItems +=
"…";
3917 documentedItems += last;
3919 synopsis += documentedItems.join(QLatin1String(
", "));
3921 if (!documentedItems.isEmpty())
3922 synopsis += QLatin1Char(
' ');
3923 synopsis += QLatin1Char(
'}');
3925 m_writer->writeCharacters(synopsis);
3929 auto templateDecl = node->templateDecl();
3931 m_writer->writeCharacters((*templateDecl).to_qstring() + QLatin1Char(
' '));
3933 m_writer->writeCharacters(namePrefix);
3934 generateSynopsisName(node, relative, generateNameLink);
3937 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
3938 m_writer->writeCharacters(
"flags ");
3939 m_writer->writeCharacters(namePrefix);
3940 generateSynopsisName(node, relative, generateNameLink);
3943 const auto property =
static_cast<
const PropertyNode *>(node);
3944 m_writer->writeCharacters(namePrefix);
3945 generateSynopsisName(node, relative, generateNameLink);
3946 m_writer->writeCharacters(
" : ");
3947 typified(property->qualifiedDataType(), relative,
false, generateType);
3950 const auto variable =
static_cast<
const VariableNode *>(node);
3952 generateSynopsisName(node, relative, generateNameLink);
3953 m_writer->writeCharacters(
" : ");
3954 typified(variable->dataType(), relative,
false, generateType);
3956 typified(variable->leftType(), relative,
false, generateType);
3957 m_writer->writeCharacters(
" ");
3958 m_writer->writeCharacters(namePrefix);
3959 generateSynopsisName(node, relative, generateNameLink);
3960 m_writer->writeCharacters(variable->rightType());
3964 m_writer->writeCharacters(namePrefix);
3965 generateSynopsisName(node, relative, generateNameLink);
3980 if (nativeEnum && nativeEnum->enumNode() && !enumValue.startsWith(
"%1."_L1.arg(nativeEnum->prefix()))) {
3981 m_writer->writeCharacters(
"%1.%2"_L1.arg(nativeEnum->prefix(), enumValue));
3986 if (!relative->isEnumType() || (relative->isEnumType(Genus::QML)
3987 && enumValue.section(
' ', 0, 0).contains(
'.'_L1))) {
3988 m_writer->writeCharacters(enumValue);
3992 QList<
const Node *> parents;
3994 parents.prepend(node);
4000 parents << relative;
4002 m_writer->writeStartElement(dbNamespace,
"code");
4003 for (
auto parent : parents) {
4004 generateSynopsisName(parent, relative,
true);
4005 m_writer->writeCharacters((relative->genus() == Genus::QML) ?
"."_L1 :
"::"_L1);
4008 m_writer->writeCharacters(enumValue);
4009 m_writer->writeEndElement();
4013
4014
4015
4020 Q_ASSERT(node && !node->name().isEmpty());
4026 m_writer->writeStartElement(dbNamespace,
"note");
4033 m_writer->writeStartElement(dbNamespace,
"para");
4034 m_writer->writeCharacters(
4035 "This function can be invoked via the meta-object system and from QML. See ");
4036 generateSimpleLink(node->url(),
"Q_INVOKABLE");
4037 m_writer->writeCharacters(
".");
4038 m_writer->writeEndElement();
4042 m_writer->writeTextElement(
4043 dbNamespace,
"para",
4044 "This is a private signal. It can be used in signal connections but "
4045 "cannot be emitted by the user.");
4049 QString handler(node->name());
4050 int prefixLocation = handler.lastIndexOf(
'.', -2) + 1;
4051 handler[prefixLocation] = handler[prefixLocation].toTitleCase();
4052 handler.insert(prefixLocation, QLatin1String(
"on"));
4053 m_writer->writeStartElement(dbNamespace,
"para");
4054 m_writer->writeCharacters(
"The corresponding handler is ");
4055 m_writer->writeTextElement(dbNamespace,
"code", handler);
4056 m_writer->writeCharacters(
".");
4057 m_writer->writeEndElement();
4065 const auto *fn =
static_cast<
const FunctionNode *>(node);
4066 auto nodes = fn->associatedProperties();
4067 if (nodes.isEmpty())
4072 QMap<PropertyNode::FunctionRole, QList<
const PropertyNode *>> roleGroups;
4073 for (
const auto *n : std::as_const(nodes)) {
4074 const auto *pn =
static_cast<
const PropertyNode *>(n);
4075 PropertyNode::FunctionRole role = pn->role(fn);
4076 roleGroups[role].append(pn);
4088 for (
auto role : roleOrder) {
4089 const auto it = roleGroups.constFind(role);
4090 if (it == roleGroups.cend())
4093 const auto &properties = it.value();
4098 msg = QStringLiteral(
"Getter function");
4101 msg = QStringLiteral(
"Setter function");
4104 msg = QStringLiteral(
"Resetter function");
4107 msg = QStringLiteral(
"Notifier signal");
4110 msg = QStringLiteral(
"Bindable function");
4116 m_writer->writeStartElement(dbNamespace,
"para");
4117 if (properties.size() == 1) {
4118 const auto *pn = properties.first();
4119 m_writer->writeCharacters(msg +
" for property ");
4120 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4121 m_writer->writeCharacters(
". ");
4123 m_writer->writeCharacters(msg +
" for properties ");
4124 for (qsizetype i = 0; i < properties.size(); ++i) {
4125 const auto *pn = properties.at(i);
4126 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4127 m_writer->writeCharacters(Utilities::separator(i, properties.size()));
4129 m_writer->writeCharacters(
" ");
4131 m_writer->writeEndElement();
4138 const Node *linkNode;
4140 QString link = getAutoLink(&linkAtom, node, &linkNode);
4141 m_writer->writeStartElement(dbNamespace,
"para");
4142 m_writer->writeCharacters(
"This property supports ");
4143 generateSimpleLink(link,
"QProperty");
4144 m_writer->writeCharacters(
" bindings.");
4145 m_writer->writeEndElement();
4150 const auto *func =
static_cast<
const FunctionNode *>(node);
4156 m_writer->writeStartElement(dbNamespace,
"para");
4159 auto writeDocBookLink = [&](
const QString &target,
const QString &label) {
4160 const Node *linkNode =
nullptr;
4162 const QString &link = getAutoLink(&linkAtom, node, &linkNode);
4164 m_writer->writeStartElement(dbNamespace,
"link");
4165 if (!link.isEmpty() && linkNode) {
4166 m_writer->writeAttribute(xlinkNamespace,
"href", link);
4168 m_writer->writeAttribute(dbNamespace,
"linkend", target);
4170 m_writer->writeCharacters(label);
4171 m_writer->writeEndElement();
4174 const QString &functionType = func
->isSignal() ?
"signal" :
"slot";
4175 const QString &configKey = func
->isSignal() ?
"overloadedsignalstarget" :
"overloadedslotstarget";
4176 const QString &defaultTarget = func
->isSignal() ?
"connecting-overloaded-signals" :
"connecting-overloaded-slots";
4177 const QString &linkTarget = Config::instance().get(configKey).asString(defaultTarget);
4179 m_writer->writeCharacters(
"This " + functionType +
" is overloaded. ");
4181 QString snippet = generateOverloadSnippet(func);
4182 if (!snippet.isEmpty()) {
4183 m_writer->writeCharacters(
"To connect to this " + functionType +
":");
4184 m_writer->writeEndElement();
4186 m_writer->writeStartElement(dbNamespace,
"programlisting");
4187 m_writer->writeCharacters(snippet);
4188 m_writer->writeEndElement();
4190 m_writer->writeStartElement(dbNamespace,
"para");
4193 m_writer->writeCharacters(
"For more examples and approaches, see ");
4194 writeDocBookLink(linkTarget,
"connecting to overloaded " + functionType +
"s");
4197 const auto &args = node
->doc().overloadList();
4198 if (args.first().first.isEmpty()) {
4199 m_writer->writeCharacters(
"This is an overloaded function.");
4201 QString target = args.first().first;
4204 if (!target.contains(
"::")) {
4207 target = parent->name() +
"::" + target;
4210 m_writer->writeCharacters(
"This function overloads ");
4212 const Node *linkNode =
nullptr;
4214 QString link = getAutoLink(&linkAtom, node, &linkNode);
4215 if (!link.isEmpty() && linkNode)
4216 generateSimpleLink(link, target);
4218 m_writer->writeCharacters(target);
4219 m_writer->writeCharacters(
".");
4223 m_writer->writeEndElement();
4232 m_writer->writeEndElement();
4240 bool closeSupplementarySection =
false;
4244 const QList<Node *> &collective = scn->collective();
4246 bool firstFunction =
true;
4247 for (
const auto *sharedNode : collective) {
4248 if (firstFunction) {
4249 startSectionBegin(sharedNode);
4251 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4252 m_writer->writeAttribute(
"renderas",
"sect2");
4253 writeXmlId(sharedNode);
4256 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4258 generateSynopsis(sharedNode, relative, Section::Details);
4260 if (firstFunction) {
4262 firstFunction =
false;
4264 m_writer->writeEndElement();
4271 startSectionBegin(node);
4273 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4277 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4278 m_writer->writeAttribute(
"renderas",
"sect2");
4280 m_writer->writeEndElement();
4283 startSectionBegin(node);
4285 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4290 Q_ASSERT(m_hasSection);
4299 closeSupplementarySection =
true;
4300 startSection(
"",
"Notes");
4304 const auto *func =
static_cast<
const FunctionNode *>(node);
4313 const auto property =
static_cast<
const PropertyNode *>(node);
4322 m_writer->writeStartElement(dbNamespace,
"para");
4324 m_writer->writeStartElement(dbNamespace,
"emphasis");
4325 m_writer->writeAttribute(
"role",
"bold");
4326 m_writer->writeCharacters(
"Access functions:");
4328 m_writer->writeEndElement();
4330 m_writer->writeEndElement();
4332 generateSectionList(section, node);
4339 m_writer->writeStartElement(dbNamespace,
"para");
4341 m_writer->writeStartElement(dbNamespace,
"emphasis");
4342 m_writer->writeAttribute(
"role",
"bold");
4343 m_writer->writeCharacters(
"Notifier signal:");
4345 m_writer->writeEndElement();
4347 m_writer->writeEndElement();
4349 generateSectionList(notifiers, node);
4353 const auto en =
static_cast<
const EnumNode *>(node);
4355 if (m_qflagsHref.isEmpty()) {
4356 Node *qflags =
m_qdb->findClassNode(QStringList(
"QFlags"));
4358 m_qflagsHref = linkForNode(qflags,
nullptr);
4362 m_writer->writeStartElement(dbNamespace,
"para");
4363 m_writer->writeCharacters(
"The ");
4364 m_writer->writeStartElement(dbNamespace,
"code");
4365 m_writer->writeCharacters(en->flagsType()->name());
4366 m_writer->writeEndElement();
4367 m_writer->writeCharacters(
" type is a typedef for ");
4368 m_writer->writeStartElement(dbNamespace,
"code");
4369 generateSimpleLink(m_qflagsHref,
"QFlags");
4370 m_writer->writeCharacters(
"<" + en->name() +
">. ");
4371 m_writer->writeEndElement();
4372 m_writer->writeCharacters(
"It stores an OR combination of ");
4373 m_writer->writeStartElement(dbNamespace,
"code");
4374 m_writer->writeCharacters(en->name());
4375 m_writer->writeEndElement();
4376 m_writer->writeCharacters(
" values.");
4377 m_writer->writeEndElement();
4382 if (closeSupplementarySection)
4393 bool useObsoleteMembers)
4398 if (!members.isEmpty()) {
4399 bool hasPrivateSignals =
false;
4400 bool isInvokable =
false;
4402 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4404 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4407 NodeVector::ConstIterator m = members.constBegin();
4408 while (m != members.constEnd()) {
4414 m_writer->writeStartElement(dbNamespace,
"listitem");
4416 m_writer->writeStartElement(dbNamespace,
"para");
4419 generateSynopsis(*m, relative, section
.style());
4420 if ((*m)->isFunction()) {
4422 if (fn->isPrivateSignal())
4423 hasPrivateSignals =
true;
4424 else if (fn->isInvokable())
4428 m_writer->writeEndElement();
4430 m_writer->writeEndElement();
4436 m_writer->writeEndElement();
4439 if (hasPrivateSignals)
4446 && !section.inheritedMembers().isEmpty()) {
4447 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4449 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4452 generateSectionInheritedList(section, relative);
4454 m_writer->writeEndElement();
4462 QList<std::pair<Aggregate *,
int>>::ConstIterator p = section.inheritedMembers().constBegin();
4463 while (p != section.inheritedMembers().constEnd()) {
4464 m_writer->writeStartElement(dbNamespace,
"listitem");
4465 m_writer->writeCharacters(QString::number((*p).second) + u' ');
4466 if ((*p).second == 1)
4467 m_writer->writeCharacters(section.singular());
4469 m_writer->writeCharacters(section.plural());
4470 m_writer->writeCharacters(
" inherited from ");
4471 generateSimpleLink(fileName((*p).first) +
'#'
4472 + Generator::cleanRef(section.title().toLower()),
4473 (*p).first->plainFullName(relative));
4479
4480
4481
4485 Q_ASSERT(m_writer ==
nullptr);
4486 m_writer = startDocument(pn);
4488 generateHeader(pn->fullTitle(), pn->subtitle(), pn);
4497
4498
4503 Q_ASSERT(m_writer ==
nullptr);
4504 m_writer = startDocument(qcn);
4507 QString title = qcn->name();
4509 title.append(
" QML Value Type");
4511 title.append(
" QML Type");
4514 title.append(
" (Singleton)");
4520 generateHeader(title, qcn->subtitle(), qcn);
4525 m_writer->writeStartElement(dbNamespace,
"note");
4526 m_writer->writeStartElement(dbNamespace,
"para");
4527 m_writer->writeStartElement(dbNamespace,
"emphasis");
4528 m_writer->writeAttribute(
"role",
"bold");
4529 m_writer->writeCharacters(
"Note: ");
4530 m_writer->writeEndElement();
4531 m_writer->writeCharacters(
"This type is a QML singleton. "
4532 "There is only one instance of this type in the QML engine.");
4533 m_writer->writeEndElement();
4534 m_writer->writeEndElement();
4537 startSection(
"details",
"Detailed Description");
4545 for (
const auto §ion : sections.stdQmlTypeDetailsSections()) {
4546 if (!section.isEmpty()) {
4547 startSection(section.title().toLower(), section.title());
4549 for (
const auto &member : section.members())
4550 generateDetailedQmlMember(member, qcn);
4556 generateObsoleteQmlMembers(sections);
4565
4566
4567
4574 if (!title.isEmpty())
4578 title += n->element() + QLatin1Char(
'.');
4579 title += n->name() +
" : " + n->dataType();
4584 auto generateQmlMethodTitle = [&](
Node *node) {
4592 if (!scn->name().isEmpty())
4593 heading = scn->name() +
" group";
4595 heading = node->name();
4596 startSection(scn, heading);
4601 const QList<Node *> sharedNodes = scn->collective();
4602 for (
const auto &sharedNode : sharedNodes) {
4603 if (sharedNode->isQmlProperty()) {
4604 auto *qpn =
static_cast<QmlPropertyNode *>(sharedNode);
4606 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4607 m_writer->writeAttribute(
"renderas",
"sect2");
4609 m_writer->writeCharacters(getQmlPropertyTitle(qpn));
4610 m_writer->writeEndElement();
4613 generateDocBookSynopsis(qpn);
4618 startSection(qpn, getQmlPropertyTitle(qpn));
4622 const QList<Node *> &sharedNodes = scn->collective();
4627 for (
const auto &sharedNode : sharedNodes) {
4629 if (!sharedNode->isFunction(Genus::QML) && !sharedNode->isQmlProperty()) {
4635 startSectionBegin(sharedNode);
4637 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4638 m_writer->writeAttribute(
"renderas",
"sect2");
4642 if (sharedNode->isFunction(Genus::QML))
4643 generateQmlMethodTitle(sharedNode);
4644 else if (sharedNode->isQmlProperty())
4645 m_writer->writeCharacters(
4646 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(sharedNode)));
4652 m_writer->writeEndElement();
4653 generateDocBookSynopsis(sharedNode);
4659 startSectionBegin(refForNode(node));
4662 generateQmlMethodTitle(node);
4663 else if (node->isQmlProperty())
4664 m_writer->writeCharacters(
4665 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(node)));
4670 startSectionBegin(node);
4674 startSectionBegin(node);
4675 generateQmlMethodTitle(node);
4689
4690
4697 if (!node->url().isNull())
4701 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4744 generateCppReferencePage(
static_cast<
Aggregate *>(node));
4754 auto *aggregate =
static_cast<
Aggregate *>(node);
4755 for (
auto c : aggregate->childNodes()) {
4756 if (node->isPageNode() && !node->isPrivate())
4757 generateDocumentation(c);
4768 Q_ASSERT(m_writer ==
nullptr);
4769 m_writer = startDocument(aggregate);
4772 generateHeader(aggregate->plainFullName(),
"", aggregate);
4777 if (!aggregate
->doc().isEmpty()) {
4778 startSection(
"details",
"Detailed Description");
4780 generateBody(aggregate);
4789 for (
const auto §ion : std::as_const(*detailsSections)) {
4790 if (section.isEmpty())
4793 startSection(section.title().toLower(), section.title());
4795 const QList<Node *> &members = section.members();
4796 for (
const auto &member : members) {
4797 if (!member->isClassNode()) {
4798 generateDetailedMember(member, aggregate);
4800 startSectionBegin();
4801 generateFullName(member, aggregate);
4804 generateBrief(member);
4818
4819
4824 Q_ASSERT(m_writer ==
nullptr);
4825 m_writer = startDocument(cn);
4828 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4834 if (cn
->genus() != Genus::DOC && cn
->genus() != Genus::DontCare) {
4845 if (!nmm.isEmpty()) {
4846 startSection(
"namespaces",
"Namespaces");
4847 generateAnnotatedList(cn, nmm.values(),
"namespaces");
4851 if (!nmm.isEmpty()) {
4852 startSection(
"classes",
"Classes");
4853 generateAnnotatedList(cn, nmm.values(),
"classes");
4859 bool generatedTitle =
false;
4861 startSection(
"details",
"Detailed Description");
4862 generatedTitle =
true;
4867 !cn
->doc().body().isEmpty() ||
4869 !cn
->doc().alsoList().empty() ||
4872 writeAnchor(
"details");
4878 if (!cn->noAutoList() && (cn->isGroup() || cn->isQmlModule()))
4879 generateAnnotatedList(cn, cn->members(),
"members", AutoSection);
4890
4891
4892
4893
4898 QString name = cn->name().toLower();
4899 name.replace(QChar(
' '), QString(
"-"));
4900 QString filename = cn->tree()->physicalModuleName() +
"-" + name +
"." + fileExtension();
4903 Q_ASSERT(m_writer ==
nullptr);
4904 m_writer = startGenericDocument(cn, filename);
4907 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4913 m_writer->writeStartElement(dbNamespace,
"para");
4914 m_writer->writeCharacters(
"Each function or type documented here is related to a class or "
4915 "namespace that is documented in a different module. The reference "
4916 "page for that class or namespace will link to the function or type "
4918 m_writer->writeEndElement();
4922 for (
const auto &member : members)
4923 generateDetailedMember(member, cnc);
4936 m_writer->writeStartElement(dbNamespace,
"link");
4937 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(node));
4938 m_writer->writeAttribute(xlinkNamespace,
"role", targetType(node));
4939 m_writer->writeCharacters(node->fullName(relative));
4940 m_writer->writeEndElement();
4944 const Node *actualNode)
4946 Q_ASSERT(apparentNode);
4947 Q_ASSERT(actualNode);
4950 m_writer->writeStartElement(dbNamespace,
"link");
4951 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(actualNode));
4952 m_writer->writeAttribute(
"role", targetType(actualNode));
4953 m_writer->writeCharacters(fullName);
4954 m_writer->writeEndElement();
#define ATOM_FORMATTING_TELETYPE
#define ATOM_LIST_LOWERALPHA
#define ATOM_FORMATTING_UNDERLINE
#define ATOM_LIST_UPPERALPHA
#define ATOM_FORMATTING_NOTRANSLATE
#define ATOM_LIST_LOWERROMAN
#define ATOM_FORMATTING_SUBSCRIPT
#define ATOM_FORMATTING_BOLD
#define ATOM_FORMATTING_TRADEMARK
#define ATOM_FORMATTING_ITALIC
#define ATOM_LIST_UPPERROMAN
#define ATOM_FORMATTING_LINK
#define ATOM_FORMATTING_SUPERSCRIPT
#define ATOM_FORMATTING_UICONTROL
#define ATOM_FORMATTING_PARAMETER
The Atom class is the fundamental unit for representing documents internally.
AtomType type() const
Return the type of this atom.
const Atom * next() const
Return the next atom in the atom list.
The ClassNode represents a C++ class.
virtual Atom::AtomType atomType() const
A class for holding the members of a collection of doc pages.
const NodeList & members() const
bool wasSeen() const override
Returns the seen flag data member of this node if it is a NamespaceNode or a CollectionNode.
NodeMap getMembers(NodeType type) const
void generatePageNode(PageNode *pn)
Generate the DocBook page for an entity that doesn't map to any underlying parsable C++ or QML elemen...
void generateQmlTypePage(QmlTypeNode *qcn)
Generate the DocBook page for a QML type.
void generateAlsoList(const Node *node) override
void generateQmlRequisites(const QmlTypeNode *qcn)
Lists the required imports and includes.
void generateAddendum(const Node *node, Generator::Addendum type, CodeMarker *marker, AdmonitionPrefix prefix) override
Generates an addendum note of type type for node.
void initializeGenerator() override
Initializes the DocBook output generator's data structures from the configuration (Config).
void generateExampleFilePage(const Node *en, ResolvedFile resolved_file, CodeMarker *=nullptr) override
Generate a file with the contents of a C++ or QML source file.
bool generateText(const Text &text, const Node *relative) override
Generate the documentation for relative.
void generateCppReferencePage(Node *node)
Generate a reference page for the C++ class, namespace, or header file documented in node.
void generateHeader(const QString &title, const QString &subtitle, const Node *node)
Generate the DocBook header for the file, including the abstract.
void generateSortedQmlNames(const Node *base, const QStringList &knownTypes, const NodeList &subs)
DocBookGenerator(FileResolver &file_resolver)
bool generateThreadSafeness(const Node *node)
Generates text that explains how threadsafe and/or reentrant node is.
void generateCollectionNode(CollectionNode *cn)
Generate the HTML page for a group, module, or QML module.
QString format() override
void generateDocBookSynopsis(const Node *node)
Generate the metadata for the given node in DocBook.
void generateGenericCollectionPage(CollectionNode *cn)
Generate the HTML page for a generic collection.
void generateList(const Node *relative, const QString &selector, Qt::SortOrder sortOrder=Qt::AscendingOrder)
void generateBody(const Node *node)
Generate the body of the documentation from the qdoc comment found with the entity represented by the...
qsizetype generateAtom(const Atom *atom, const Node *relative, CodeMarker *) override
Generate DocBook from an instance of Atom.
void generateProxyPage(Aggregate *aggregate)
bool generateStatus(const Node *node)
void generateRequisites(const Aggregate *inner)
Lists the required imports and includes.
void generateSortedNames(const ClassNode *cn, const QList< RelatedClass > &rc)
void generateDocumentation(Node *node) override
Recursive writing of DocBook files from the root node.
void generateGroupReferenceText(const Node *node)
Return a string representing a text that exposes information about the groups that the node is part o...
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 isPrimaryOverload() const
bool isMacroWithoutParams() const
bool isPrivateSignal() const
const Parameters & parameters() const
bool isPureVirtual() const override
bool isDefault() const override
Returns true if the QML property node is marked as default.
bool hasOverloads() const
Returns true if this function has overloads.
bool isMacro() const override
returns true if either FunctionNode::isMacroWithParams() or FunctionNode::isMacroWithoutParams() retu...
bool hasAssociatedProperties() const
bool generateComparisonCategory(const Node *node, CodeMarker *marker=nullptr)
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)
void generateEnumValuesForQmlReference(const Node *node, CodeMarker *marker)
virtual int skipAtoms(const Atom *atom, Atom::AtomType type) const
bool m_threeColumnEnumValueTable
virtual void initializeGenerator()
No-op base implementation.
void initializeTextOutput()
Resets the variables used during text output.
static bool isIncluded(const InclusionPolicy &policy, const NodeContext &context)
This class represents a C++ namespace.
NamespaceNode * docNode() const
Returns a pointer to the NamespaceNode that represents where the namespace documentation is actually ...
Tree * tree() const override
Returns a pointer to the Tree that contains this NamespaceNode.
Interface implemented by Node subclasses that can refer to a C++ enum.
virtual const NativeEnum * nativeEnum() const =0
Encapsulates information about native (C++) enum values.
A PageNode is a Node that generates a documentation page.
bool noAutoList() const
Returns the value of the no auto-list flag.
The Parameter class describes one function parameter.
This class describes one instance of using the Q_PROPERTY macro.
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.
void mergeCollections(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...
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(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...
static void subclasses(const Node *base, NodeList &subs, bool recurse=false)
Loads the list subs with the nodes of all the subclasses of base.
QmlTypeNode * qmlBaseNode() const override
If this Aggregate is a QmlTypeNode, this function returns a pointer to the QmlTypeNode that is its ba...
CollectionNode * logicalModule() const override
If this is a QmlTypeNode, a pointer to its QML module is returned, which is a pointer to a Collection...
A class for containing the elements of one documentation section.
const NodeVector & obsoleteMembers() const
void appendMembers(const NodeVector &nv)
const NodeVector & members() const
A class for creating vectors of collections for documentation.
Aggregate * aggregate() const
Sections(Aggregate *aggregate)
This constructor builds the vectors of sections based on the type of the aggregate node.
SectionVector & stdDetailsSections()
SectionVector & stdCppClassDetailsSections()
bool hasObsoleteMembers(SectionPtrVector *summary_spv, SectionPtrVector *details_spv) const
Returns true if any sections in this object contain obsolete members.
static Text sectionHeading(const Atom *sectionBegin)
const Atom * firstAtom() const
Text & operator=(const Text &text)
const Atom * lastAtom() const
bool isStatic() const override
Returns true if the FunctionNode represents a static function.
static bool isThreeColumnEnumValueTable(const Atom *atom)
Determines whether the list atom should be shown with three columns (constant-value-description).
static bool isOneColumnValueTable(const Atom *atom)
Determines whether the list atom should be shown with just one column (value).
static void rewritePropertyBrief(const Atom *atom, const Node *relative)
Rewrites the brief of this node depending on its first word.
static int hOffset(const Node *node)
Header offset depending on the type of the node.
static bool hasBrief(const Node *node)
Do not display.
XmlGenerator(FileResolver &file_resolver)
static const QRegularExpression m_funcLeftParen
static NodeType typeFromString(const Atom *atom)
Returns the type of this atom as an enumeration.
#define CONFIG_DOCBOOKEXTENSIONS
#define CONFIG_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
The Node class is the base class for all the nodes in QDoc's parse tree.
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 isEnumType(Genus g) const
bool isGroup() const
Returns true if the node type is Group.
virtual bool docMustBeGenerated() const
This function is called to perform a test to decide if the node must have documentation generated.
bool isPrivate() const
Returns true if this node's access is Private.
bool isNamespace() const
Returns true if the node type is Namespace.
bool isTypedef() const
Returns true if the node type is Typedef.
bool isQmlBasicType() const
Returns true if the node type is QmlBasicType.
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
bool isSharedCommentNode() const
Returns true if the node type is SharedComment.
bool isHeader() const
Returns true if the node type is HeaderFile.
NodeType nodeType() const override
Returns this node's type.
Genus genus() const override
Returns this node's Genus.
virtual bool isPageNode() const
Returns true if this node represents something that generates a documentation page.
bool isEnumType() const
Returns true if the node type is Enum.
virtual Status status() const
Returns the node's status value.
virtual bool isTextPageNode() const
Returns true if the node is a PageNode but not an Aggregate.
Aggregate * parent() const
Returns the node's parent pointer.
bool isVariable() const
Returns true if the node type is Variable.
virtual bool isDeprecated() const
Returns true if this node's status is Deprecated.
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
static bool nodeNameLessThan(const Node *first, const Node *second)
Returns true if the node n1 is less than node n2.
const Location & location() const
If this node's definition location is empty, this function returns this node's declaration location.
bool isProxyNode() const
Returns true if the node type is Proxy.
Access access() const
Returns the node's Access setting, which can be Public, Protected, or Private.
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
ThreadSafeness threadSafeness() const
Returns the thread safeness value for whatever this node represents.
virtual bool isMarkedReimp() const
Returns true if the FunctionNode is marked as a reimplemented function.
bool isProperty() const
Returns true if the node type is Property.
NodeContext createContext() const
bool isModule() const
Returns true if the node type is Module.
bool isClass() const
Returns true if the node type is Class.
virtual bool isPropertyGroup() const
Returns true if the node is a SharedCommentNode for documenting multiple C++ properties or multiple Q...
ThreadSafeness
An unsigned char that specifies the degree of thread-safeness of the element.
bool isSharingComment() const
This function returns true if the node is sharing a comment with other nodes.
bool hasDoc() const
Returns true if this node is documented, or it represents a documented node read from the index ('had...
bool isRelatedNonmember() const
Returns true if this is a related nonmember of something.
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
virtual bool isCollectionNode() const
Returns true if this is an instance of CollectionNode.
static bool nodeSortKeyOrNameLessThan(const Node *n1, const Node *n2)
Returns true if node n1 is less than node n2 when comparing the sort keys, defined with.
bool isQmlModule() const
Returns true if the node type is QmlModule.
bool isExample() const
Returns true if the node type is Example.
bool isIndexNode() const
Returns true if this node was created from something in an index file.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.
A class for parsing and managing a function parameter list.
const Parameter & at(int i) const
Represents a file that is reachable by QDoc based on its current configuration.