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, outputDir() + QLatin1String(
"/images"));
622 m_writer->writeTextElement(dbNamespace,
"alt", atom->next()->string());
626 m_writer->writeStartElement(dbNamespace,
"imageobject");
628 m_writer->writeEmptyElement(dbNamespace,
"imagedata");
630 m_writer->writeAttribute(
"fileref",
"images/" + file_name);
632 m_writer->writeEndElement();
636 setImageFileName(relative,
"images/" + file_name);
639 m_writer->writeEndElement();
643 if (m_closeFigureWrapper) {
644 m_writer->writeEndElement();
646 m_closeFigureWrapper =
false;
654 QString admonType = atom->typeString().toLower();
657 m_writer->writeStartElement(dbNamespace, admonType);
659 m_writer->writeStartElement(dbNamespace,
"para");
662 case Atom::ImportantRight:
663 case Atom::NoteRight:
664 case Atom::WarningRight:
665 m_writer->writeEndElement();
668 m_writer->writeEndElement();
676 const Node *node =
nullptr;
677 QString link = getLink(atom, relative, &node);
678 beginLink(link, node, relative);
682 const Node *node =
static_cast<
const Node*>(Utilities::nodeForString(atom->string()));
683 beginLink(linkForNode(node, relative), node, relative);
693 m_writer->writeEndElement();
699 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
702 m_writer->writeStartElement(dbNamespace,
"variablelist");
705 m_writer->writeStartElement(dbNamespace,
"informaltable");
707 m_writer->writeStartElement(dbNamespace,
"thead");
709 m_writer->writeStartElement(dbNamespace,
"tr");
711 m_writer->writeTextElement(dbNamespace,
"th",
"Constant");
717 m_writer->writeTextElement(dbNamespace,
"th",
"Value");
722 m_writer->writeTextElement(dbNamespace,
"th",
"Description");
726 m_writer->writeEndElement();
728 m_writer->writeEndElement();
731 m_writer->writeStartElement(dbNamespace,
"orderedlist");
733 if (atom->next() !=
nullptr && atom->next()->string().toInt() > 1)
734 m_writer->writeAttribute(
"startingnumber", atom->next()->string());
737 m_writer->writeAttribute(
"numeration",
"upperalpha");
739 m_writer->writeAttribute(
"numeration",
"loweralpha");
741 m_writer->writeAttribute(
"numeration",
"upperroman");
743 m_writer->writeAttribute(
"numeration",
"lowerroman");
745 m_writer->writeAttribute(
"numeration",
"arabic");
755 m_writer->writeStartElement(dbNamespace,
"varlistentry");
757 m_writer->writeStartElement(dbNamespace,
"item");
759 std::pair<QString,
int> pair = getAtomListValue(atom);
760 skipAhead = pair.second;
762 m_writer->writeStartElement(dbNamespace,
"tr");
764 m_writer->writeStartElement(dbNamespace,
"td");
766 m_writer->writeStartElement(dbNamespace,
"para");
768 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
769 generateEnumValue(pair.first, relative);
770 m_writer->writeEndElement();
772 m_writer->writeEndElement();
776 const auto enume =
static_cast<
const EnumNode *>(relative);
777 QString itemValue = enume->itemValue(atom
->next()->string());
779 m_writer->writeStartElement(dbNamespace,
"td");
780 if (itemValue.isEmpty())
781 m_writer->writeCharacters(
"?");
783 m_writer->writeStartElement(dbNamespace,
"code");
785 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
786 m_writer->writeCharacters(itemValue);
787 m_writer->writeEndElement();
789 m_writer->writeEndElement();
797 m_writer->writeEndElement();
803 m_writer->writeEndElement();
810 m_inListItemLineOpen =
false;
812 m_writer->writeStartElement(dbNamespace,
"listitem");
814 m_writer->writeStartElement(dbNamespace,
"para");
819 m_writer->writeEmptyElement(dbNamespace,
"td");
821 m_inListItemLineOpen =
false;
823 m_writer->writeStartElement(dbNamespace,
"td");
825 m_inListItemLineOpen =
true;
829 m_writer->writeStartElement(dbNamespace,
"listitem");
838 m_writer->writeEndElement();
841 m_writer->writeEndElement();
843 m_writer->writeEndElement();
846 if (m_inListItemLineOpen) {
847 m_writer->writeEndElement();
849 m_inListItemLineOpen =
false;
851 m_writer->writeEndElement();
854 m_writer->writeEndElement();
859 case Atom::ListRight:
865 m_writer->writeEndElement();
872 m_writer->writeStartElement(dbNamespace,
"para");
878 m_writer->writeEndElement();
883 case Atom::QuotationLeft:
884 m_writer->writeStartElement(dbNamespace,
"blockquote");
885 m_inBlockquote =
true;
887 case Atom::QuotationRight:
888 m_writer->writeEndElement();
890 m_inBlockquote =
false;
893 m_writer->device()->write(atom->string().toUtf8());
899 currentSectionLevel = atom->string().toInt() +
hOffset(relative
);
901 if (currentSectionLevel > 1) {
904 while (!sectionLevels.empty() && sectionLevels.top() >= currentSectionLevel) {
906 m_writer->writeEndElement();
910 sectionLevels.push(currentSectionLevel);
912 m_writer->writeStartElement(dbNamespace,
"section");
913 writeXmlId(Tree::refForAtom(atom));
926 generateAtom(atom->next(), relative,
nullptr);
927 generateAtom(atom->next()->next(), relative,
nullptr);
928 generateAtom(atom->next()->next()->next(), relative,
nullptr);
930 m_closeSectionAfterGeneratedList =
true;
937 m_writer->writeTextElement(dbNamespace,
"title",
"");
946 if (currentSectionLevel > 1) {
947 m_writer->writeStartElement(dbNamespace,
"title");
953 if (currentSectionLevel > 1) {
954 m_writer->writeEndElement();
959 case Atom::SidebarLeft:
960 m_writer->writeStartElement(dbNamespace,
"sidebar");
962 case Atom::SidebarRight:
963 m_writer->writeEndElement();
970 m_writer->writeCharacters(atom->string());
973 std::pair<QString, QString> pair = getTableWidthAttr(atom);
974 QString attr = pair.second;
975 QString width = pair.first;
978 m_writer->writeEndElement();
983 m_tableHeaderAlreadyOutput =
false;
985 m_writer->writeStartElement(dbNamespace,
"informaltable");
986 m_writer->writeAttribute(
"style", attr);
987 if (!width.isEmpty())
988 m_writer->writeAttribute(
"width", width);
991 case Atom::TableRight:
992 m_tableWidthAttr = {
"",
""};
993 m_writer->writeEndElement();
1002 if (m_tableHeaderAlreadyOutput) {
1005 m_writer->writeEndElement();
1008 const QString &attr = m_tableWidthAttr.second;
1009 const QString &width = m_tableWidthAttr.first;
1011 m_writer->writeStartElement(dbNamespace,
"informaltable");
1012 m_writer->writeAttribute(
"style", attr);
1013 if (!width.isEmpty())
1014 m_writer->writeAttribute(
"width", width);
1017 m_tableHeaderAlreadyOutput =
true;
1023 id = Utilities::asAsciiPrintable(next->string());
1028 m_writer->writeStartElement(dbNamespace,
"thead");
1030 m_writer->writeStartElement(dbNamespace,
"tr");
1036 m_closeTableCell =
true;
1037 m_writer->writeStartElement(dbNamespace,
"td");
1043 if (m_closeTableCell) {
1044 m_closeTableCell =
false;
1045 m_writer->writeEndElement();
1049 m_writer->writeEndElement();
1053 m_writer->writeStartElement(dbNamespace,
"tr");
1056 m_writer->writeEndElement();
1068 bool hasTarget {
false};
1070 id = Utilities::asAsciiPrintable(atom
->next()->string());
1075 m_writer->writeStartElement(dbNamespace,
"tr");
1078 if (atom->string().isEmpty()) {
1079 m_writer->writeAttribute(
"valign",
"top");
1084 QStringList args = atom->string().split(
"\"", Qt::SkipEmptyParts);
1087 const int nArgs = args.size();
1092 QStringLiteral(
"Error when parsing attributes for the table: got \"%1\"")
1093 .arg(atom->string()));
1095 for (
int i = 0; i + 1 < nArgs; i += 2) {
1098 const QString &attr = args.at(i).chopped(1);
1101 writeXmlId(args.at(i + 1));
1103 m_writer->writeAttribute(attr, args.at(i + 1));
1119 m_closeTableRow =
true;
1120 m_writer->writeEndElement();
1126 if (m_closeTableRow) {
1127 m_closeTableRow =
false;
1128 m_writer->writeEndElement();
1132 m_writer->writeEndElement();
1135 case Atom::TableItemLeft:
1136 m_writer->writeStartElement(dbNamespace, m_inTableHeader ?
"th" :
"td");
1138 for (
int i = 0; i < atom->count(); ++i) {
1139 const QString &p = atom->string(i);
1140 if (p.contains(
'=')) {
1141 QStringList lp = p.split(QLatin1Char(
'='));
1142 m_writer->writeAttribute(lp.at(0), lp.at(1));
1144 QStringList spans = p.split(QLatin1Char(
','));
1145 if (spans.size() == 2) {
1146 if (spans.at(0) !=
"1")
1147 m_writer->writeAttribute(
"colspan", spans.at(0).trimmed());
1148 if (spans.at(1) !=
"1")
1149 m_writer->writeAttribute(
"rowspan", spans.at(1).trimmed());
1156 case Atom::TableItemRight:
1157 m_writer->writeEndElement();
1169 QString nextId = Utilities::asAsciiPrintable(
1171 QString ownId = Utilities::asAsciiPrintable(atom->string());
1172 if (nextId == ownId)
1176 writeAnchor(Utilities::asAsciiPrintable(atom->string()));
1178 case Atom::UnhandledFormat:
1179 m_writer->writeStartElement(dbNamespace,
"emphasis");
1180 m_writer->writeAttribute(
"role",
"bold");
1181 m_writer->writeCharacters(
"<Missing DocBook>");
1182 m_writer->writeEndElement();
1184 case Atom::UnknownCommand:
1185 m_writer->writeStartElement(dbNamespace,
"emphasis");
1186 m_writer->writeAttribute(
"role",
"bold");
1188 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1189 m_writer->writeCharacters(
"<Unknown command>");
1190 m_writer->writeStartElement(dbNamespace,
"code");
1191 m_writer->writeCharacters(atom->string());
1192 m_writer->writeEndElement();
1193 m_writer->writeEndElement();
1213 if (classMap.isEmpty())
1216 std::function<
void(
ClassNode *)> generateClassAndChildren
1217 = [
this, &relative, &generateClassAndChildren](ClassNode * classe) {
1218 m_writer->writeStartElement(dbNamespace,
"listitem");
1222 m_writer->writeStartElement(dbNamespace,
"para");
1223 generateFullName(classe, relative);
1224 m_writer->writeEndElement();
1228 bool hasChild =
false;
1229 for (
const RelatedClass &relatedClass : classe->derivedClasses()) {
1230 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1237 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1240 for (
const RelatedClass &relatedClass: classe->derivedClasses()) {
1241 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1242 generateClassAndChildren(relatedClass.m_node);
1246 m_writer->writeEndElement();
1251 m_writer->writeEndElement();
1255 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1258 for (
const auto &it : classMap) {
1259 auto *classe =
static_cast<ClassNode *>(it);
1260 if (classe->baseClasses().isEmpty())
1261 generateClassAndChildren(classe);
1264 m_writer->writeEndElement();
1275 if (match.hasMatch()) {
1277 qsizetype leftParenLoc = match.capturedStart(1);
1278 m_writer->writeCharacters(atom->string().left(leftParenLoc));
1280 m_writer->writeCharacters(atom->string().mid(leftParenLoc));
1284 m_writer->writeCharacters(atom->string());
1288
1289
1290
1294 m_writer->writeStartElement(dbNamespace,
"link");
1295 m_writer->writeAttribute(xlinkNamespace,
"href", link);
1296 if (node && !(relative && node->status() == relative->status())
1297 && node->isDeprecated())
1298 m_writer->writeAttribute(
"role",
"deprecated");
1307 m_writer->writeEndElement();
1313 Qt::SortOrder sortOrder)
1318 if (selector == QLatin1String(
"overviews"))
1320 else if (selector == QLatin1String(
"cpp-modules"))
1322 else if (selector == QLatin1String(
"qml-modules"))
1328 const QList<CollectionNode *> collectionList = cnm.values();
1329 nodeList.reserve(collectionList.size());
1330 for (
auto *collectionNode : collectionList)
1331 nodeList.append(collectionNode);
1332 generateAnnotatedList(relative, nodeList, selector, Auto, sortOrder);
1335
1336
1337
1338 Node *n =
const_cast<
Node *>(relative);
1341 generateAnnotatedList(cn, cn->members(), selector, Auto, sortOrder);
1346
1347
1348
1350 const QString &selector, GeneratedListType type,
1351 Qt::SortOrder sortOrder)
1353 if (nodeList.isEmpty())
1357 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1358 if (
std::all_of(nodeList.cbegin(), nodeList.cend(), [&policy](
const Node *n) {
1360 return !InclusionFilter::isIncluded(policy, context) || n->isDeprecated();
1367 bool noItemsHaveTitle =
1368 type == ItemizedList ||
std::all_of(nodeList.begin(), nodeList.end(),
1369 [](
const Node* node) {
1370 return node->doc().briefText().toString().isEmpty();
1374 if (type == AutoSection && m_hasSection)
1375 startSection(
"",
"Contents");
1378 if (!nodeList.isEmpty()) {
1379 m_writer->writeStartElement(dbNamespace, noItemsHaveTitle ?
"itemizedlist" :
"variablelist");
1380 m_writer->writeAttribute(
"role", selector);
1384 if (sortOrder == Qt::DescendingOrder)
1388 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1389 for (
const auto &node : std::as_const(members)) {
1390 const NodeContext context = node->createContext();
1391 if (!InclusionFilter::isIncluded(policy, context) || node->isDeprecated())
1394 if (noItemsHaveTitle) {
1395 m_writer->writeStartElement(dbNamespace,
"listitem");
1397 m_writer->writeStartElement(dbNamespace,
"para");
1399 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1401 m_writer->writeStartElement(dbNamespace,
"term");
1403 generateFullName(node, relative);
1404 if (noItemsHaveTitle) {
1405 m_writer->writeEndElement();
1407 m_writer->writeEndElement();
1409 m_writer->writeEndElement();
1411 m_writer->writeStartElement(dbNamespace,
"listitem");
1413 m_writer->writeStartElement(dbNamespace,
"para");
1414 m_writer->writeCharacters(node->doc().briefText().toString());
1415 m_writer->writeEndElement();
1417 m_writer->writeEndElement();
1419 m_writer->writeEndElement();
1424 m_writer->writeEndElement();
1428 if (type == AutoSection && m_hasSection)
1433
1434
1435
1437 const QString &selector)
1440 for (
const QString &name : nmm.uniqueKeys()) {
1441 if (!name.isEmpty())
1442 startSection(name.toLower(), name);
1443 generateAnnotatedList(relative, nmm.values(name), selector);
1444 if (!name.isEmpty())
1450
1451
1452
1453
1454
1455
1456
1457
1458
1460 bool includeAlphabet,
const QString &commonPrefix,
1461 const QString &selector)
1471 const int NumParagraphs = 37;
1472 qsizetype commonPrefixLen = commonPrefix.size();
1475
1476
1477
1478
1479
1481 QString paragraphName[NumParagraphs + 1];
1482 QSet<
char> usedParagraphNames;
1484 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
1485 QStringList pieces = c.key().split(
"::");
1486 int idx = commonPrefixLen;
1487 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
1489 QString last = pieces.last().toLower();
1490 QString key = last.mid(idx);
1492 int paragraphNr = NumParagraphs - 1;
1494 if (key[0].digitValue() != -1) {
1495 paragraphNr = key[0].digitValue();
1496 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
1497 paragraphNr = 10 + key[0].unicode() -
'a';
1500 paragraphName[paragraphNr] = key[0].toUpper();
1501 usedParagraphNames.insert(key[0].toLower().cell());
1502 paragraph[paragraphNr].insert(last, c.value());
1506
1507
1508
1509
1510
1511
1512
1513 int paragraphOffset[NumParagraphs + 1];
1514 paragraphOffset[0] = 0;
1515 for (
int i = 0; i < NumParagraphs; i++)
1516 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
1519 if (includeAlphabet && !usedParagraphNames.isEmpty()) {
1520 m_writer->writeStartElement(dbNamespace,
"simplelist");
1523 for (
int i = 0; i < 26; i++) {
1525 if (usedParagraphNames.contains(
char(
'a' + i))) {
1526 m_writer->writeStartElement(dbNamespace,
"member");
1527 generateSimpleLink(ch, ch.toUpper());
1528 m_writer->writeEndElement();
1533 m_writer->writeEndElement();
1538 QHash<QString,
int> nameOccurrences;
1539 for (
const auto &[key, node] : nmm.asKeyValueRange()) {
1540 QStringList pieces{node->fullName(relative).split(
"::"_L1)};
1541 const QString &name{pieces.last()};
1542 nameOccurrences[name]++;
1547 int curParOffset = 0;
1549 m_writer->writeStartElement(dbNamespace,
"variablelist");
1550 m_writer->writeAttribute(
"role", selector);
1553 for (
int i = 0; i < nmm.size(); i++) {
1554 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
1561 if (curParOffset == 0) {
1563 m_writer->writeEndElement();
1565 m_writer->writeEndElement();
1567 m_writer->writeEndElement();
1571 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1572 if (includeAlphabet)
1573 writeXmlId(paragraphName[curParNr][0].toLower());
1576 m_writer->writeStartElement(dbNamespace,
"term");
1577 m_writer->writeStartElement(dbNamespace,
"emphasis");
1578 m_writer->writeAttribute(
"role",
"bold");
1579 m_writer->writeCharacters(paragraphName[curParNr]);
1580 m_writer->writeEndElement();
1581 m_writer->writeEndElement();
1584 m_writer->writeStartElement(dbNamespace,
"listitem");
1586 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1591 m_writer->writeStartElement(dbNamespace,
"listitem");
1593 m_writer->writeStartElement(dbNamespace,
"para");
1595 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
1596 NodeMultiMap::Iterator it;
1597 NodeMultiMap::Iterator next;
1598 it = paragraph[curParNr].begin();
1599 for (
int j = 0; j < curParOffset; j++)
1604 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
1605 const auto &name{pieces.last()};
1608 if (nameOccurrences[name] > 1) {
1609 const QString moduleName = it.value()->isQmlNode() ? it.value()->logicalModuleName()
1610 : it.value()->tree()->camelCaseModuleName();
1611 pieces.last().append(
": %1"_L1.arg(moduleName));
1615 m_writer->writeStartElement(dbNamespace,
"link");
1616 m_writer->writeAttribute(xlinkNamespace,
"href", linkForNode(*it, relative));
1617 if (
const QString type = targetType(it.value()); !type.isEmpty())
1618 m_writer->writeAttribute(
"role", type);
1619 m_writer->writeCharacters(pieces.last());
1620 m_writer->writeEndElement();
1623 if (pieces.size() > 1) {
1624 m_writer->writeCharacters(
" (");
1625 generateFullName(it.value()->parent(), relative);
1626 m_writer->writeCharacters(
")");
1630 m_writer->writeEndElement();
1632 m_writer->writeEndElement();
1637 m_writer->writeEndElement();
1639 m_writer->writeEndElement();
1641 m_writer->writeEndElement();
1644 m_writer->writeEndElement();
1653 m_writer->writeStartElement(dbNamespace,
"simplelist");
1654 m_writer->writeAttribute(
"role",
"functionIndex");
1656 for (
int i = 0; i < 26; i++) {
1658 m_writer->writeStartElement(dbNamespace,
"member");
1659 m_writer->writeAttribute(xlinkNamespace,
"href", QString(
"#") + ch);
1660 m_writer->writeCharacters(ch.toUpper());
1661 m_writer->writeEndElement();
1664 m_writer->writeEndElement();
1671 char nextLetter =
'a';
1674 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1678 QMap<QString, NodeMap>::ConstIterator f = funcIndex.constBegin();
1679 while (f != funcIndex.constEnd()) {
1680 m_writer->writeStartElement(dbNamespace,
"listitem");
1682 m_writer->writeStartElement(dbNamespace,
"para");
1683 m_writer->writeCharacters(f.key() +
": ");
1685 currentLetter = f.key()[0].unicode();
1686 while (islower(currentLetter) && currentLetter >= nextLetter) {
1687 writeAnchor(QString(nextLetter));
1691 NodeMap::ConstIterator s = (*f).constBegin();
1692 while (s != (*f).constEnd()) {
1693 m_writer->writeCharacters(
" ");
1694 generateFullName((*s)->parent(), relative);
1698 m_writer->writeEndElement();
1700 m_writer->writeEndElement();
1704 m_writer->writeEndElement();
1712 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
1713 Text text = it.key();
1715 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1718 m_writer->writeStartElement(dbNamespace,
"listitem");
1720 m_writer->writeStartElement(dbNamespace,
"para");
1721 generateFullName(it.value(), relative);
1722 m_writer->writeEndElement();
1724 m_writer->writeEndElement();
1727 }
while (it != legaleseTexts.constEnd() && it.key() == text);
1728 m_writer->writeEndElement();
1743 m_writer->writeStartElement(dbNamespace,
"para");
1745 m_writer->writeEndElement();
1753 if (!node->since().isEmpty()) {
1754 m_writer->writeStartElement(dbNamespace,
"para");
1755 m_writer->writeCharacters(
"This " + typeString(node) +
" was introduced in ");
1756 m_writer->writeCharacters(formatSince(node) +
".");
1757 m_writer->writeEndElement();
1767
1768
1769
1776 m_writer->writeStartElement(dbNamespace,
"info");
1778 m_writer->writeStartElement(dbNamespace,
"title");
1779 if (isApiGenus(node->genus()) && m_useITS)
1780 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1781 m_writer->writeCharacters(title);
1782 m_writer->writeEndElement();
1785 if (!subTitle.isEmpty()) {
1786 m_writer->writeStartElement(dbNamespace,
"subtitle");
1787 if (isApiGenus(node->genus()) && m_useITS)
1788 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1789 m_writer->writeCharacters(subTitle);
1790 m_writer->writeEndElement();
1794 if (!m_productName.isEmpty() || !m_project.isEmpty()) {
1795 m_writer->writeTextElement(dbNamespace,
"productname", m_productName.isEmpty() ?
1796 m_project : m_productName);
1800 if (!m_buildVersion.isEmpty()) {
1801 m_writer->writeTextElement(dbNamespace,
"edition", m_buildVersion);
1805 if (!m_projectDescription.isEmpty()) {
1806 m_writer->writeTextElement(dbNamespace,
"titleabbrev", m_projectDescription);
1814 if (node && !node->links().empty()) {
1815 std::pair<QString, QString> linkPair;
1816 std::pair<QString, QString> anchorPair;
1817 const Node *linkNode;
1819 if (node->links().contains(Node::PreviousLink)) {
1820 linkPair = node->links()[Node::PreviousLink];
1821 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1822 if (!linkNode || linkNode == node)
1823 anchorPair = linkPair;
1825 anchorPair = anchorForNode(linkNode);
1827 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1828 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1829 m_writer->writeEmptyElement(dbNamespace,
"link");
1830 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1831 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1832 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"prev");
1833 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1834 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1836 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1837 m_writer->writeEndElement();
1840 if (node->links().contains(Node::NextLink)) {
1841 linkPair = node->links()[Node::NextLink];
1842 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1843 if (!linkNode || linkNode == node)
1844 anchorPair = linkPair;
1846 anchorPair = anchorForNode(linkNode);
1848 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1849 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1850 m_writer->writeEmptyElement(dbNamespace,
"link");
1851 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1852 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1853 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"next");
1854 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1855 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1857 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1858 m_writer->writeEndElement();
1861 if (node->links().contains(Node::StartLink)) {
1862 linkPair = node->links()[Node::StartLink];
1863 linkNode =
m_qdb->findNodeForTarget(linkPair.first, node);
1864 if (!linkNode || linkNode == node)
1865 anchorPair = linkPair;
1867 anchorPair = anchorForNode(linkNode);
1869 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1870 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1871 m_writer->writeEmptyElement(dbNamespace,
"link");
1872 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1873 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1874 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"start");
1875 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1876 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1878 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1879 m_writer->writeEndElement();
1891 m_writer->writeStartElement(dbNamespace,
"abstract");
1894 bool generatedSomething =
false;
1901 brief <<
"The " << ns->name()
1902 <<
" namespace includes the following elements from module "
1903 << ns
->tree()->camelCaseModuleName() <<
". The full namespace is "
1904 <<
"documented in module " << NS
->tree()->camelCaseModuleName();
1905 addNodeLink(brief, fullDocumentLocation(NS),
" here.");
1914 m_writer->writeStartElement(dbNamespace,
"para");
1916 m_writer->writeEndElement();
1919 generatedSomething =
true;
1930 if (!generatedSomething)
1931 m_writer->writeTextElement(dbNamespace,
"para", m_projectDescription +
".");
1933 m_writer->writeEndElement();
1938 m_writer->writeEndElement();
1944 while (!sectionLevels.isEmpty()) {
1945 sectionLevels.pop();
1952 if (m_closeSectionAfterGeneratedList) {
1953 m_closeSectionAfterGeneratedList =
false;
1956 if (m_closeSectionAfterRawTitle) {
1957 m_closeSectionAfterRawTitle =
false;
1962 m_writer->writeEndElement();
1965void DocBookGenerator::generateSimpleLink(
const QString &href,
const QString &text)
1967 m_writer->writeStartElement(dbNamespace,
"link");
1968 m_writer->writeAttribute(xlinkNamespace,
"href", href);
1969 m_writer->writeCharacters(text);
1970 m_writer->writeEndElement();
1982 startSection(
"obsolete",
"Obsolete Members for " + aggregate->plainFullName());
1984 m_writer->writeStartElement(dbNamespace,
"para");
1985 m_writer->writeStartElement(dbNamespace,
"emphasis");
1986 m_writer->writeAttribute(
"role",
"bold");
1987 m_writer->writeCharacters(
"The following members of class ");
1988 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
1989 m_writer->writeCharacters(
" are deprecated.");
1990 m_writer->writeEndElement();
1991 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
1992 m_writer->writeEndElement();
1995 for (
const Section *section : details_spv) {
1996 const QString &title =
"Obsolete " + section->title();
1997 startSection(title.toLower(), title);
1999 const NodeVector &members = section->obsoleteMembers();
2000 NodeVector::ConstIterator m = members.constBegin();
2001 while (m != members.constEnd()) {
2002 if ((*m)->access() != Access::Private)
2003 generateDetailedMember(*m, aggregate);
2014
2015
2016
2017
2018
2019
2020
2030 startSection(
"obsolete",
"Obsolete Members for " + aggregate->name());
2032 m_writer->writeStartElement(dbNamespace,
"para");
2033 m_writer->writeStartElement(dbNamespace,
"emphasis");
2034 m_writer->writeAttribute(
"role",
"bold");
2035 m_writer->writeCharacters(
"The following members of QML type ");
2036 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2037 m_writer->writeCharacters(
" are deprecated.");
2038 m_writer->writeEndElement();
2039 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2040 m_writer->writeEndElement();
2043 for (
const auto *section : details_spv) {
2044 const QString &title =
"Obsolete " + section->title();
2045 startSection(title.toLower(), title);
2047 const NodeVector &members = section->obsoleteMembers();
2048 NodeVector::ConstIterator m = members.constBegin();
2049 while (m != members.constEnd()) {
2050 if ((*m)->access() != Access::Private)
2051 generateDetailedQmlMember(*m, aggregate);
2065 return QStringLiteral(
"classsynopsis");
2067 return QStringLiteral(
"packagesynopsis");
2073 return QStringLiteral(
"enumsynopsis");
2075 return QStringLiteral(
"typedefsynopsis");
2078 const auto fn =
static_cast<
const FunctionNode *>(node);
2080 return QStringLiteral(
"constructorsynopsis");
2082 return QStringLiteral(
"destructorsynopsis");
2083 return QStringLiteral(
"methodsynopsis");
2086 return QStringLiteral(
"fieldsynopsis");
2088 node
->doc().location().warning(QString(
"Unknown node tag %1").arg(node->nodeTypeString()));
2089 return QStringLiteral(
"synopsis");
2094 m_writer->writeStartElement(dbNamespace,
"varlistentry");
2096 m_writer->writeTextElement(dbNamespace,
"term", description);
2098 m_writer->writeStartElement(dbNamespace,
"listitem");
2100 m_writer->writeStartElement(dbNamespace,
"para");
2106 m_writer->writeEndElement();
2109 m_writer->writeEndElement();
2111 m_writer->writeEndElement();
2115void DocBookGenerator::generateRequisite(
const QString &description,
const QString &value)
2117 generateStartRequisite(description);
2118 m_writer->writeCharacters(value);
2119 generateEndRequisite();
2123
2124
2125
2126void DocBookGenerator::generateCMakeRequisite(
const QString &findPackage,
const QString &linkLibraries)
2128 const QString description(
"CMake");
2129 generateStartRequisite(description);
2130 m_writer->writeCharacters(findPackage);
2131 m_writer->writeEndElement();
2134 m_writer->writeStartElement(dbNamespace,
"para");
2135 m_writer->writeCharacters(linkLibraries);
2136 generateEndRequisite();
2142 QMap<QString, ClassNode *> classMap;
2143 QList<RelatedClass>::ConstIterator r = rc.constBegin();
2144 while (r != rc.constEnd()) {
2147 && !rcn
->doc().isEmpty()) {
2148 classMap[rcn->plainFullName(cn).toLower()] = rcn;
2153 QStringList classNames = classMap.keys();
2157 for (
const QString &className : classNames) {
2158 generateFullName(classMap.value(className), cn);
2159 m_writer->writeCharacters(Utilities::comma(index++, classNames.size()));
2167 QMap<QString, Node *> classMap;
2168 QStringList typeNames(knownTypes);
2169 for (
const auto sub : subs)
2170 typeNames << sub->name();
2172 for (
auto sub : subs) {
2173 QString key{sub->plainFullName(base).toLower()};
2175 if (typeNames.count(sub->name()) > 1)
2176 key.append(
": (%1)"_L1.arg(sub->logicalModuleName()));
2177 classMap[key] = sub;
2180 QStringList names = classMap.keys();
2184 for (
const QString &name : names) {
2185 generateFullName(classMap.value(name), base);
2186 if (name.contains(
':'))
2187 m_writer->writeCharacters(name.section(
':', 1));
2188 m_writer->writeCharacters(Utilities::comma(index++, names.size()));
2193
2194
2203 QXmlStreamWriter* oldWriter = m_writer;
2205 m_writer =
new QXmlStreamWriter(&output);
2208 if (aggregate->includeFile()) generateRequisite(
"Header", *aggregate->includeFile());
2211 if (!aggregate->since().isEmpty())
2212 generateRequisite(
"Since", formatSince(aggregate));
2219 if (
const auto result = cmakeRequisite(cn)) {
2220 generateCMakeRequisite(result->first, result->second);
2223 if (cn && !cn->qtVariable().isEmpty())
2224 generateRequisite(
"qmake",
"QT += " + cn->qtVariable());
2231 generateStartRequisite(
"In QML");
2234 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2237 for (
const auto &item : std::as_const(nativeTypes)) {
2238 generateFullName(item, classe);
2239 m_writer->writeCharacters(
2240 Utilities::comma(idx++, nativeTypes.size()));
2242 generateEndRequisite();
2246 QList<RelatedClass>::ConstIterator r;
2247 if (classe && !classe->baseClasses().isEmpty()) {
2248 generateStartRequisite(
"Inherits");
2250 r = classe->baseClasses().constBegin();
2252 while (r != classe->baseClasses().constEnd()) {
2254 generateFullName((*r).m_node, classe);
2256 if ((*r).m_access == Access::Protected)
2257 m_writer->writeCharacters(
" (protected)");
2258 else if ((*r).m_access == Access::Private)
2259 m_writer->writeCharacters(
" (private)");
2260 m_writer->writeCharacters(
2261 Utilities::comma(index++, classe->baseClasses().size()));
2266 generateEndRequisite();
2270 if (!classe->derivedClasses().isEmpty()) {
2271 generateStartRequisite(
"Inherited By");
2272 generateSortedNames(classe, classe->derivedClasses());
2273 generateEndRequisite();
2278 if (!aggregate->groupNames().empty()) {
2279 generateStartRequisite(
"Group");
2281 generateEndRequisite();
2285 if (
auto status = formatStatus(aggregate, m_qdb); status)
2286 generateRequisite(
"Status", status.value());
2290 m_writer = oldWriter;
2292 if (!output.isEmpty()) {
2295 static const QRegularExpression xmlTag(R"(<(/?)n\d+:)");
2296 static const QRegularExpression xmlnsDocBookDefinition(R"( xmlns:n\d+=")" + QString{dbNamespace} +
"\"");
2297 static const QRegularExpression xmlnsXLinkDefinition(R"( xmlns:n\d+=")" + QString{xlinkNamespace} +
"\"");
2298 static const QRegularExpression xmlAttr(R"( n\d+:)");
2300 const QString cleanOutput = output.replace(xmlTag, R"(<\1db:)")
2301 .replace(xmlnsDocBookDefinition,
"")
2302 .replace(xmlnsXLinkDefinition,
"")
2303 .replace(xmlAttr,
" xlink:");
2305 m_writer->writeStartElement(dbNamespace,
"variablelist");
2307 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2310 m_writer->device()->write(cleanOutput.toUtf8());
2312 m_writer->writeEndElement();
2318
2319
2327 const QString importText =
"Import Statement";
2328 const QString sinceText =
"Since";
2329 const QString inheritedByText =
"Inherited By";
2330 const QString inheritsText =
"Inherits";
2331 const QString nativeTypeText =
"In C++";
2332 const QString groupText =
"Group";
2333 const QString statusText =
"Status";
2341 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2350 bool generate_import_statement = !qcn->logicalModuleName().isEmpty();
2351 if (generate_import_statement && collection) {
2356 const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base;
2358 if (!generates_something)
2361 QStringList knownTypeNames{qcn->name()};
2363 knownTypeNames << base->name();
2366 m_writer->writeStartElement(dbNamespace,
"variablelist");
2368 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2371 if (generate_import_statement) {
2372 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2373 generateRequisite(importText, parts.join(
' ').trimmed());
2377 if (!qcn->since().isEmpty())
2378 generateRequisite(sinceText, formatSince(qcn));
2383 generateStartRequisite(nativeTypeText);
2384 generateSimpleLink(fullDocumentLocation(cn), cn->name());
2385 generateEndRequisite();
2390 generateStartRequisite(inheritsText);
2391 generateSimpleLink(fullDocumentLocation(base), base->name());
2393 for (
const auto sub : std::as_const(subs)) {
2394 if (knownTypeNames.contains(sub->name())) {
2395 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
2399 generateEndRequisite();
2403 if (!subs.isEmpty()) {
2404 generateStartRequisite(inheritedByText);
2405 generateSortedQmlNames(qcn, knownTypeNames, subs);
2406 generateEndRequisite();
2410 if (!qcn->groupNames().empty()) {
2411 generateStartRequisite(groupText);
2413 generateEndRequisite();
2417 if (
auto status = formatStatus(qcn, m_qdb); status)
2418 generateRequisite(statusText, status.value());
2420 m_writer->writeEndElement();
2431 const QString &state =
static_cast<
const CollectionNode*>(node)->state();
2432 if (!state.isEmpty()) {
2433 m_writer->writeStartElement(dbNamespace,
"para");
2434 m_writer->writeCharacters(
"This " + typeString(node) +
" is in ");
2435 m_writer->writeStartElement(dbNamespace,
"emphasis");
2436 m_writer->writeCharacters(state);
2437 m_writer->writeEndElement();
2438 m_writer->writeCharacters(
" state.");
2439 m_writer->writeEndElement();
2444 if (
const auto &version = node->deprecatedSince(); !version.isEmpty()) {
2445 m_writer->writeStartElement(dbNamespace,
"para");
2446 m_writer->writeCharacters(
"This " + typeString(node)
2447 +
" is scheduled for deprecation in version "
2449 m_writer->writeEndElement();
2454 case Node::Preliminary:
2455 m_writer->writeStartElement(dbNamespace,
"para");
2456 m_writer->writeStartElement(dbNamespace,
"emphasis");
2457 m_writer->writeAttribute(
"role",
"bold");
2458 m_writer->writeCharacters(
"This " + typeString(node)
2459 +
" is under development and is subject to change.");
2460 m_writer->writeEndElement();
2461 m_writer->writeEndElement();
2464 case Node::Deprecated:
2465 m_writer->writeStartElement(dbNamespace,
"para");
2467 m_writer->writeStartElement(dbNamespace,
"emphasis");
2468 m_writer->writeAttribute(
"role",
"bold");
2470 m_writer->writeCharacters(
"This " + typeString(node) +
" is deprecated");
2471 if (
const QString &version = node->deprecatedSince(); !version.isEmpty()) {
2472 m_writer->writeCharacters(
" since ");
2473 if (node->isQmlNode() && !node->logicalModuleName().isEmpty())
2474 m_writer->writeCharacters(node->logicalModuleName() +
" ");
2475 m_writer->writeCharacters(version);
2477 m_writer->writeCharacters(
". We strongly advise against using it in new code.");
2478 if (node->isAggregate())
2479 m_writer->writeEndElement();
2480 m_writer->writeEndElement();
2490
2491
2492
2496 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2499 NodeList::ConstIterator n = nodes.constBegin();
2500 while (n != nodes.constEnd()) {
2501 m_writer->writeStartElement(dbNamespace,
"listitem");
2503 m_writer->writeStartElement(dbNamespace,
"para");
2505 generateSimpleLink(currentGenerator()->fullDocumentLocation(*n),
2506 (*n)->signature(Node::SignaturePlain));
2508 m_writer->writeEndElement();
2510 m_writer->writeEndElement();
2515 m_writer->writeEndElement();
2520
2521
2522
2529 const auto aggregate =
static_cast<
const Aggregate *>(node);
2531 const QStringList &groups_names{aggregate->groupNames()};
2532 if (!groups_names.empty()) {
2533 m_writer->writeCharacters(aggregate->name() +
" is part of ");
2534 m_writer->writeStartElement(dbNamespace,
"simplelist");
2536 for (qsizetype index{0}; index < groups_names.size(); ++index) {
2540 m_writer->writeStartElement(dbNamespace,
"member");
2541 if (QString target{linkForNode(group,
nullptr)}; !target.isEmpty())
2542 generateSimpleLink(target, group->fullTitle());
2544 m_writer->writeCharacters(group->name());
2545 m_writer->writeEndElement();
2548 m_writer->writeEndElement();
2554
2555
2556
2562 const Node *reentrantNode;
2564 QString linkReentrant = getAutoLink(&reentrantAtom, node, &reentrantNode);
2565 const Node *threadSafeNode;
2567 QString linkThreadSafe = getAutoLink(&threadSafeAtom, node, &threadSafeNode);
2570 m_writer->writeStartElement(dbNamespace,
"warning");
2572 m_writer->writeStartElement(dbNamespace,
"para");
2573 m_writer->writeCharacters(
"This " + typeString(node) +
" is not ");
2574 generateSimpleLink(linkReentrant,
"reentrant");
2575 m_writer->writeCharacters(
".");
2576 m_writer->writeEndElement();
2578 m_writer->writeEndElement();
2582 m_writer->writeStartElement(dbNamespace,
"note");
2584 m_writer->writeStartElement(dbNamespace,
"para");
2587 m_writer->writeCharacters(
"All functions in this " + typeString(node) +
" are ");
2588 if (ts == Node::ThreadSafe)
2589 generateSimpleLink(linkThreadSafe,
"thread-safe");
2591 generateSimpleLink(linkReentrant,
"reentrant");
2596 bool exceptions = hasExceptions(node, reentrant, threadsafe, nonreentrant);
2597 if (!exceptions || (ts ==
Node::Reentrant && !threadsafe.isEmpty())) {
2598 m_writer->writeCharacters(
".");
2599 m_writer->writeEndElement();
2602 m_writer->writeCharacters(
" with the following exceptions:");
2603 m_writer->writeEndElement();
2605 m_writer->writeStartElement(dbNamespace,
"para");
2608 if (!nonreentrant.isEmpty()) {
2609 m_writer->writeCharacters(
"These functions are not ");
2610 generateSimpleLink(linkReentrant,
"reentrant");
2611 m_writer->writeCharacters(
":");
2612 m_writer->writeEndElement();
2614 generateSignatureList(nonreentrant);
2616 if (!threadsafe.isEmpty()) {
2617 m_writer->writeCharacters(
"These functions are also ");
2618 generateSimpleLink(linkThreadSafe,
"thread-safe");
2619 m_writer->writeCharacters(
":");
2620 m_writer->writeEndElement();
2622 generateSignatureList(threadsafe);
2625 if (!reentrant.isEmpty()) {
2626 m_writer->writeCharacters(
"These functions are only ");
2627 generateSimpleLink(linkReentrant,
"reentrant");
2628 m_writer->writeCharacters(
":");
2629 m_writer->writeEndElement();
2631 generateSignatureList(reentrant);
2633 if (!nonreentrant.isEmpty()) {
2634 m_writer->writeCharacters(
"These functions are not ");
2635 generateSimpleLink(linkReentrant,
"reentrant");
2636 m_writer->writeCharacters(
":");
2637 m_writer->writeEndElement();
2639 generateSignatureList(nonreentrant);
2644 m_writer->writeCharacters(
"This " + typeString(node) +
" is ");
2645 if (ts == Node::ThreadSafe)
2646 generateSimpleLink(linkThreadSafe,
"thread-safe");
2648 generateSimpleLink(linkReentrant,
"reentrant");
2649 m_writer->writeCharacters(
".");
2650 m_writer->writeEndElement();
2653 m_writer->writeEndElement();
2663
2664
2665
2673
2674
2675
2679 t =
"Destroys the instance of " + fn
->parent()->name() +
".";
2681 t +=
" The destructor is virtual.";
2683 t =
"Default constructs an instance of " + fn
->parent()->name() +
".";
2685 t =
"Copy constructor.";
2687 t =
"Move-copy constructor.";
2689 t =
"Copy-assignment constructor.";
2691 t =
"Move-assignment constructor.";
2695 m_writer->writeTextElement(dbNamespace,
"para", t);
2699 if (fn && !fn->overridesThis().isEmpty())
2700 generateReimplementsClause(fn);
2730 generateRequiredLinks(node);
2734
2735
2736
2737
2738
2745 const auto en =
static_cast<
const ExampleNode *>(node);
2748 if (exampleUrl.isEmpty()) {
2750 generateFileList(en,
false);
2751 generateFileList(en,
true);
2754 generateLinkToExample(en, exampleUrl);
2759
2760
2761
2762
2763
2767 QString exampleUrl(baseUrl);
2769#ifndef QT_BOOTSTRAPPED
2770 link = QUrl(exampleUrl).host();
2772 if (!link.isEmpty())
2773 link.prepend(
" @ ");
2774 link.prepend(
"Example project");
2776 const QLatin1Char separator(
'/');
2777 const QLatin1Char placeholder(
'\1');
2778 if (!exampleUrl.contains(placeholder)) {
2779 if (!exampleUrl.endsWith(separator))
2780 exampleUrl += separator;
2781 exampleUrl += placeholder;
2785 QStringList path = QStringList()
2787 path.removeAll(QString());
2791 startSection(
"Example project");
2793 m_writer->writeStartElement(dbNamespace,
"para");
2794 generateSimpleLink(exampleUrl.replace(placeholder, path.join(separator)), link);
2795 m_writer->writeEndElement();
2804
2805
2806
2807
2808
2809
2825 paths = en->images();
2828 paths = en->files();
2831 std::sort(paths.begin(), paths.end(), Generator::comparePaths);
2833 if (paths.isEmpty())
2836 startSection(
"",
"List of Files");
2838 m_writer->writeStartElement(dbNamespace,
"para");
2839 m_writer->writeCharacters(tag);
2840 m_writer->writeEndElement();
2843 startSection(
"List of Files");
2845 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2848 for (
const auto &path : std::as_const(paths)) {
2849 auto maybe_resolved_file{file_resolver.resolve(path)};
2850 if (!maybe_resolved_file) {
2852 QString details = std::transform_reduce(
2853 file_resolver.get_search_directories().cbegin(),
2854 file_resolver.get_search_directories().cend(),
2855 u"Searched directories:"_s,
2857 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
2860 en->location().warning(u"Cannot find file to quote from: %1"_s.arg(path), details);
2865 const auto &file{*maybe_resolved_file};
2866 if (images) addImageToCopy(en, file);
2867 else generateExampleFilePage(en, file);
2869 m_writer->writeStartElement(dbNamespace,
"listitem");
2871 m_writer->writeStartElement(dbNamespace,
"para");
2872 generateSimpleLink(file.get_query(), file.get_query());
2873 m_writer->writeEndElement();
2874 m_writer->writeEndElement();
2878 m_writer->writeEndElement();
2885
2886
2896 const auto en =
static_cast<
const ExampleNode *>(node);
2899 QXmlStreamWriter *currentWriter = m_writer;
2900 m_writer = startDocument(en, resolved_file.get_query());
2901 generateHeader(en->fullTitle(), en->subtitle(), en);
2906 QString code = quoter.quoteTo(en
->location(), QString(), QString());
2907 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
2913 m_writer = currentWriter;
2919 if (fn->overridesThis().isEmpty() || !fn
->parent()->isClassNode())
2924 if (
const FunctionNode *overrides = cn->findOverriddenFunction(fn);
2927 m_writer->writeStartElement(dbNamespace,
"para");
2928 m_writer->writeCharacters(
"Reimplements: ");
2931 generateFullName(overrides
->parent(), fullName, overrides);
2932 m_writer->writeCharacters(
".");
2933 m_writer->writeEndElement();
2939 if (
const PropertyNode *sameName = cn->findOverriddenProperty(fn); sameName && sameName
->hasDoc()) {
2940 m_writer->writeStartElement(dbNamespace,
"para");
2941 m_writer->writeCharacters(
"Reimplements an access function for property: ");
2942 QString fullName = sameName
->parent()->name() +
"::" + sameName->name();
2943 generateFullName(sameName
->parent(), fullName, sameName);
2944 m_writer->writeCharacters(
".");
2945 m_writer->writeEndElement();
2954 QList<Text> alsoList = node
->doc().alsoList();
2955 supplementAlsoList(node, alsoList);
2957 if (!alsoList.isEmpty()) {
2958 startSection(
"See Also");
2960 m_writer->writeStartElement(dbNamespace,
"para");
2961 m_writer->writeStartElement(dbNamespace,
"emphasis");
2962 m_writer->writeCharacters(
"See also ");
2963 m_writer->writeEndElement();
2966 m_writer->writeStartElement(dbNamespace,
"simplelist");
2967 m_writer->writeAttribute(
"type",
"vert");
2968 m_writer->writeAttribute(
"role",
"see-also");
2971 for (
const Text &text : alsoList) {
2972 m_writer->writeStartElement(dbNamespace,
"member");
2973 generateText(text, node);
2974 m_writer->writeEndElement();
2978 m_writer->writeEndElement();
2981 m_writer->writeEndElement();
2989
2990
2991
2992QXmlStreamWriter *
DocBookGenerator::startGenericDocument(
const Node *node,
const QString &fileName)
2995 QFile *outFile = openSubPageFile(
static_cast<
const PageNode*>(node), fileName);
2996 m_writer =
new QXmlStreamWriter(outFile);
2997 m_writer->setAutoFormatting(
false);
2999 m_writer->writeStartDocument();
3001 m_writer->writeNamespace(dbNamespace,
"db");
3002 m_writer->writeNamespace(xlinkNamespace,
"xlink");
3004 m_writer->writeNamespace(itsNamespace,
"its");
3005 m_writer->writeStartElement(dbNamespace,
"article");
3006 m_writer->writeAttribute(
"version",
"5.2");
3007 if (!m_naturalLanguage.isEmpty())
3008 m_writer->writeAttribute(
"xml:lang", m_naturalLanguage);
3012 sectionLevels.resize(0);
3021 m_hasSection =
false;
3024 QString fileName = Generator::fileName(node, fileExtension());
3025 return startGenericDocument(node, fileName);
3030 m_hasSection =
false;
3032 QString fileName = linkForExampleFile(file);
3033 return startGenericDocument(en, fileName);
3038 m_writer->writeEndElement();
3039 m_writer->writeEndDocument();
3041 m_writer->device()->close();
3042 delete m_writer->device();
3048
3049
3050
3055 const auto aggregate =
static_cast<
const Aggregate *>(node);
3058 QString subtitleText;
3059 const QString typeWord{aggregate->typeWord(
true)};
3061 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3063 auto templateDecl = node->templateDecl();
3065 subtitleText =
"%1 %2 %3"_L1.arg((*templateDecl).to_qstring(),
3066 aggregate->typeWord(
false),
3067 aggregate->plainFullName());
3068 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3070 title = aggregate->fullTitle();
3074 m_writer = startDocument(node);
3077 generateHeader(title, subtitleText, aggregate);
3086 if (!aggregate
->doc().isEmpty()) {
3087 startSection(
"details",
"Detailed Description");
3089 generateBody(aggregate);
3100 for (
const Section §ion : sectionVector) {
3101 if (section.members().isEmpty())
3104 startSection(section.title().toLower(), section.title());
3106 for (
const Node *member : section.members()) {
3107 if (member->nodeType() != NodeType::Class) {
3109 generateDetailedMember(member, aggregate);
3111 startSectionBegin();
3112 m_writer->writeCharacters(
"class ");
3113 generateFullName(member, aggregate);
3116 generateBrief(member);
3125 generateObsoleteMembers(sections);
3130void DocBookGenerator::generateSynopsisInfo(
const QString &key,
const QString &value)
3132 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3133 m_writer->writeAttribute(
"role", key);
3134 m_writer->writeCharacters(value);
3135 m_writer->writeEndElement();
3141 m_writer->writeTextElement(dbNamespace,
"modifier", value);
3146
3147
3157 if (!m_useDocBook52)
3184 QString synopsisTag = nodeToSynopsisTag(node);
3185 m_writer->writeStartElement(dbNamespace, synopsisTag);
3190 m_writer->writeStartElement(dbNamespace,
"ooclass");
3191 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3192 m_writer->writeEndElement();
3195 m_writer->writeTextElement(dbNamespace,
"namespacename", node->plainName());
3198 m_writer->writeStartElement(dbNamespace,
"ooclass");
3199 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3200 m_writer->writeEndElement();
3202 if (!qcn->groupNames().isEmpty())
3203 m_writer->writeAttribute(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3205 m_writer->writeTextElement(dbNamespace,
"modifier",
"(Qt property)");
3207 m_writer->writeTextElement(dbNamespace,
"type", propertyNode->dataType());
3209 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3213 m_writer->writeTextElement(dbNamespace,
"modifier",
"static");
3216 m_writer->writeTextElement(dbNamespace,
"type", variableNode->dataType());
3218 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3222 m_writer->writeTextElement(dbNamespace,
"enumname", node->plainName());
3226 QString name = node->name();
3228 name.prepend(qpn->element() + QLatin1Char(
'.'));
3230 m_writer->writeTextElement(dbNamespace,
"type", qpn->dataType());
3232 m_writer->writeTextElement(dbNamespace,
"varname", name);
3236 m_writer->writeTextElement(dbNamespace,
"modifier",
"attached");
3240 m_writer->writeTextElement(dbNamespace,
"modifier",
"writable");
3244 m_writer->writeTextElement(dbNamespace,
"modifier",
"required");
3248 generateModifier(
"[read-only]");
3252 generateModifier(
"[default]");
3256 if (functionNode->virtualness() !=
"non")
3257 generateModifier(
"virtual");
3258 if (functionNode->isConst())
3259 generateModifier(
"const");
3260 if (functionNode->isStatic())
3261 generateModifier(
"static");
3266 if (functionNode->returnType() ==
"void")
3267 m_writer->writeEmptyElement(dbNamespace,
"void");
3269 m_writer->writeTextElement(dbNamespace,
"type", functionNode->returnTypeString());
3274 QString name = node->plainName();
3275 if (name.endsWith(
"()"))
3277 m_writer->writeTextElement(dbNamespace,
"methodname", name);
3281 m_writer->writeEmptyElement(dbNamespace,
"void");
3286 for (
int i = 0; i < lp
.count(); ++i) {
3288 m_writer->writeStartElement(dbNamespace,
"methodparam");
3290 m_writer->writeTextElement(dbNamespace,
"type", parameter.type());
3292 m_writer->writeTextElement(dbNamespace,
"parameter", parameter.name());
3294 if (!parameter.defaultValue().isEmpty()) {
3295 m_writer->writeTextElement(dbNamespace,
"initializer", parameter.defaultValue());
3298 m_writer->writeEndElement();
3302 if (functionNode->isDefault())
3303 generateModifier(
"default");
3304 if (functionNode->isFinal())
3305 generateModifier(
"final");
3306 if (functionNode->isOverride())
3307 generateModifier(
"override");
3309 m_writer->writeTextElement(dbNamespace,
"typedefname", node->plainName());
3313 QStringLiteral(
"Unexpected node type in generateDocBookSynopsis: %1")
3314 .arg(node->nodeTypeString()));
3320 for (
const EnumItem &item : enumNode->items()) {
3321 m_writer->writeStartElement(dbNamespace,
"enumitem");
3323 m_writer->writeTextElement(dbNamespace,
"enumidentifier", item.name());
3325 m_writer->writeTextElement(dbNamespace,
"enumvalue", item.value());
3327 m_writer->writeEndElement();
3331 if (enumNode->items().isEmpty()) {
3334 m_writer->writeStartElement(dbNamespace,
"enumitem");
3336 m_writer->writeEmptyElement(dbNamespace,
"enumidentifier");
3338 m_writer->writeEndElement();
3349 generateSynopsisInfo(
"meta", functionNode->metanessString());
3352 generateSynopsisInfo(
"overload",
"overload");
3353 generateSynopsisInfo(
"overload-number",
3354 QString::number(functionNode->overloadNumber()));
3357 if (functionNode->isRef())
3358 generateSynopsisInfo(
"refness", QString::number(1));
3359 else if (functionNode->isRefRef())
3360 generateSynopsisInfo(
"refness", QString::number(2));
3363 QStringList associatedProperties;
3364 const auto &nodes = functionNode->associatedProperties();
3365 for (
const Node *n : nodes) {
3366 const auto pn =
static_cast<
const PropertyNode *>(n);
3367 associatedProperties << pn->name();
3369 associatedProperties.sort();
3370 generateSynopsisInfo(
"associated-property",
3371 associatedProperties.join(QLatin1Char(
',')));
3377 signature +=
" final";
3379 signature +=
" override";
3381 signature +=
" = 0";
3383 signature +=
" = default";
3384 generateSynopsisInfo(
"signature", signature);
3390 case Access::Public:
3391 generateSynopsisInfo(
"access",
"public");
3393 case Access::Protected:
3394 generateSynopsisInfo(
"access",
"protected");
3396 case Access::Private:
3397 generateSynopsisInfo(
"access",
"private");
3402 if (node->isAbstract())
3403 generateSynopsisInfo(
"abstract",
"true");
3409 generateSynopsisInfo(
"status",
"active");
3411 case Node::Preliminary:
3412 generateSynopsisInfo(
"status",
"preliminary");
3414 case Node::Deprecated:
3415 generateSynopsisInfo(
"status",
"deprecated");
3417 case Node::Internal:
3418 generateSynopsisInfo(
"status",
"internal");
3421 generateSynopsisInfo(
"status",
"main");
3428 if (aggregate->includeFile()) generateSynopsisInfo(
"headers", *aggregate->includeFile());
3431 if (!aggregate->since().isEmpty())
3432 generateSynopsisInfo(
"since", formatSince(aggregate));
3436 if (!aggregate->physicalModuleName().isEmpty()) {
3440 if (
const auto result = cmakeRequisite(cn)) {
3441 generateSynopsisInfo(
"cmake-find-package", result->first);
3442 generateSynopsisInfo(
"cmake-target-link-libraries", result->second);
3445 if (cn && !cn->qtVariable().isEmpty())
3446 generateSynopsisInfo(
"qmake",
"QT += " + cn->qtVariable());
3454 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3455 m_writer->writeAttribute(
"role",
"nativeTypeFor");
3457 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
3460 for (
auto item : std::as_const(nativeTypes)) {
3461 const Node *otherNode{
nullptr};
3462 Atom a = Atom(Atom::LinkNode, Utilities::stringForNode(item));
3463 const QString &link = getAutoLink(&a, aggregate, &otherNode);
3464 generateSimpleLink(link, item->name());
3467 m_writer->writeEndElement();
3471 QList<RelatedClass>::ConstIterator r;
3472 if (!classe->baseClasses().isEmpty()) {
3473 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3474 m_writer->writeAttribute(
"role",
"inherits");
3476 r = classe->baseClasses().constBegin();
3478 while (r != classe->baseClasses().constEnd()) {
3480 generateFullName((*r).m_node, classe);
3483 m_writer->writeCharacters(
" (protected)");
3485 m_writer->writeCharacters(
" (private)");
3487 m_writer->writeCharacters(
3488 Utilities::comma(index++, classe->baseClasses().size()));
3493 m_writer->writeEndElement();
3498 if (!classe->derivedClasses().isEmpty()) {
3499 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3500 m_writer->writeAttribute(
"role",
"inheritedBy");
3501 generateSortedNames(classe, classe->derivedClasses());
3502 m_writer->writeEndElement();
3511 QString logicalModuleVersion;
3515 logicalModuleVersion = collection->logicalModuleVersion();
3517 logicalModuleVersion = qcn->logicalModuleVersion();
3519 QStringList importText;
3520 importText <<
"import " + qcn->logicalModuleName();
3521 if (!logicalModuleVersion.isEmpty())
3522 importText << logicalModuleVersion;
3523 generateSynopsisInfo(
"import", importText.join(
' '));
3526 if (!qcn->since().isEmpty())
3527 generateSynopsisInfo(
"since", formatSince(qcn));
3530 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
3538 QStringList knownTypeNames{qcn->name()};
3540 knownTypeNames << base->name();
3545 if (!subs.isEmpty()) {
3546 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3547 m_writer->writeAttribute(
"role",
"inheritedBy");
3548 generateSortedQmlNames(qcn, knownTypeNames, subs);
3549 m_writer->writeEndElement();
3555 const Node *otherNode =
nullptr;
3557 QString link = getAutoLink(&a, base, &otherNode);
3559 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3560 m_writer->writeAttribute(
"role",
"inherits");
3561 generateSimpleLink(link, base->name());
3563 for (
const auto sub : std::as_const(subs)) {
3564 if (knownTypeNames.contains(sub->name())) {
3565 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
3569 m_writer->writeEndElement();
3577 const Node *otherNode =
nullptr;
3579 QString link = getAutoLink(&a, cn, &otherNode);
3581 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3582 m_writer->writeAttribute(
"role",
"nativeType");
3583 generateSimpleLink(link, cn->name());
3584 m_writer->writeEndElement();
3591 case Node::UnspecifiedSafeness:
3592 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3594 case Node::NonReentrant:
3595 generateSynopsisInfo(
"threadsafeness",
"non-reentrant");
3597 case Node::Reentrant:
3598 generateSynopsisInfo(
"threadsafeness",
"reentrant");
3600 case Node::ThreadSafe:
3601 generateSynopsisInfo(
"threadsafeness",
"thread safe");
3604 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3609 if (!node->physicalModuleName().isEmpty())
3610 generateSynopsisInfo(
"module", node->physicalModuleName());
3613 if (classNode && !classNode->groupNames().isEmpty()) {
3614 generateSynopsisInfo(
"groups", classNode->groupNames().join(QLatin1Char(
',')));
3615 }
else if (qcn && !qcn->groupNames().isEmpty()) {
3616 generateSynopsisInfo(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3621 for (
const Node *fnNode : propertyNode->getters()) {
3623 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3624 generateSynopsisInfo(
"getter", funcNode->name());
3627 for (
const Node *fnNode : propertyNode->setters()) {
3629 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3630 generateSynopsisInfo(
"setter", funcNode->name());
3633 for (
const Node *fnNode : propertyNode->resetters()) {
3635 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3636 generateSynopsisInfo(
"resetter", funcNode->name());
3639 for (
const Node *fnNode : propertyNode->notifiers()) {
3641 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3642 generateSynopsisInfo(
"notifier", funcNode->name());
3647 m_writer->writeEndElement();
3653 m_writer->writeStartElement(dbNamespace,
"typedefsynopsis");
3656 m_writer->writeTextElement(dbNamespace,
"typedefname",
3657 enumNode->flagsType()->fullDocumentName());
3660 m_writer->writeEndElement();
3671 return node->name().mid(4);
3672 return node->name();
3676
3677
3678
3679void DocBookGenerator::typified(
const QString &string,
const Node *relative,
bool trailingSpace,
3684 QString pendingWord;
3686 for (
int i = 0; i <= string.size(); ++i) {
3688 if (i != string.size())
3691 QChar lower = ch.toLower();
3692 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
3693 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
3696 if (!pendingWord.isEmpty()) {
3697 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
3698 if (generateType && isProbablyType) {
3700 m_writer->writeCharacters(result);
3704 const Node *n =
m_qdb->findTypeNode(pendingWord, relative, Genus::DontCare);
3709 href = linkForNode(n, relative);
3712 m_writer->writeStartElement(dbNamespace,
"type");
3714 m_writer->writeCharacters(pendingWord);
3716 generateSimpleLink(href, pendingWord);
3717 m_writer->writeEndElement();
3719 result += pendingWord;
3722 pendingWord.clear();
3724 if (ch.unicode() !=
'\0')
3729 if (trailingSpace && string.size()) {
3730 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
3731 result += QLatin1Char(
' ');
3734 m_writer->writeCharacters(result);
3738 bool generateNameLink)
3742 QString name = taggedNode(node);
3744 if (!generateNameLink) {
3745 m_writer->writeCharacters(name);
3749 m_writer->writeStartElement(dbNamespace,
"emphasis");
3750 m_writer->writeAttribute(
"role",
"bold");
3751 generateSimpleLink(linkForNode(node, relative), name);
3752 m_writer->writeEndElement();
3756 bool generateExtra,
bool generateType)
3758 const QString &pname = parameter.name();
3759 const QString &ptype = parameter.type();
3761 if (!pname.isEmpty()) {
3762 typified(ptype, relative,
true, generateType);
3768 if (generateExtra || pname.isEmpty()) {
3769 m_writer->writeStartElement(dbNamespace,
"emphasis");
3770 m_writer->writeCharacters(paramName);
3771 m_writer->writeEndElement();
3774 const QString &pvalue = parameter.defaultValue();
3775 if (generateExtra && !pvalue.isEmpty())
3776 m_writer->writeCharacters(
" = " + pvalue);
3788 const int MaxEnumValues = 6;
3790 if (generateExtra) {
3791 if (
auto extra = CodeMarker::extraSynopsis(node, style); !extra.isEmpty())
3792 m_writer->writeCharacters(extra +
" ");
3796 QString namePrefix {};
3800 namePrefix = taggedNode(node->parent()) +
"::";
3805 case NodeType::Namespace:
3806 m_writer->writeCharacters(
"namespace ");
3807 m_writer->writeCharacters(namePrefix);
3808 generateSynopsisName(node, relative, generateNameLink);
3810 case NodeType::Class:
3811 m_writer->writeCharacters(
"class ");
3812 m_writer->writeCharacters(namePrefix);
3813 generateSynopsisName(node, relative, generateNameLink);
3820 if (!func->isNonvirtual())
3821 m_writer->writeCharacters(QStringLiteral(
"virtual "));
3825 if (style != Section::AllMembers && !func->returnType().isEmpty())
3826 typified(func->returnTypeString(), relative,
true, generateType);
3827 m_writer->writeCharacters(namePrefix);
3828 generateSynopsisName(node, relative, generateNameLink);
3831 m_writer->writeCharacters(QStringLiteral(
"("));
3834 for (
int i = 0; i < parameters
.count(); i++) {
3836 m_writer->writeCharacters(QStringLiteral(
", "));
3837 generateParameter(parameters
.at(i
), relative, generateExtra, generateType);
3840 m_writer->writeCharacters(QStringLiteral(
")"));
3843 if (func->isConst())
3844 m_writer->writeCharacters(QStringLiteral(
" const"));
3850 synopsis += QStringLiteral(
" final");
3852 synopsis += QStringLiteral(
" override");
3854 synopsis += QStringLiteral(
" = 0");
3856 synopsis += QStringLiteral(
" &");
3858 synopsis += QStringLiteral(
" &&");
3859 m_writer->writeCharacters(synopsis);
3861 if (!func->returnType().isEmpty() && func->returnType() !=
"void") {
3862 m_writer->writeCharacters(QStringLiteral(
" : "));
3863 typified(func->returnTypeString(), relative,
false, generateType);
3868 synopsis += QStringLiteral(
" &");
3870 synopsis += QStringLiteral(
" &&");
3871 m_writer->writeCharacters(synopsis);
3875 const auto enume =
static_cast<
const EnumNode *>(node);
3877 m_writer->writeCharacters(
"enum "_L1);
3878 m_writer->writeCharacters(namePrefix);
3879 generateSynopsisName(node, relative, generateNameLink);
3880 }
else if (generateNameLink) {
3881 m_writer->writeStartElement(dbNamespace,
"emphasis");
3882 m_writer->writeAttribute(
"role",
"bold");
3883 generateSimpleLink(linkForNode(node, relative),
"enum");
3884 m_writer->writeEndElement();
3886 m_writer->writeCharacters(
"enum"_L1);
3893 QStringList documentedItems = enume
->doc().enumItemNames();
3894 if (documentedItems.isEmpty()) {
3895 const auto &enumItems = enume->items();
3896 for (
const auto &item : enumItems)
3897 documentedItems << item.name();
3899 const QStringList omitItems = enume
->doc().omitEnumItemNames();
3900 for (
const auto &item : omitItems)
3901 documentedItems.removeAll(item);
3903 if (documentedItems.size() > MaxEnumValues) {
3905 const QString last = documentedItems.last();
3906 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
3907 documentedItems +=
"…";
3908 documentedItems += last;
3910 synopsis += documentedItems.join(QLatin1String(
", "));
3912 if (!documentedItems.isEmpty())
3913 synopsis += QLatin1Char(
' ');
3914 synopsis += QLatin1Char(
'}');
3916 m_writer->writeCharacters(synopsis);
3920 auto templateDecl = node->templateDecl();
3922 m_writer->writeCharacters((*templateDecl).to_qstring() + QLatin1Char(
' '));
3924 m_writer->writeCharacters(namePrefix);
3925 generateSynopsisName(node, relative, generateNameLink);
3928 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
3929 m_writer->writeCharacters(
"flags ");
3930 m_writer->writeCharacters(namePrefix);
3931 generateSynopsisName(node, relative, generateNameLink);
3934 const auto property =
static_cast<
const PropertyNode *>(node);
3935 m_writer->writeCharacters(namePrefix);
3936 generateSynopsisName(node, relative, generateNameLink);
3937 m_writer->writeCharacters(
" : ");
3938 typified(property->qualifiedDataType(), relative,
false, generateType);
3941 const auto variable =
static_cast<
const VariableNode *>(node);
3943 generateSynopsisName(node, relative, generateNameLink);
3944 m_writer->writeCharacters(
" : ");
3945 typified(variable->dataType(), relative,
false, generateType);
3947 typified(variable->leftType(), relative,
false, generateType);
3948 m_writer->writeCharacters(
" ");
3949 m_writer->writeCharacters(namePrefix);
3950 generateSynopsisName(node, relative, generateNameLink);
3951 m_writer->writeCharacters(variable->rightType());
3955 m_writer->writeCharacters(namePrefix);
3956 generateSynopsisName(node, relative, generateNameLink);
3971 if (nativeEnum && nativeEnum->enumNode() && !enumValue.startsWith(
"%1."_L1.arg(nativeEnum->prefix()))) {
3972 m_writer->writeCharacters(
"%1.%2"_L1.arg(nativeEnum->prefix(), enumValue));
3977 m_writer->writeCharacters(enumValue);
3981 QList<
const Node *> parents;
3983 parents.prepend(node);
3989 parents << relative;
3991 m_writer->writeStartElement(dbNamespace,
"code");
3992 for (
auto parent : parents) {
3993 generateSynopsisName(parent, relative,
true);
3994 m_writer->writeCharacters((relative->genus() == Genus::QML) ?
"."_L1 :
"::"_L1);
3997 m_writer->writeCharacters(enumValue);
3998 m_writer->writeEndElement();
4002
4003
4004
4009 Q_ASSERT(node && !node->name().isEmpty());
4015 m_writer->writeStartElement(dbNamespace,
"note");
4022 m_writer->writeStartElement(dbNamespace,
"para");
4023 m_writer->writeCharacters(
4024 "This function can be invoked via the meta-object system and from QML. See ");
4025 generateSimpleLink(node->url(),
"Q_INVOKABLE");
4026 m_writer->writeCharacters(
".");
4027 m_writer->writeEndElement();
4031 m_writer->writeTextElement(
4032 dbNamespace,
"para",
4033 "This is a private signal. It can be used in signal connections but "
4034 "cannot be emitted by the user.");
4038 QString handler(node->name());
4039 int prefixLocation = handler.lastIndexOf(
'.', -2) + 1;
4040 handler[prefixLocation] = handler[prefixLocation].toTitleCase();
4041 handler.insert(prefixLocation, QLatin1String(
"on"));
4042 m_writer->writeStartElement(dbNamespace,
"para");
4043 m_writer->writeCharacters(
"The corresponding handler is ");
4044 m_writer->writeTextElement(dbNamespace,
"code", handler);
4045 m_writer->writeCharacters(
".");
4046 m_writer->writeEndElement();
4054 const auto *fn =
static_cast<
const FunctionNode *>(node);
4055 auto nodes = fn->associatedProperties();
4056 if (nodes.isEmpty())
4061 QMap<PropertyNode::FunctionRole, QList<
const PropertyNode *>> roleGroups;
4062 for (
const auto *n : std::as_const(nodes)) {
4063 const auto *pn =
static_cast<
const PropertyNode *>(n);
4064 PropertyNode::FunctionRole role = pn->role(fn);
4065 roleGroups[role].append(pn);
4077 for (
auto role : roleOrder) {
4078 const auto it = roleGroups.constFind(role);
4079 if (it == roleGroups.cend())
4082 const auto &properties = it.value();
4087 msg = QStringLiteral(
"Getter function");
4090 msg = QStringLiteral(
"Setter function");
4093 msg = QStringLiteral(
"Resetter function");
4096 msg = QStringLiteral(
"Notifier signal");
4099 msg = QStringLiteral(
"Bindable function");
4105 m_writer->writeStartElement(dbNamespace,
"para");
4106 if (properties.size() == 1) {
4107 const auto *pn = properties.first();
4108 m_writer->writeCharacters(msg +
" for property ");
4109 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4110 m_writer->writeCharacters(
". ");
4112 m_writer->writeCharacters(msg +
" for properties ");
4113 for (qsizetype i = 0; i < properties.size(); ++i) {
4114 const auto *pn = properties.at(i);
4115 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4116 m_writer->writeCharacters(Utilities::separator(i, properties.size()));
4118 m_writer->writeCharacters(
" ");
4120 m_writer->writeEndElement();
4127 const Node *linkNode;
4129 QString link = getAutoLink(&linkAtom, node, &linkNode);
4130 m_writer->writeStartElement(dbNamespace,
"para");
4131 m_writer->writeCharacters(
"This property supports ");
4132 generateSimpleLink(link,
"QProperty");
4133 m_writer->writeCharacters(
" bindings.");
4134 m_writer->writeEndElement();
4139 const auto *func =
static_cast<
const FunctionNode *>(node);
4140 m_writer->writeStartElement(dbNamespace,
"para");
4143 auto writeDocBookLink = [&](
const QString &target,
const QString &label) {
4144 const Node *linkNode =
nullptr;
4146 const QString &link = getAutoLink(&linkAtom, node, &linkNode);
4148 m_writer->writeStartElement(dbNamespace,
"link");
4149 if (!link.isEmpty() && linkNode) {
4150 m_writer->writeAttribute(xlinkNamespace,
"href", link);
4152 m_writer->writeAttribute(dbNamespace,
"linkend", target);
4154 m_writer->writeCharacters(label);
4155 m_writer->writeEndElement();
4158 const QString &functionType = func
->isSignal() ?
"signal" :
"slot";
4159 const QString &configKey = func
->isSignal() ?
"overloadedsignalstarget" :
"overloadedslotstarget";
4160 const QString &defaultTarget = func
->isSignal() ?
"connecting-overloaded-signals" :
"connecting-overloaded-slots";
4161 const QString &linkTarget = Config::instance().get(configKey).asString(defaultTarget);
4163 m_writer->writeCharacters(
"This " + functionType +
" is overloaded. ");
4165 QString snippet = generateOverloadSnippet(func);
4166 if (!snippet.isEmpty()) {
4167 m_writer->writeCharacters(
"To connect to this " + functionType +
":");
4168 m_writer->writeEndElement();
4170 m_writer->writeStartElement(dbNamespace,
"programlisting");
4171 m_writer->writeCharacters(snippet);
4172 m_writer->writeEndElement();
4174 m_writer->writeStartElement(dbNamespace,
"para");
4177 m_writer->writeCharacters(
"For more examples and approaches, see ");
4178 writeDocBookLink(linkTarget,
"connecting to overloaded " + functionType +
"s");
4181 const auto &args = node
->doc().overloadList();
4182 if (args.first().first.isEmpty()) {
4183 m_writer->writeCharacters(
"This is an overloaded function.");
4185 QString target = args.first().first;
4188 if (!target.contains(
"::")) {
4191 target = parent->name() +
"::" + target;
4194 m_writer->writeCharacters(
"This function overloads ");
4196 const Node *linkNode =
nullptr;
4198 QString link = getAutoLink(&linkAtom, node, &linkNode);
4199 if (!link.isEmpty() && linkNode) {
4200 generateSimpleLink(link, target);
4202 m_writer->writeCharacters(target);
4204 m_writer->writeCharacters(
".");
4208 m_writer->writeEndElement();
4217 m_writer->writeEndElement();
4225 bool closeSupplementarySection =
false;
4229 const QList<Node *> &collective = scn->collective();
4231 bool firstFunction =
true;
4232 for (
const auto *sharedNode : collective) {
4233 if (firstFunction) {
4234 startSectionBegin(sharedNode);
4236 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4237 m_writer->writeAttribute(
"renderas",
"sect2");
4238 writeXmlId(sharedNode);
4241 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4243 generateSynopsis(sharedNode, relative, Section::Details);
4245 if (firstFunction) {
4247 firstFunction =
false;
4249 m_writer->writeEndElement();
4256 startSectionBegin(node);
4258 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4262 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4263 m_writer->writeAttribute(
"renderas",
"sect2");
4265 m_writer->writeEndElement();
4268 startSectionBegin(node);
4270 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4275 Q_ASSERT(m_hasSection);
4284 closeSupplementarySection =
true;
4285 startSection(
"",
"Notes");
4289 const auto *func =
static_cast<
const FunctionNode *>(node);
4298 const auto property =
static_cast<
const PropertyNode *>(node);
4307 m_writer->writeStartElement(dbNamespace,
"para");
4309 m_writer->writeStartElement(dbNamespace,
"emphasis");
4310 m_writer->writeAttribute(
"role",
"bold");
4311 m_writer->writeCharacters(
"Access functions:");
4313 m_writer->writeEndElement();
4315 m_writer->writeEndElement();
4317 generateSectionList(section, node);
4324 m_writer->writeStartElement(dbNamespace,
"para");
4326 m_writer->writeStartElement(dbNamespace,
"emphasis");
4327 m_writer->writeAttribute(
"role",
"bold");
4328 m_writer->writeCharacters(
"Notifier signal:");
4330 m_writer->writeEndElement();
4332 m_writer->writeEndElement();
4334 generateSectionList(notifiers, node);
4338 const auto en =
static_cast<
const EnumNode *>(node);
4340 if (m_qflagsHref.isEmpty()) {
4341 Node *qflags =
m_qdb->findClassNode(QStringList(
"QFlags"));
4343 m_qflagsHref = linkForNode(qflags,
nullptr);
4347 m_writer->writeStartElement(dbNamespace,
"para");
4348 m_writer->writeCharacters(
"The ");
4349 m_writer->writeStartElement(dbNamespace,
"code");
4350 m_writer->writeCharacters(en->flagsType()->name());
4351 m_writer->writeEndElement();
4352 m_writer->writeCharacters(
" type is a typedef for ");
4353 m_writer->writeStartElement(dbNamespace,
"code");
4354 generateSimpleLink(m_qflagsHref,
"QFlags");
4355 m_writer->writeCharacters(
"<" + en->name() +
">. ");
4356 m_writer->writeEndElement();
4357 m_writer->writeCharacters(
"It stores an OR combination of ");
4358 m_writer->writeStartElement(dbNamespace,
"code");
4359 m_writer->writeCharacters(en->name());
4360 m_writer->writeEndElement();
4361 m_writer->writeCharacters(
" values.");
4362 m_writer->writeEndElement();
4367 if (closeSupplementarySection)
4378 bool useObsoleteMembers)
4383 if (!members.isEmpty()) {
4384 bool hasPrivateSignals =
false;
4385 bool isInvokable =
false;
4387 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4389 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4392 NodeVector::ConstIterator m = members.constBegin();
4393 while (m != members.constEnd()) {
4399 m_writer->writeStartElement(dbNamespace,
"listitem");
4401 m_writer->writeStartElement(dbNamespace,
"para");
4404 generateSynopsis(*m, relative, section
.style());
4405 if ((*m)->isFunction()) {
4407 if (fn->isPrivateSignal())
4408 hasPrivateSignals =
true;
4409 else if (fn->isInvokable())
4413 m_writer->writeEndElement();
4415 m_writer->writeEndElement();
4421 m_writer->writeEndElement();
4424 if (hasPrivateSignals)
4431 && !section.inheritedMembers().isEmpty()) {
4432 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4434 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4437 generateSectionInheritedList(section, relative);
4439 m_writer->writeEndElement();
4447 QList<std::pair<Aggregate *,
int>>::ConstIterator p = section.inheritedMembers().constBegin();
4448 while (p != section.inheritedMembers().constEnd()) {
4449 m_writer->writeStartElement(dbNamespace,
"listitem");
4450 m_writer->writeCharacters(QString::number((*p).second) + u' ');
4451 if ((*p).second == 1)
4452 m_writer->writeCharacters(section.singular());
4454 m_writer->writeCharacters(section.plural());
4455 m_writer->writeCharacters(
" inherited from ");
4456 generateSimpleLink(fileName((*p).first) +
'#'
4457 + Generator::cleanRef(section.title().toLower()),
4458 (*p).first->plainFullName(relative));
4464
4465
4466
4470 Q_ASSERT(m_writer ==
nullptr);
4471 m_writer = startDocument(pn);
4473 generateHeader(pn->fullTitle(), pn->subtitle(), pn);
4482
4483
4488 Q_ASSERT(m_writer ==
nullptr);
4489 m_writer = startDocument(qcn);
4492 QString title = qcn->fullTitle();
4494 title.append(
" QML Value Type");
4496 title.append(
" QML Type");
4499 title.append(
" (Singleton)");
4505 generateHeader(title, qcn->subtitle(), qcn);
4510 m_writer->writeStartElement(dbNamespace,
"note");
4511 m_writer->writeStartElement(dbNamespace,
"para");
4512 m_writer->writeStartElement(dbNamespace,
"emphasis");
4513 m_writer->writeAttribute(
"role",
"bold");
4514 m_writer->writeCharacters(
"Note: ");
4515 m_writer->writeEndElement();
4516 m_writer->writeCharacters(
"This type is a QML singleton. "
4517 "There is only one instance of this type in the QML engine.");
4518 m_writer->writeEndElement();
4519 m_writer->writeEndElement();
4522 startSection(
"details",
"Detailed Description");
4530 for (
const auto §ion : sections.stdQmlTypeDetailsSections()) {
4531 if (!section.isEmpty()) {
4532 startSection(section.title().toLower(), section.title());
4534 for (
const auto &member : section.members())
4535 generateDetailedQmlMember(member, qcn);
4541 generateObsoleteQmlMembers(sections);
4550
4551
4552
4559 if (!title.isEmpty())
4563 title += n->element() + QLatin1Char(
'.');
4564 title += n->name() +
" : " + n->dataType();
4569 auto generateQmlMethodTitle = [&](
Node *node) {
4577 if (!scn->name().isEmpty())
4578 heading = scn->name() +
" group";
4580 heading = node->name();
4581 startSection(scn, heading);
4586 const QList<Node *> sharedNodes = scn->collective();
4587 for (
const auto &sharedNode : sharedNodes) {
4588 if (sharedNode->isQmlProperty()) {
4589 auto *qpn =
static_cast<QmlPropertyNode *>(sharedNode);
4591 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4592 m_writer->writeAttribute(
"renderas",
"sect2");
4594 m_writer->writeCharacters(getQmlPropertyTitle(qpn));
4595 m_writer->writeEndElement();
4598 generateDocBookSynopsis(qpn);
4603 startSection(qpn, getQmlPropertyTitle(qpn));
4607 const QList<Node *> &sharedNodes = scn->collective();
4612 for (
const auto &sharedNode : sharedNodes) {
4614 if (!sharedNode->isFunction(Genus::QML) && !sharedNode->isQmlProperty()) {
4620 startSectionBegin(sharedNode);
4622 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4623 m_writer->writeAttribute(
"renderas",
"sect2");
4627 if (sharedNode->isFunction(Genus::QML))
4628 generateQmlMethodTitle(sharedNode);
4629 else if (sharedNode->isQmlProperty())
4630 m_writer->writeCharacters(
4631 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(sharedNode)));
4637 m_writer->writeEndElement();
4638 generateDocBookSynopsis(sharedNode);
4644 startSectionBegin(refForNode(node));
4647 generateQmlMethodTitle(node);
4648 else if (node->isQmlProperty())
4649 m_writer->writeCharacters(
4650 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(node)));
4655 startSectionBegin(node);
4659 startSectionBegin(node);
4660 generateQmlMethodTitle(node);
4674
4675
4682 if (!node->url().isNull())
4686 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4729 generateCppReferencePage(
static_cast<
Aggregate *>(node));
4739 auto *aggregate =
static_cast<
Aggregate *>(node);
4740 for (
auto c : aggregate->childNodes()) {
4741 if (node->isPageNode() && !node->isPrivate())
4742 generateDocumentation(c);
4753 Q_ASSERT(m_writer ==
nullptr);
4754 m_writer = startDocument(aggregate);
4757 generateHeader(aggregate->plainFullName(),
"", aggregate);
4762 if (!aggregate
->doc().isEmpty()) {
4763 startSection(
"details",
"Detailed Description");
4765 generateBody(aggregate);
4774 for (
const auto §ion : std::as_const(*detailsSections)) {
4775 if (section.isEmpty())
4778 startSection(section.title().toLower(), section.title());
4780 const QList<Node *> &members = section.members();
4781 for (
const auto &member : members) {
4782 if (!member->isClassNode()) {
4783 generateDetailedMember(member, aggregate);
4785 startSectionBegin();
4786 generateFullName(member, aggregate);
4789 generateBrief(member);
4803
4804
4809 Q_ASSERT(m_writer ==
nullptr);
4810 m_writer = startDocument(cn);
4813 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4819 if (cn
->genus() != Genus::DOC && cn
->genus() != Genus::DontCare) {
4830 if (!nmm.isEmpty()) {
4831 startSection(
"namespaces",
"Namespaces");
4832 generateAnnotatedList(cn, nmm.values(),
"namespaces");
4836 if (!nmm.isEmpty()) {
4837 startSection(
"classes",
"Classes");
4838 generateAnnotatedList(cn, nmm.values(),
"classes");
4844 bool generatedTitle =
false;
4846 startSection(
"details",
"Detailed Description");
4847 generatedTitle =
true;
4852 !cn
->doc().body().isEmpty() ||
4854 !cn
->doc().alsoList().empty() ||
4857 writeAnchor(
"details");
4863 if (!cn->noAutoList() && (cn->isGroup() || cn->isQmlModule()))
4864 generateAnnotatedList(cn, cn->members(),
"members", AutoSection);
4875
4876
4877
4878
4883 QString name = cn->name().toLower();
4884 name.replace(QChar(
' '), QString(
"-"));
4885 QString filename = cn->tree()->physicalModuleName() +
"-" + name +
"." + fileExtension();
4888 Q_ASSERT(m_writer ==
nullptr);
4889 m_writer = startGenericDocument(cn, filename);
4892 generateHeader(cn->fullTitle(), cn->subtitle(), cn);
4898 m_writer->writeStartElement(dbNamespace,
"para");
4899 m_writer->writeCharacters(
"Each function or type documented here is related to a class or "
4900 "namespace that is documented in a different module. The reference "
4901 "page for that class or namespace will link to the function or type "
4903 m_writer->writeEndElement();
4907 for (
const auto &member : members)
4908 generateDetailedMember(member, cnc);
4921 m_writer->writeStartElement(dbNamespace,
"link");
4922 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(node));
4923 m_writer->writeAttribute(xlinkNamespace,
"role", targetType(node));
4924 m_writer->writeCharacters(node->fullName(relative));
4925 m_writer->writeEndElement();
4929 const Node *actualNode)
4931 Q_ASSERT(apparentNode);
4932 Q_ASSERT(actualNode);
4935 m_writer->writeStartElement(dbNamespace,
"link");
4936 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(actualNode));
4937 m_writer->writeAttribute(
"role", targetType(actualNode));
4938 m_writer->writeCharacters(fullName);
4939 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 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)
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[]
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.