34#include <QtCore/qlist.h>
35#include <QtCore/qmap.h>
36#include <QtCore/quuid.h>
37#include <QtCore/qurl.h>
38#include <QtCore/qregularexpression.h>
39#include <QtCore/qversionnumber.h>
47using namespace Qt::StringLiterals;
49static const char dbNamespace[] =
"http://docbook.org/ns/docbook";
57 m_writer->writeCharacters(
"\n");
65 m_writer->writeAttribute(
"xml:id", registerRef(id,
true));
78 QString id = Generator::cleanRef(refForNode(node),
true);
80 m_writer->writeAttribute(
"xml:id", id);
87 m_writer->writeStartElement(dbNamespace,
"section");
90 m_writer->writeStartElement(dbNamespace,
"title");
95 m_writer->writeStartElement(dbNamespace,
"section");
98 m_writer->writeStartElement(dbNamespace,
"title");
103 m_writer->writeEndElement();
109 startSectionBegin(id);
110 m_writer->writeCharacters(title);
116 startSectionBegin(node);
117 m_writer->writeCharacters(title);
124 startSection(
"", title);
129 m_writer->writeEndElement();
138 m_writer->writeEmptyElement(dbNamespace,
"anchor");
144
145
146
151 m_config = &Config::instance();
157 if (m_projectDescription.isEmpty() && !m_project.isEmpty())
158 m_projectDescription = m_project + QLatin1String(
" Reference Documentation");
161 if (m_naturalLanguage.isEmpty())
162 m_naturalLanguage = QLatin1String(
"en");
166 m_config->get(format() + Config::dot +
"usedocbookextensions").asBool();
167 m_useITS = m_config->get(format() + Config::dot +
"its").asBool();
176
177
184
185
186
187
202 QString rewritten = code;
203 static const QRegularExpression re(
"(<@[^>&]*>)|(<\\/@[^&>]*>)");
204 rewritten.replace(re,
"");
209
210
216 qsizetype skipAhead = 0;
217 Genus genus = Genus::DontCare;
225 if (!m_inLink && !m_inContents && !m_inSectionHeading) {
226 const Node *node =
nullptr;
227 QString link = getAutoLink(atom, relative, &node, genus);
232 if (link.isEmpty()) {
233 m_writer->writeCharacters(atom->string());
235 beginLink(link, node, relative);
240 m_writer->writeCharacters(atom->string());
250 m_writer->writeStartElement(dbNamespace,
"para");
256 m_writer->writeEndElement();
266 m_writer->writeCharacters(plainCode(atom->string()));
268 m_writer->writeTextElement(dbNamespace,
"code", plainCode(atom->string()));
270 case Atom::CaptionLeft:
271 m_writer->writeStartElement(dbNamespace,
"title");
275 m_writer->writeEndElement();
279 m_writer->writeStartElement(dbNamespace,
"programlisting");
280 m_writer->writeAttribute(
"language",
"qml");
282 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
283 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
284 m_writer->writeEndElement();
288 m_writer->writeStartElement(dbNamespace,
"programlisting");
290 if (atom->strings().count() == 2)
291 m_writer->writeAttribute(
"language", atom->string(1));
293 m_writer->writeAttribute(
"language",
"cpp");
295 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
296 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
297 m_writer->writeEndElement();
301 m_writer->writeStartElement(dbNamespace,
"programlisting");
302 m_writer->writeAttribute(
"language",
"cpp");
303 m_writer->writeAttribute(
"role",
"bad");
305 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
306 m_writer->writeCharacters(plainCode(removeCodeMarkers(atom->string())));
307 m_writer->writeEndElement();
314 qsizetype offset{ 0 };
323 case Atom::FootnoteLeft:
324 m_writer->writeStartElement(dbNamespace,
"footnote");
326 m_writer->writeStartElement(dbNamespace,
"para");
329 case Atom::FootnoteRight:
330 m_writer->writeEndElement();
333 m_writer->writeEndElement();
341 m_writer->writeStartElement(dbNamespace,
"emphasis");
342 m_writer->writeAttribute(
"role",
"bold");
344 m_writer->writeStartElement(dbNamespace,
"emphasis");
346 m_writer->writeStartElement(dbNamespace,
"emphasis");
347 m_writer->writeAttribute(
"role",
"underline");
349 m_writer->writeStartElement(dbNamespace,
"subscript");
351 m_writer->writeStartElement(dbNamespace,
"superscript");
354 m_writer->writeStartElement(dbNamespace,
"code");
356 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
359 m_writer->writeAttribute(
"role",
"parameter");
363 m_writer->writeStartElement(dbNamespace,
"guilabel");
365 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
367 m_writer->writeStartElement(dbNamespace,
368 appendTrademark(atom->find(Atom::FormattingRight)) ?
369 "trademark" :
"phrase");
371 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
373 m_writer->writeStartElement(dbNamespace,
"phrase");
375 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
377 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
390 m_writer->writeEndElement();
393 m_inTeletype =
false;
396 relative
->location().warning(QStringLiteral(
"Unsupported formatting: %1").arg(atom->string()));
400 if (
const CollectionNode *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group))
401 generateList(cn, atom->string(), Generator::sortOrder(atom->strings().last()));
404 const auto sortOrder{Generator::sortOrder(atom->strings().last())};
405 bool hasGeneratedSomething =
false;
406 if (atom->string() == QLatin1String(
"annotatedclasses")
407 || atom->string() == QLatin1String(
"attributions")
408 || atom->string() == QLatin1String(
"namespaces")) {
409 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedclasses")
410 ? m_qdb->getCppClasses()
411 : atom->string() == QLatin1String(
"attributions") ? m_qdb->getAttributions()
412 : m_qdb->getNamespaces();
413 generateAnnotatedList(relative, things.values(), atom->string(), Auto, sortOrder);
414 hasGeneratedSomething = !things.isEmpty();
415 }
else if (atom->string() == QLatin1String(
"annotatedexamples")
416 || atom->string() == QLatin1String(
"annotatedattributions")) {
417 const NodeMultiMap things = atom->string() == QLatin1String(
"annotatedexamples")
418 ? m_qdb->getExamples()
419 : m_qdb->getAttributions();
420 generateAnnotatedLists(relative, things, atom->string());
421 hasGeneratedSomething = !things.isEmpty();
422 }
else if (atom->string() == QLatin1String(
"classes")
423 || atom->string() == QLatin1String(
"qmlbasictypes")
424 || atom->string() == QLatin1String(
"qmlvaluetypes")
425 || atom->string() == QLatin1String(
"qmltypes")) {
426 const NodeMultiMap things = atom->string() == QLatin1String(
"classes")
427 ? m_qdb->getCppClasses()
428 : (atom->string() == QLatin1String(
"qmlvaluetypes")
429 || atom->string() == QLatin1String(
"qmlbasictypes"))
430 ? m_qdb->getQmlValueTypes()
431 : m_qdb->getQmlTypes();
432 generateCompactList(relative, things,
true, QString(), atom->string());
433 hasGeneratedSomething = !things.isEmpty();
434 }
else if (atom->string().contains(
"classes ")) {
435 QString rootName = atom->string().mid(atom->string().indexOf(
"classes") + 7).trimmed();
438 hasGeneratedSomething = !things.isEmpty();
439 generateCompactList(relative, things,
true, rootName, atom->string());
440 }
else if ((idx = atom->string().indexOf(QStringLiteral(
"bymodule"))) != -1) {
441 QString moduleName = atom->string().mid(idx + 8).trimmed();
444 if (
const CollectionNode *cn = qdb->getCollectionNode(moduleName, moduleType)) {
446 switch (moduleType) {
452 if (atom->string().contains(QLatin1String(
"qmlvaluetypes")))
458 generateAnnotatedList(relative, cn->members(), atom->string(), Auto, sortOrder);
462 if (!map.isEmpty()) {
463 generateAnnotatedList(relative, map.values(), atom->string(), Auto, sortOrder);
464 hasGeneratedSomething =
true;
467 }
else if (atom->string() == QLatin1String(
"classhierarchy")) {
468 generateClassHierarchy(relative, m_qdb->getCppClasses());
469 hasGeneratedSomething = !m_qdb->getCppClasses().isEmpty();
470 }
else if (atom->string().startsWith(
"obsolete")) {
471 QString prefix = atom->string().contains(
"cpp") ? QStringLiteral(
"Q") : QString();
472 const NodeMultiMap &things = atom->string() == QLatin1String(
"obsoleteclasses")
473 ? m_qdb->getObsoleteClasses()
474 : atom->string() == QLatin1String(
"obsoleteqmltypes")
475 ? m_qdb->getObsoleteQmlTypes()
476 : atom->string() == QLatin1String(
"obsoletecppmembers")
477 ? m_qdb->getClassesWithObsoleteMembers()
478 : m_qdb->getQmlTypesWithObsoleteMembers();
479 generateCompactList(relative, things,
false, prefix, atom->string());
480 hasGeneratedSomething = !things.isEmpty();
481 }
else if (atom->string() == QLatin1String(
"functionindex")) {
482 generateFunctionIndex(relative);
483 hasGeneratedSomething = !m_qdb->getFunctionIndex().isEmpty();
484 }
else if (atom->string() == QLatin1String(
"legalese")) {
485 generateLegaleseList(relative);
486 hasGeneratedSomething = !m_qdb->getLegaleseTexts().isEmpty();
487 }
else if (atom->string() == QLatin1String(
"overviews")
488 || atom->string() == QLatin1String(
"cpp-modules")
489 || atom->string() == QLatin1String(
"qml-modules")
490 || atom->string() == QLatin1String(
"related")) {
491 generateList(relative, atom->string());
492 hasGeneratedSomething =
true;
494 }
else if (
const auto *cn = m_qdb->getCollectionNode(atom->string(), NodeType::Group); cn) {
495 generateAnnotatedList(cn, cn->members(), atom->string(), ItemizedList, sortOrder);
496 hasGeneratedSomething =
true;
501 if (!hasGeneratedSomething && !m_inPara) {
502 m_writer->writeEmptyElement(dbNamespace,
"para");
534 m_writer->writeStartElement(dbNamespace,
"figure");
541 generateAtom(current, relative,
nullptr);
546 generateAtom(current, relative,
nullptr);
552 generateAtom(current, relative,
nullptr);
556 m_closeFigureWrapper =
true;
567 m_writer->writeStartElement(dbNamespace,
"figure");
574 generateAtom(current, relative,
nullptr);
579 generateAtom(current, relative,
nullptr);
585 generateAtom(current, relative,
nullptr);
589 m_closeFigureWrapper =
true;
612 m_writer->writeStartElement(dbNamespace, tag);
615 auto maybe_resolved_file{file_resolver.resolve(atom->string())};
616 if (!maybe_resolved_file) {
618 relative
->location().warning(QStringLiteral(
"Missing image: %1").arg(atom->string()));
620 m_writer->writeStartElement(dbNamespace,
"textobject");
622 m_writer->writeStartElement(dbNamespace,
"para");
623 m_writer->writeTextElement(dbNamespace,
"emphasis",
624 "[Missing image " + atom->string() +
"]");
625 m_writer->writeEndElement();
627 m_writer->writeEndElement();
631 QString file_name{QFileInfo{file.get_path()}.fileName()};
635 "%1/%2"_L1.arg(outputDir(), imagesOutputDir()));
639 m_writer->writeTextElement(dbNamespace,
"alt", atom->next()->string());
643 m_writer->writeStartElement(dbNamespace,
"imageobject");
645 m_writer->writeEmptyElement(dbNamespace,
"imagedata");
646 const auto &imgPath =
"%1/%2"_L1.arg(imagesOutputDir(), file_name);
648 m_writer->writeAttribute(
"fileref", imgPath);
650 m_writer->writeEndElement();
654 setImageFileName(relative, imgPath);
657 m_writer->writeEndElement();
661 if (m_closeFigureWrapper) {
662 m_writer->writeEndElement();
664 m_closeFigureWrapper =
false;
672 QString admonType = atom->typeString().toLower();
675 m_writer->writeStartElement(dbNamespace, admonType);
677 m_writer->writeStartElement(dbNamespace,
"para");
680 case Atom::ImportantRight:
681 case Atom::NoteRight:
682 case Atom::WarningRight:
683 m_writer->writeEndElement();
686 m_writer->writeEndElement();
694 const Node *node =
nullptr;
695 QString link = getLink(atom, relative, &node);
696 beginLink(link, node, relative);
700 const Node *node =
static_cast<
const Node*>(Utilities::nodeForString(atom->string()));
701 beginLink(linkForNode(node, relative), node, relative);
711 m_writer->writeEndElement();
717 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
720 m_writer->writeStartElement(dbNamespace,
"variablelist");
723 m_writer->writeStartElement(dbNamespace,
"informaltable");
725 m_writer->writeStartElement(dbNamespace,
"thead");
727 m_writer->writeStartElement(dbNamespace,
"tr");
729 m_writer->writeTextElement(dbNamespace,
"th",
"Constant");
732 m_threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
733 if (m_threeColumnEnumValueTable && relative->isEnumType(Genus::CPP)) {
735 m_writer->writeTextElement(dbNamespace,
"th",
"Value");
740 m_writer->writeTextElement(dbNamespace,
"th",
"Description");
744 m_writer->writeEndElement();
746 m_writer->writeEndElement();
749 m_writer->writeStartElement(dbNamespace,
"orderedlist");
751 if (atom->next() !=
nullptr && atom->next()->string().toInt() != 1)
752 m_writer->writeAttribute(
"startingnumber", atom->next()->string());
755 m_writer->writeAttribute(
"numeration",
"upperalpha");
757 m_writer->writeAttribute(
"numeration",
"loweralpha");
759 m_writer->writeAttribute(
"numeration",
"upperroman");
761 m_writer->writeAttribute(
"numeration",
"lowerroman");
763 m_writer->writeAttribute(
"numeration",
"arabic");
773 m_writer->writeStartElement(dbNamespace,
"varlistentry");
775 m_writer->writeStartElement(dbNamespace,
"item");
777 std::pair<QString,
int> pair = getAtomListValue(atom);
778 skipAhead = pair.second;
780 m_writer->writeStartElement(dbNamespace,
"tr");
782 m_writer->writeStartElement(dbNamespace,
"td");
784 m_writer->writeStartElement(dbNamespace,
"para");
786 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
787 generateEnumValue(pair.first, relative);
788 m_writer->writeEndElement();
790 m_writer->writeEndElement();
794 const auto enume =
static_cast<
const EnumNode *>(relative);
795 QString itemValue = enume->itemValue(atom
->next()->string());
797 m_writer->writeStartElement(dbNamespace,
"td");
798 if (itemValue.isEmpty())
799 m_writer->writeCharacters(
"?");
801 m_writer->writeStartElement(dbNamespace,
"code");
803 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
804 m_writer->writeCharacters(itemValue);
805 m_writer->writeEndElement();
807 m_writer->writeEndElement();
815 m_writer->writeEndElement();
821 m_writer->writeEndElement();
828 m_inListItemLineOpen =
false;
830 m_writer->writeStartElement(dbNamespace,
"listitem");
832 m_writer->writeStartElement(dbNamespace,
"para");
835 if (m_threeColumnEnumValueTable) {
837 m_writer->writeEmptyElement(dbNamespace,
"td");
839 m_inListItemLineOpen =
false;
841 m_writer->writeStartElement(dbNamespace,
"td");
843 m_inListItemLineOpen =
true;
847 m_writer->writeStartElement(dbNamespace,
"listitem");
856 m_writer->writeEndElement();
859 m_writer->writeEndElement();
861 m_writer->writeEndElement();
864 if (m_inListItemLineOpen) {
865 m_writer->writeEndElement();
867 m_inListItemLineOpen =
false;
869 m_writer->writeEndElement();
872 m_writer->writeEndElement();
877 case Atom::ListRight:
883 m_writer->writeEndElement();
890 m_writer->writeStartElement(dbNamespace,
"para");
896 m_writer->writeEndElement();
901 case Atom::QuotationLeft:
902 m_writer->writeStartElement(dbNamespace,
"blockquote");
903 m_inBlockquote =
true;
905 case Atom::QuotationRight:
906 m_writer->writeEndElement();
908 m_inBlockquote =
false;
911 m_writer->device()->write(atom->string().toUtf8());
917 currentSectionLevel = atom->string().toInt() +
hOffset(relative
);
919 if (currentSectionLevel > 1) {
922 while (!sectionLevels.empty() && sectionLevels.top() >= currentSectionLevel) {
924 m_writer->writeEndElement();
928 sectionLevels.push(currentSectionLevel);
930 m_writer->writeStartElement(dbNamespace,
"section");
931 writeXmlId(Tree::refForAtom(atom));
944 generateAtom(atom->next(), relative,
nullptr);
945 generateAtom(atom->next()->next(), relative,
nullptr);
946 generateAtom(atom->next()->next()->next(), relative,
nullptr);
948 m_closeSectionAfterGeneratedList =
true;
955 m_writer->writeTextElement(dbNamespace,
"title",
"");
964 if (currentSectionLevel > 1) {
965 m_writer->writeStartElement(dbNamespace,
"title");
966 m_inSectionHeading =
true;
971 if (currentSectionLevel > 1) {
972 m_writer->writeEndElement();
974 m_inSectionHeading =
false;
977 case Atom::SidebarLeft:
978 m_writer->writeStartElement(dbNamespace,
"sidebar");
980 case Atom::SidebarRight:
981 m_writer->writeEndElement();
985 if (m_inLink && !m_inContents && !m_inSectionHeading)
988 m_writer->writeCharacters(atom->string());
991 std::pair<QString, QString> pair = getTableWidthAttr(atom);
992 QString attr = pair.second;
993 QString width = pair.first;
996 m_writer->writeEndElement();
1001 m_tableHeaderAlreadyOutput =
false;
1003 m_writer->writeStartElement(dbNamespace,
"informaltable");
1004 m_writer->writeAttribute(
"style", attr);
1005 if (!width.isEmpty())
1006 m_writer->writeAttribute(
"width", width);
1009 case Atom::TableRight:
1010 m_tableWidthAttr = {
"",
""};
1011 m_writer->writeEndElement();
1020 if (m_tableHeaderAlreadyOutput) {
1023 m_writer->writeEndElement();
1026 const QString &attr = m_tableWidthAttr.second;
1027 const QString &width = m_tableWidthAttr.first;
1029 m_writer->writeStartElement(dbNamespace,
"informaltable");
1030 m_writer->writeAttribute(
"style", attr);
1031 if (!width.isEmpty())
1032 m_writer->writeAttribute(
"width", width);
1035 m_tableHeaderAlreadyOutput =
true;
1041 id = TextUtils::asAsciiPrintable(next->string());
1046 m_writer->writeStartElement(dbNamespace,
"thead");
1048 m_writer->writeStartElement(dbNamespace,
"tr");
1051 m_inTableHeader =
true;
1054 m_closeTableCell =
true;
1055 m_writer->writeStartElement(dbNamespace,
"td");
1061 if (m_closeTableCell) {
1062 m_closeTableCell =
false;
1063 m_writer->writeEndElement();
1067 m_writer->writeEndElement();
1071 m_writer->writeStartElement(dbNamespace,
"tr");
1074 m_writer->writeEndElement();
1076 m_inTableHeader =
false;
1086 bool hasTarget {
false};
1088 id = TextUtils::asAsciiPrintable(atom
->next()->string());
1093 m_writer->writeStartElement(dbNamespace,
"tr");
1096 if (atom->string().isEmpty()) {
1097 m_writer->writeAttribute(
"valign",
"top");
1102 QStringList args = atom->string().split(
"\"", Qt::SkipEmptyParts);
1105 const int nArgs = args.size();
1110 QStringLiteral(
"Error when parsing attributes for the table: got \"%1\"")
1111 .arg(atom->string()));
1113 for (
int i = 0; i + 1 < nArgs; i += 2) {
1116 const QString &attr = args.at(i).chopped(1);
1119 writeXmlId(args.at(i + 1));
1121 m_writer->writeAttribute(attr, args.at(i + 1));
1137 m_closeTableRow =
true;
1138 m_writer->writeEndElement();
1144 if (m_closeTableRow) {
1145 m_closeTableRow =
false;
1146 m_writer->writeEndElement();
1150 m_writer->writeEndElement();
1153 case Atom::TableItemLeft:
1154 m_writer->writeStartElement(dbNamespace, m_inTableHeader ?
"th" :
"td");
1156 for (
int i = 0; i < atom->count(); ++i) {
1157 const QString &p = atom->string(i);
1158 if (p.contains(
'=')) {
1159 QStringList lp = p.split(QLatin1Char(
'='));
1160 m_writer->writeAttribute(lp.at(0), lp.at(1));
1162 QStringList spans = p.split(QLatin1Char(
','));
1163 if (spans.size() == 2) {
1164 if (spans.at(0) !=
"1")
1165 m_writer->writeAttribute(
"colspan", spans.at(0).trimmed());
1166 if (spans.at(1) !=
"1")
1167 m_writer->writeAttribute(
"rowspan", spans.at(1).trimmed());
1174 case Atom::TableItemRight:
1175 m_writer->writeEndElement();
1187 QString nextId = TextUtils::asAsciiPrintable(
1189 QString ownId = TextUtils::asAsciiPrintable(atom->string());
1190 if (nextId == ownId)
1194 writeAnchor(TextUtils::asAsciiPrintable(atom->string()));
1196 case Atom::UnhandledFormat:
1197 m_writer->writeStartElement(dbNamespace,
"emphasis");
1198 m_writer->writeAttribute(
"role",
"bold");
1199 m_writer->writeCharacters(
"<Missing DocBook>");
1200 m_writer->writeEndElement();
1202 case Atom::UnknownCommand:
1203 m_writer->writeStartElement(dbNamespace,
"emphasis");
1204 m_writer->writeAttribute(
"role",
"bold");
1206 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1207 m_writer->writeCharacters(
"<Unknown command>");
1208 m_writer->writeStartElement(dbNamespace,
"code");
1209 m_writer->writeCharacters(atom->string());
1210 m_writer->writeEndElement();
1211 m_writer->writeEndElement();
1231 if (classMap.isEmpty())
1234 std::function<
void(
ClassNode *)> generateClassAndChildren
1235 = [
this, &relative, &generateClassAndChildren](ClassNode * classe) {
1236 m_writer->writeStartElement(dbNamespace,
"listitem");
1240 m_writer->writeStartElement(dbNamespace,
"para");
1241 generateFullName(classe, relative);
1242 m_writer->writeEndElement();
1246 bool hasChild =
false;
1247 for (
const RelatedClass &relatedClass : classe->derivedClasses()) {
1248 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1255 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1258 for (
const RelatedClass &relatedClass: classe->derivedClasses()) {
1259 if (relatedClass.m_node && relatedClass.m_node->isInAPI()) {
1260 generateClassAndChildren(relatedClass.m_node);
1264 m_writer->writeEndElement();
1269 m_writer->writeEndElement();
1273 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1276 for (
const auto &it : classMap) {
1277 auto *classe =
static_cast<ClassNode *>(it);
1278 if (classe->baseClasses().isEmpty())
1279 generateClassAndChildren(classe);
1282 m_writer->writeEndElement();
1291 if (m_linkNode && m_linkNode->isFunction()) {
1293 if (match.hasMatch()) {
1295 qsizetype leftParenLoc = match.capturedStart(1);
1296 m_writer->writeCharacters(atom->string().left(leftParenLoc));
1298 m_writer->writeCharacters(atom->string().mid(leftParenLoc));
1302 m_writer->writeCharacters(atom->string());
1306
1307
1308
1312 m_writer->writeStartElement(dbNamespace,
"link");
1313 m_writer->writeAttribute(xlinkNamespace,
"href", link);
1314 if (node && !(relative && node->status() == relative->status())
1315 && node->isDeprecated())
1316 m_writer->writeAttribute(
"role",
"deprecated");
1325 m_writer->writeEndElement();
1327 m_linkNode =
nullptr;
1331 Qt::SortOrder sortOrder)
1336 if (selector == QLatin1String(
"overviews"))
1338 else if (selector == QLatin1String(
"cpp-modules"))
1340 else if (selector == QLatin1String(
"qml-modules"))
1345 m_qdb->mergeCollections(type, cnm, relative);
1346 const QList<CollectionNode *> collectionList = cnm.values();
1347 nodeList.reserve(collectionList.size());
1348 for (
auto *collectionNode : collectionList)
1349 nodeList.append(collectionNode);
1350 generateAnnotatedList(relative, nodeList, selector, Auto, sortOrder);
1353
1354
1355
1356 Node *n =
const_cast<
Node *>(relative);
1357 auto *cn =
static_cast<CollectionNode *>(n);
1358 m_qdb->mergeCollections(cn);
1359 generateAnnotatedList(cn, cn->members(), selector, Auto, sortOrder);
1364
1365
1366
1368 const QString &selector, GeneratedListType type,
1369 Qt::SortOrder sortOrder)
1371 if (nodeList.isEmpty())
1375 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1376 if (
std::all_of(nodeList.cbegin(), nodeList.cend(), [&policy](
const Node *n) {
1378 return !InclusionFilter::isIncluded(policy, context) || n->isDeprecated();
1385 bool noItemsHaveTitle =
1386 type == ItemizedList ||
std::all_of(nodeList.begin(), nodeList.end(),
1387 [](
const Node* node) {
1388 return node->doc().briefText().toString().isEmpty();
1392 if (type == AutoSection && m_hasSection)
1393 startSection(
"",
"Contents");
1396 if (!nodeList.isEmpty()) {
1397 m_writer->writeStartElement(dbNamespace, noItemsHaveTitle ?
"itemizedlist" :
"variablelist");
1398 m_writer->writeAttribute(
"role", selector);
1402 members.reserve(nodeList.size());
1403 std::copy_if(nodeList.cbegin(), nodeList.cend(),
std::back_inserter(members),
1404 [&policy](
const Node *n) {
1406 return InclusionFilter::isIncluded(policy, context) && !n->isDeprecated();
1409 if (sortOrder == Qt::DescendingOrder)
1415 auto sameLocation = [
this](
const Node *a,
const Node *b) {
1416 return fullDocumentLocation(a) == fullDocumentLocation(b);
1418 members.erase(
std::unique(members.begin(), members.end(), sameLocation), members.end());
1420 for (
const auto &node : std::as_const(members)) {
1421 if (noItemsHaveTitle) {
1422 m_writer->writeStartElement(dbNamespace,
"listitem");
1424 m_writer->writeStartElement(dbNamespace,
"para");
1426 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1428 m_writer->writeStartElement(dbNamespace,
"term");
1430 generateFullName(node, relative);
1431 if (noItemsHaveTitle) {
1432 m_writer->writeEndElement();
1434 m_writer->writeEndElement();
1436 m_writer->writeEndElement();
1438 m_writer->writeStartElement(dbNamespace,
"listitem");
1440 m_writer->writeStartElement(dbNamespace,
"para");
1441 m_writer->writeCharacters(node->doc().briefText().toString());
1442 m_writer->writeEndElement();
1444 m_writer->writeEndElement();
1446 m_writer->writeEndElement();
1451 m_writer->writeEndElement();
1455 if (type == AutoSection && m_hasSection)
1460
1461
1462
1464 const QString &selector)
1467 for (
const QString &name : nmm.uniqueKeys()) {
1468 if (!name.isEmpty())
1469 startSection(name.toLower(), name);
1470 generateAnnotatedList(relative, nmm.values(name), selector);
1471 if (!name.isEmpty())
1477
1478
1479
1480
1481
1482
1483
1484
1485
1487 bool includeAlphabet,
const QString &commonPrefix,
1488 const QString &selector)
1498 const int NumParagraphs = 37;
1499 qsizetype commonPrefixLen = commonPrefix.size();
1502
1503
1504
1505
1506
1508 QString paragraphName[NumParagraphs + 1];
1509 QSet<
char> usedParagraphNames;
1511 for (
auto c = nmm.constBegin(); c != nmm.constEnd(); ++c) {
1512 QStringList pieces = c.key().split(
"::");
1513 int idx = commonPrefixLen;
1514 if (idx > 0 && !pieces.last().startsWith(commonPrefix, Qt::CaseInsensitive))
1516 QString last = pieces.last().toLower();
1517 QString key = last.mid(idx);
1519 int paragraphNr = NumParagraphs - 1;
1521 if (key[0].digitValue() != -1) {
1522 paragraphNr = key[0].digitValue();
1523 }
else if (key[0] >= QLatin1Char(
'a') && key[0] <= QLatin1Char(
'z')) {
1524 paragraphNr = 10 + key[0].unicode() -
'a';
1527 paragraphName[paragraphNr] = key[0].toUpper();
1528 usedParagraphNames.insert(key[0].toLower().cell());
1529 paragraph[paragraphNr].insert(last, c.value());
1533
1534
1535
1536
1537
1538
1539
1540 int paragraphOffset[NumParagraphs + 1];
1541 paragraphOffset[0] = 0;
1542 for (
int i = 0; i < NumParagraphs; i++)
1543 paragraphOffset[i + 1] = paragraphOffset[i] + paragraph[i].size();
1546 if (includeAlphabet && !usedParagraphNames.isEmpty()) {
1547 m_writer->writeStartElement(dbNamespace,
"simplelist");
1550 for (
int i = 0; i < 26; i++) {
1552 if (usedParagraphNames.contains(
char(
'a' + i))) {
1553 m_writer->writeStartElement(dbNamespace,
"member");
1554 generateSimpleLink(ch, ch.toUpper());
1555 m_writer->writeEndElement();
1560 m_writer->writeEndElement();
1565 QHash<QString,
int> nameOccurrences;
1566 for (
const auto &[key, node] : nmm.asKeyValueRange()) {
1567 QStringList pieces{node->fullName(relative).split(
"::"_L1)};
1568 const QString &name{pieces.last()};
1569 nameOccurrences[name]++;
1574 int curParOffset = 0;
1576 m_writer->writeStartElement(dbNamespace,
"variablelist");
1577 m_writer->writeAttribute(
"role", selector);
1580 for (
int i = 0; i < nmm.size(); i++) {
1581 while ((curParNr < NumParagraphs) && (curParOffset == paragraph[curParNr].size())) {
1588 if (curParOffset == 0) {
1590 m_writer->writeEndElement();
1592 m_writer->writeEndElement();
1594 m_writer->writeEndElement();
1598 m_writer->writeStartElement(dbNamespace,
"varlistentry");
1599 if (includeAlphabet)
1600 writeXmlId(paragraphName[curParNr][0].toLower());
1603 m_writer->writeStartElement(dbNamespace,
"term");
1604 m_writer->writeStartElement(dbNamespace,
"emphasis");
1605 m_writer->writeAttribute(
"role",
"bold");
1606 m_writer->writeCharacters(paragraphName[curParNr]);
1607 m_writer->writeEndElement();
1608 m_writer->writeEndElement();
1611 m_writer->writeStartElement(dbNamespace,
"listitem");
1613 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1618 m_writer->writeStartElement(dbNamespace,
"listitem");
1620 m_writer->writeStartElement(dbNamespace,
"para");
1622 if ((curParNr < NumParagraphs) && !paragraphName[curParNr].isEmpty()) {
1623 NodeMultiMap::Iterator it;
1624 NodeMultiMap::Iterator next;
1625 it = paragraph[curParNr].begin();
1626 for (
int j = 0; j < curParOffset; j++)
1631 QStringList pieces{it.value()->fullName(relative).split(
"::"_L1)};
1632 const auto &name{pieces.last()};
1635 if (nameOccurrences[name] > 1) {
1636 const QString moduleName = it.value()->isQmlNode() ? it.value()->logicalModuleName()
1637 : it.value()->tree()->camelCaseModuleName();
1638 pieces.last().append(
": %1"_L1.arg(moduleName));
1642 m_writer->writeStartElement(dbNamespace,
"link");
1643 m_writer->writeAttribute(xlinkNamespace,
"href", linkForNode(*it, relative));
1644 if (
const QString type = targetType(it.value()); !type.isEmpty())
1645 m_writer->writeAttribute(
"role", type);
1646 m_writer->writeCharacters(pieces.last());
1647 m_writer->writeEndElement();
1650 if (pieces.size() > 1) {
1651 m_writer->writeCharacters(
" (");
1652 generateFullName(it.value()->parent(), relative);
1653 m_writer->writeCharacters(
")");
1657 m_writer->writeEndElement();
1659 m_writer->writeEndElement();
1664 m_writer->writeEndElement();
1666 m_writer->writeEndElement();
1668 m_writer->writeEndElement();
1671 m_writer->writeEndElement();
1680 m_writer->writeStartElement(dbNamespace,
"simplelist");
1681 m_writer->writeAttribute(
"role",
"functionIndex");
1683 for (
int i = 0; i < 26; i++) {
1685 m_writer->writeStartElement(dbNamespace,
"member");
1686 m_writer->writeAttribute(xlinkNamespace,
"href", QString(
"#") + ch);
1687 m_writer->writeCharacters(ch.toUpper());
1688 m_writer->writeEndElement();
1691 m_writer->writeEndElement();
1696 if (m_qdb->getFunctionIndex().isEmpty())
1698 char nextLetter =
'a';
1701 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1704 NodeMapMap &funcIndex = m_qdb->getFunctionIndex();
1705 QMap<QString, NodeMap>::ConstIterator f = funcIndex.constBegin();
1706 while (f != funcIndex.constEnd()) {
1707 m_writer->writeStartElement(dbNamespace,
"listitem");
1709 m_writer->writeStartElement(dbNamespace,
"para");
1710 m_writer->writeCharacters(f.key() +
": ");
1712 currentLetter = f.key()[0].unicode();
1713 while (islower(currentLetter) && currentLetter >= nextLetter) {
1714 writeAnchor(QString(nextLetter));
1718 NodeMap::ConstIterator s = (*f).constBegin();
1719 while (s != (*f).constEnd()) {
1720 m_writer->writeCharacters(
" ");
1721 generateFullName((*s)->parent(), relative);
1725 m_writer->writeEndElement();
1727 m_writer->writeEndElement();
1731 m_writer->writeEndElement();
1739 for (
auto it = legaleseTexts.cbegin(), end = legaleseTexts.cend(); it != end; ++it) {
1740 Text text = it.key();
1742 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
1745 m_writer->writeStartElement(dbNamespace,
"listitem");
1747 m_writer->writeStartElement(dbNamespace,
"para");
1748 generateFullName(it.value(), relative);
1749 m_writer->writeEndElement();
1751 m_writer->writeEndElement();
1754 }
while (it != legaleseTexts.constEnd() && it.key() == text);
1755 m_writer->writeEndElement();
1770 m_writer->writeStartElement(dbNamespace,
"para");
1772 m_writer->writeEndElement();
1779 if (node->since().isEmpty())
1782 const auto *shared = node->isSharedCommentNode()
1783 ?
static_cast<
const SharedCommentNode *>(node) :
nullptr;
1784 const bool plural = shared && shared->collective().size() > 1;
1785 const Node *described = plural ? shared->collective().first() : node;
1789 m_writer->writeStartElement(dbNamespace,
"para");
1790 m_writer->writeCharacters((plural ?
"These "_L1 :
"This "_L1)
1791 + NodeText::nodeTypeDescription(described, number)
1792 + (plural ?
" were introduced in "_L1 :
" was introduced in "_L1)
1793 + formatSince(node) +
"."_L1);
1794 m_writer->writeEndElement();
1800
1801
1802
1808 if (!subTitle.isEmpty()) {
1809 m_writer->writeStartElement(dbNamespace,
"subtitle");
1810 if (isApiGenus(node->genus()) && m_useITS)
1811 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1812 m_writer->writeCharacters(subTitle);
1813 m_writer->writeEndElement();
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1836 m_writer->writeStartElement(dbNamespace,
"info");
1838 m_writer->writeStartElement(dbNamespace,
"title");
1839 if (isApiGenus(node->genus()) && m_useITS)
1840 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
1842 m_writer->writeEndElement();
1847
1848
1849
1850
1851
1854 if (!m_productName.isEmpty() || !m_project.isEmpty()) {
1855 m_writer->writeTextElement(dbNamespace,
"productname", m_productName.isEmpty() ?
1856 m_project : m_productName);
1860 if (!m_buildVersion.isEmpty()) {
1861 m_writer->writeTextElement(dbNamespace,
"edition", m_buildVersion);
1865 if (!m_projectDescription.isEmpty()) {
1866 m_writer->writeTextElement(dbNamespace,
"titleabbrev", m_projectDescription);
1874 if (node && !node->links().empty()) {
1875 std::pair<QString, QString> linkPair;
1876 std::pair<QString, QString> anchorPair;
1877 const Node *linkNode;
1879 if (node->links().contains(Node::PreviousLink)) {
1880 linkPair = node->links()[Node::PreviousLink];
1881 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1882 if (!linkNode || linkNode == node)
1883 anchorPair = linkPair;
1885 anchorPair = anchorForNode(linkNode);
1887 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1888 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1889 m_writer->writeEmptyElement(dbNamespace,
"link");
1890 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1891 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1892 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"prev");
1893 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1894 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1896 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1897 m_writer->writeEndElement();
1900 if (node->links().contains(Node::NextLink)) {
1901 linkPair = node->links()[Node::NextLink];
1902 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1903 if (!linkNode || linkNode == node)
1904 anchorPair = linkPair;
1906 anchorPair = anchorForNode(linkNode);
1908 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1909 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1910 m_writer->writeEmptyElement(dbNamespace,
"link");
1911 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1912 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1913 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"next");
1914 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1915 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1917 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1918 m_writer->writeEndElement();
1921 if (node->links().contains(Node::StartLink)) {
1922 linkPair = node->links()[Node::StartLink];
1923 linkNode = m_qdb->findNodeForTarget(linkPair.first, node);
1924 if (!linkNode || linkNode == node)
1925 anchorPair = linkPair;
1927 anchorPair = anchorForNode(linkNode);
1929 m_writer->writeStartElement(dbNamespace,
"extendedlink");
1930 m_writer->writeAttribute(xlinkNamespace,
"type",
"extended");
1931 m_writer->writeEmptyElement(dbNamespace,
"link");
1932 m_writer->writeAttribute(xlinkNamespace,
"to", anchorPair.first);
1933 m_writer->writeAttribute(xlinkNamespace,
"type",
"arc");
1934 m_writer->writeAttribute(xlinkNamespace,
"arcrole",
"start");
1935 if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
1936 m_writer->writeAttribute(xlinkNamespace,
"title", anchorPair.second);
1938 m_writer->writeAttribute(xlinkNamespace,
"title", linkPair.second);
1939 m_writer->writeEndElement();
1951 m_writer->writeStartElement(dbNamespace,
"abstract");
1954 bool generatedSomething =
false;
1958 node->isNamespace() ?
static_cast<
const NamespaceNode *>(node) :
nullptr;
1961 brief <<
"The " << ns->name()
1962 <<
" namespace includes the following elements from module "
1963 << ns
->tree()->camelCaseModuleName() <<
". The full namespace is "
1964 <<
"documented in module " << NS
->tree()->camelCaseModuleName();
1965 addNodeLink(brief, fullDocumentLocation(NS),
" here.");
1974 m_writer->writeStartElement(dbNamespace,
"para");
1976 m_writer->writeEndElement();
1979 generatedSomething =
true;
1989 if (!generatedSomething)
1990 m_writer->writeTextElement(dbNamespace,
"para", m_projectDescription +
".");
1992 m_writer->writeEndElement();
1997 m_writer->writeEndElement();
2003 while (!sectionLevels.isEmpty()) {
2004 sectionLevels.pop();
2011 if (m_closeSectionAfterGeneratedList) {
2012 m_closeSectionAfterGeneratedList =
false;
2015 if (m_closeSectionAfterRawTitle) {
2016 m_closeSectionAfterRawTitle =
false;
2021 m_writer->writeEndElement();
2024void DocBookGenerator::generateSimpleLink(
const QString &href,
const QString &text)
2026 m_writer->writeStartElement(dbNamespace,
"link");
2027 m_writer->writeAttribute(xlinkNamespace,
"href", href);
2028 m_writer->writeCharacters(text);
2029 m_writer->writeEndElement();
2033
2034
2035
2038 static const QHash<QString, QString> extrefUrls = {
2039 {u"cpp-explicitly-defaulted"_s,
2040 u"https://en.cppreference.com/w/cpp/language/function#Defaulted_functions"_s},
2041 {u"cpp-deleted-functions"_s,
2042 u"https://en.cppreference.com/w/cpp/language/function#Deleted_functions"_s},
2045 static const QRegularExpression extrefRegex(
2046 u"<@extref target=\"([^\"]+)\">([^<]*)</@extref>"_s);
2049 auto it = extrefRegex.globalMatch(extra);
2050 while (it.hasNext()) {
2051 auto match = it.next();
2052 if (match.capturedStart() > pos)
2053 m_writer->writeCharacters(extra.mid(pos, match.capturedStart() - pos));
2055 QString target = match.captured(1);
2056 QString text = match.captured(2);
2057 QString url = extrefUrls.value(target);
2059 generateSimpleLink(url, text);
2061 m_writer->writeCharacters(text);
2063 pos = match.capturedEnd();
2065 if (pos < extra.size())
2066 m_writer->writeCharacters(extra.mid(pos));
2078 startSection(
"obsolete",
"Obsolete Members for " + aggregate->plainFullName());
2080 m_writer->writeStartElement(dbNamespace,
"para");
2081 m_writer->writeStartElement(dbNamespace,
"emphasis");
2082 m_writer->writeAttribute(
"role",
"bold");
2083 m_writer->writeCharacters(
"The following members of class ");
2084 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2085 m_writer->writeCharacters(
" are deprecated.");
2086 m_writer->writeEndElement();
2087 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2088 m_writer->writeEndElement();
2091 for (
const Section *section : details_spv) {
2092 const QString &title =
"Obsolete " + section->title();
2093 startSection(title.toLower(), title);
2095 const NodeVector &members = section->obsoleteMembers();
2096 NodeVector::ConstIterator m = members.constBegin();
2097 while (m != members.constEnd()) {
2098 if ((*m)->access() != Access::Private)
2099 generateDetailedMember(*m, aggregate);
2110
2111
2112
2113
2114
2115
2116
2126 startSection(
"obsolete",
"Obsolete Members for " + aggregate->name());
2128 m_writer->writeStartElement(dbNamespace,
"para");
2129 m_writer->writeStartElement(dbNamespace,
"emphasis");
2130 m_writer->writeAttribute(
"role",
"bold");
2131 m_writer->writeCharacters(
"The following members of QML type ");
2132 generateSimpleLink(linkForNode(aggregate,
nullptr), aggregate->name());
2133 m_writer->writeCharacters(
" are deprecated.");
2134 m_writer->writeEndElement();
2135 m_writer->writeCharacters(
" We strongly advise against using them in new code.");
2136 m_writer->writeEndElement();
2139 for (
const auto *section : details_spv) {
2140 const QString &title =
"Obsolete " + section->title();
2141 startSection(title.toLower(), title);
2143 const NodeVector &members = section->obsoleteMembers();
2144 NodeVector::ConstIterator m = members.constBegin();
2145 while (m != members.constEnd()) {
2146 if ((*m)->access() != Access::Private)
2147 generateDetailedQmlMember(*m, aggregate);
2161 return QStringLiteral(
"classsynopsis");
2163 return QStringLiteral(
"packagesynopsis");
2169 return QStringLiteral(
"enumsynopsis");
2171 return QStringLiteral(
"typedefsynopsis");
2174 const auto fn =
static_cast<
const FunctionNode *>(node);
2175 if (fn->isCtor() || fn->isCCtor() || fn->isMCtor())
2176 return QStringLiteral(
"constructorsynopsis");
2178 return QStringLiteral(
"destructorsynopsis");
2179 return QStringLiteral(
"methodsynopsis");
2182 return QStringLiteral(
"fieldsynopsis");
2184 node
->doc().location().warning(QString(
"Unknown node tag %1").arg(node->nodeTypeString()));
2185 return QStringLiteral(
"synopsis");
2190 m_writer->writeStartElement(dbNamespace,
"varlistentry");
2192 m_writer->writeTextElement(dbNamespace,
"term", description);
2194 m_writer->writeStartElement(dbNamespace,
"listitem");
2196 m_writer->writeStartElement(dbNamespace,
"para");
2202 m_writer->writeEndElement();
2205 m_writer->writeEndElement();
2207 m_writer->writeEndElement();
2211void DocBookGenerator::generateRequisite(
const QString &description,
const QString &value)
2213 generateStartRequisite(description);
2214 m_writer->writeCharacters(value);
2215 generateEndRequisite();
2219
2220
2221
2222void DocBookGenerator::generateCMakeRequisite(
const QString &findPackage,
const QString &linkLibraries)
2224 const QString description(
"CMake");
2225 generateStartRequisite(description);
2226 m_writer->writeCharacters(findPackage);
2227 m_writer->writeEndElement();
2230 m_writer->writeStartElement(dbNamespace,
"para");
2231 m_writer->writeCharacters(linkLibraries);
2232 generateEndRequisite();
2238 QMap<QString, ClassNode *> classMap;
2239 QList<RelatedClass>::ConstIterator r = rc.constBegin();
2240 while (r != rc.constEnd()) {
2243 && !rcn
->doc().isEmpty()) {
2244 classMap[rcn->plainFullName(cn).toLower()] = rcn;
2249 QStringList classNames = classMap.keys();
2253 for (
const QString &className : classNames) {
2254 generateFullName(classMap.value(className), cn);
2255 m_writer->writeCharacters(TextUtils::comma(index++, classNames.size()));
2263 QMap<QString, Node *> classMap;
2264 QStringList typeNames(knownTypes);
2265 for (
const auto sub : subs)
2266 typeNames << sub->name();
2268 for (
auto sub : subs) {
2269 QString key{sub->plainFullName(base).toLower()};
2271 if (typeNames.count(sub->name()) > 1)
2272 key.append(
": (%1)"_L1.arg(sub->logicalModuleName()));
2273 classMap[key] = sub;
2276 QStringList names = classMap.keys();
2280 for (
const QString &name : names) {
2281 generateFullName(classMap.value(name), base);
2282 if (name.contains(
':'))
2283 m_writer->writeCharacters(name.section(
':', 1));
2284 m_writer->writeCharacters(TextUtils::comma(index++, names.size()));
2289
2290
2299 QXmlStreamWriter* oldWriter = m_writer;
2301 m_writer =
new QXmlStreamWriter(&output);
2304 if (aggregate->includeFile()) generateRequisite(
"Header", *aggregate->includeFile());
2307 if (!aggregate->since().isEmpty())
2308 generateRequisite(
"Since", formatSince(aggregate));
2313 m_qdb->getCollectionNode(aggregate->physicalModuleName(), NodeType::Module);
2315 if (
const auto result = cmakeRequisite(cn)) {
2316 generateCMakeRequisite(result->first, result->second);
2319 if (cn && !cn->qtVariable().isEmpty())
2320 generateRequisite(
"qmake",
"QT += " + cn->qtVariable());
2325 auto *classe =
const_cast<ClassNode *>(
static_cast<
const ClassNode *>(aggregate));
2326 if (classe && classe->isQmlNativeType() && !classe->isInternal()) {
2327 generateStartRequisite(
"In QML");
2330 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
2333 for (
const auto &item : std::as_const(nativeTypes)) {
2334 generateFullName(item, classe);
2335 m_writer->writeCharacters(
2336 TextUtils::comma(idx++, nativeTypes.size()));
2338 generateEndRequisite();
2342 QList<RelatedClass>::ConstIterator r;
2343 const auto *metaTags = classe ? classe->doc().metaTagMap() :
nullptr;
2344 bool suppressInherits = metaTags && metaTags->contains(u"qdoc-suppress-inheritance"_s);
2345 if (classe && !suppressInherits && !classe->baseClasses().isEmpty()) {
2346 generateStartRequisite(
"Inherits");
2348 r = classe->baseClasses().constBegin();
2350 while (r != classe->baseClasses().constEnd()) {
2352 generateFullName((*r).m_node, classe);
2354 if ((*r).m_access == Access::Protected)
2355 m_writer->writeCharacters(
" (protected)");
2356 else if ((*r).m_access == Access::Private)
2357 m_writer->writeCharacters(
" (private)");
2358 m_writer->writeCharacters(
2359 TextUtils::comma(index++, classe->baseClasses().size()));
2364 generateEndRequisite();
2368 if (!classe->derivedClasses().isEmpty()) {
2369 generateStartRequisite(
"Inherited By");
2370 generateSortedNames(classe, classe->derivedClasses());
2371 generateEndRequisite();
2376 if (!aggregate->groupNames().empty()) {
2377 generateStartRequisite(
"Group");
2379 generateEndRequisite();
2383 if (
auto status = formatStatus(aggregate, m_qdb); status)
2384 generateRequisite(
"Status", status.value());
2388 m_writer = oldWriter;
2390 if (!output.isEmpty()) {
2393 static const QRegularExpression xmlTag(R"(<(/?)n\d+:)");
2394 static const QRegularExpression xmlnsDocBookDefinition(R"( xmlns:n\d+=")" + QString{dbNamespace} +
"\"");
2395 static const QRegularExpression xmlnsXLinkDefinition(R"( xmlns:n\d+=")" + QString{xlinkNamespace} +
"\"");
2396 static const QRegularExpression xmlAttr(R"( n\d+:)");
2398 const QString cleanOutput = output.replace(xmlTag, R"(<\1db:)")
2399 .replace(xmlnsDocBookDefinition,
"")
2400 .replace(xmlnsXLinkDefinition,
"")
2401 .replace(xmlAttr,
" xlink:");
2403 m_writer->writeStartElement(dbNamespace,
"variablelist");
2405 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2408 m_writer->device()->write(cleanOutput.toUtf8());
2410 m_writer->writeEndElement();
2416
2417
2425 const QString importText =
"Import Statement";
2426 const QString sinceText =
"Since";
2427 const QString inheritedByText =
"Inherited By";
2428 const QString inheritsText =
"Inherits";
2429 const QString nativeTypeText =
"In C++";
2430 const QString groupText =
"Group";
2431 const QString statusText =
"Status";
2439 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
2448 bool generate_import_statement = !qcn->logicalModuleName().isEmpty();
2449 if (generate_import_statement && collection) {
2454 const bool generates_something = generate_import_statement || !qcn->since().isEmpty() || !subs.isEmpty() || base;
2456 if (!generates_something)
2459 QStringList knownTypeNames{qcn->name()};
2461 knownTypeNames << base->name();
2464 m_writer->writeStartElement(dbNamespace,
"variablelist");
2466 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
2469 if (generate_import_statement) {
2470 QStringList parts = QStringList() <<
"import" << qcn->logicalModuleName() << qcn->logicalModuleVersion();
2471 generateRequisite(importText, parts.join(
' ').trimmed());
2475 if (!qcn->since().isEmpty())
2476 generateRequisite(sinceText, formatSince(qcn));
2481 generateStartRequisite(nativeTypeText);
2482 generateSimpleLink(fullDocumentLocation(cn), cn->name());
2483 generateEndRequisite();
2488 generateStartRequisite(inheritsText);
2489 generateSimpleLink(fullDocumentLocation(base), base->name());
2491 for (
const auto sub : std::as_const(subs)) {
2492 if (knownTypeNames.contains(sub->name())) {
2493 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
2497 generateEndRequisite();
2501 if (!subs.isEmpty()) {
2502 generateStartRequisite(inheritedByText);
2503 generateSortedQmlNames(qcn, knownTypeNames, subs);
2504 generateEndRequisite();
2508 if (!qcn->groupNames().empty()) {
2509 generateStartRequisite(groupText);
2511 generateEndRequisite();
2515 if (
auto status = formatStatus(qcn, m_qdb); status)
2516 generateRequisite(statusText, status.value());
2518 m_writer->writeEndElement();
2525 const auto *shared = node->isSharedCommentNode()
2526 ?
static_cast<
const SharedCommentNode *>(node) :
nullptr;
2527 const bool plural = shared && !shared->isPropertyGroup() && shared->collective().size() > 1;
2528 const QString subject = plural
2529 ?
"These "_L1 + NodeText::nodeTypeDescription(shared->collective().first(), NodeText::GrammaticalNumber::Plural) +
" are"_L1
2530 :
"This "_L1 + NodeText::nodeTypeDescription(node) +
" is"_L1;
2536 const QString &state =
static_cast<
const CollectionNode*>(node)->state();
2537 if (!state.isEmpty()) {
2538 m_writer->writeStartElement(dbNamespace,
"para");
2539 m_writer->writeCharacters(
"This " + NodeText::nodeTypeDescription(node) +
" is in ");
2540 m_writer->writeStartElement(dbNamespace,
"emphasis");
2541 m_writer->writeCharacters(state);
2542 m_writer->writeEndElement();
2543 m_writer->writeCharacters(
" state.");
2544 m_writer->writeEndElement();
2549 if (
const auto &version = node->deprecatedSince(); !version.isEmpty()) {
2550 m_writer->writeStartElement(dbNamespace,
"para");
2551 m_writer->writeCharacters(subject
2552 +
" scheduled for deprecation in version "
2554 m_writer->writeEndElement();
2559 case Status::Preliminary:
2560 m_writer->writeStartElement(dbNamespace,
"para");
2561 m_writer->writeStartElement(dbNamespace,
"emphasis");
2562 m_writer->writeAttribute(
"role",
"bold");
2563 m_writer->writeCharacters(
2567 .replace(
'\1'_L1, NodeText::nodeTypeDescription(node)));
2568 m_writer->writeEndElement();
2569 m_writer->writeEndElement();
2572 case Status::Deprecated:
2573 m_writer->writeStartElement(dbNamespace,
"para");
2575 m_writer->writeStartElement(dbNamespace,
"emphasis");
2576 m_writer->writeAttribute(
"role",
"bold");
2578 m_writer->writeCharacters(subject +
" deprecated");
2579 if (
const QString &version = node->deprecatedSince(); !version.isEmpty()) {
2580 m_writer->writeCharacters(
" since ");
2581 if (node->isQmlNode() && !node->logicalModuleName().isEmpty())
2582 m_writer->writeCharacters(node->logicalModuleName() +
" ");
2583 m_writer->writeCharacters(version);
2585 m_writer->writeCharacters(
". We strongly advise against using "
2586 + (plural ?
"them"_L1 :
"it"_L1) +
" in new code.");
2587 if (node->isAggregate())
2588 m_writer->writeEndElement();
2589 m_writer->writeEndElement();
2600
2601
2602
2606 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2609 NodeList::ConstIterator n = nodes.constBegin();
2610 while (n != nodes.constEnd()) {
2611 m_writer->writeStartElement(dbNamespace,
"listitem");
2613 m_writer->writeStartElement(dbNamespace,
"para");
2615 generateSimpleLink(currentGenerator()->fullDocumentLocation(*n),
2616 (*n)->signature(Node::SignaturePlain));
2618 m_writer->writeEndElement();
2620 m_writer->writeEndElement();
2625 m_writer->writeEndElement();
2630
2631
2632
2639 const auto aggregate =
static_cast<
const Aggregate *>(node);
2641 const QStringList &groups_names{aggregate->groupNames()};
2642 if (!groups_names.empty()) {
2643 m_writer->writeCharacters(aggregate->name() +
" is part of ");
2644 m_writer->writeStartElement(dbNamespace,
"simplelist");
2646 for (qsizetype index{0}; index < groups_names.size(); ++index) {
2648 m_qdb->mergeCollections(group);
2650 m_writer->writeStartElement(dbNamespace,
"member");
2651 if (QString target{linkForNode(group,
nullptr)}; !target.isEmpty())
2652 generateSimpleLink(target, group->fullTitle());
2654 m_writer->writeCharacters(group->name());
2655 m_writer->writeEndElement();
2658 m_writer->writeEndElement();
2664
2665
2666
2672 const Node *reentrantNode;
2674 QString linkReentrant = getAutoLink(&reentrantAtom, node, &reentrantNode);
2675 const Node *threadSafeNode;
2677 QString linkThreadSafe = getAutoLink(&threadSafeAtom, node, &threadSafeNode);
2680 m_writer->writeStartElement(dbNamespace,
"warning");
2682 m_writer->writeStartElement(dbNamespace,
"para");
2683 m_writer->writeCharacters(
"This " + NodeText::nodeTypeDescription(node) +
" is not ");
2684 generateSimpleLink(linkReentrant,
"reentrant");
2685 m_writer->writeCharacters(
".");
2686 m_writer->writeEndElement();
2688 m_writer->writeEndElement();
2692 m_writer->writeStartElement(dbNamespace,
"note");
2694 m_writer->writeStartElement(dbNamespace,
"para");
2697 m_writer->writeCharacters(
"All functions in this " + NodeText::nodeTypeDescription(node) +
" are ");
2698 if (ts == Node::ThreadSafe)
2699 generateSimpleLink(linkThreadSafe,
"thread-safe");
2701 generateSimpleLink(linkReentrant,
"reentrant");
2706 bool exceptions = hasExceptions(node, reentrant, threadsafe, nonreentrant);
2707 if (!exceptions || (ts ==
Node::Reentrant && !threadsafe.isEmpty())) {
2708 m_writer->writeCharacters(
".");
2709 m_writer->writeEndElement();
2712 m_writer->writeCharacters(
" with the following exceptions:");
2713 m_writer->writeEndElement();
2715 m_writer->writeStartElement(dbNamespace,
"para");
2718 if (!nonreentrant.isEmpty()) {
2719 m_writer->writeCharacters(
"These functions are not ");
2720 generateSimpleLink(linkReentrant,
"reentrant");
2721 m_writer->writeCharacters(
":");
2722 m_writer->writeEndElement();
2724 generateSignatureList(nonreentrant);
2726 if (!threadsafe.isEmpty()) {
2727 m_writer->writeCharacters(
"These functions are also ");
2728 generateSimpleLink(linkThreadSafe,
"thread-safe");
2729 m_writer->writeCharacters(
":");
2730 m_writer->writeEndElement();
2732 generateSignatureList(threadsafe);
2735 if (!reentrant.isEmpty()) {
2736 m_writer->writeCharacters(
"These functions are only ");
2737 generateSimpleLink(linkReentrant,
"reentrant");
2738 m_writer->writeCharacters(
":");
2739 m_writer->writeEndElement();
2741 generateSignatureList(reentrant);
2743 if (!nonreentrant.isEmpty()) {
2744 m_writer->writeCharacters(
"These functions are not ");
2745 generateSimpleLink(linkReentrant,
"reentrant");
2746 m_writer->writeCharacters(
":");
2747 m_writer->writeEndElement();
2749 generateSignatureList(nonreentrant);
2754 m_writer->writeCharacters(
"This " + NodeText::nodeTypeDescription(node) +
" is ");
2755 if (ts == Node::ThreadSafe)
2756 generateSimpleLink(linkThreadSafe,
"thread-safe");
2758 generateSimpleLink(linkReentrant,
"reentrant");
2759 m_writer->writeCharacters(
".");
2760 m_writer->writeEndElement();
2763 m_writer->writeEndElement();
2773
2774
2775
2779 const FunctionNode *fn = node->isFunction() ?
static_cast<
const FunctionNode *>(node) :
nullptr;
2783
2784
2785
2789 t =
"Destroys the instance of " + fn
->parent()->name() +
".";
2791 t +=
" The destructor is virtual.";
2793 t =
"Default constructs an instance of " + fn
->parent()->name() +
".";
2795 t =
"Copy constructor.";
2797 t =
"Move-copy constructor.";
2799 t =
"Copy-assignment constructor.";
2801 t =
"Move-assignment constructor.";
2805 m_writer->writeTextElement(dbNamespace,
"para", t);
2809 if (fn && !fn->overridesThis().isEmpty())
2810 generateReimplementsClause(fn);
2812 if (
static_cast<
const PropertyNode *>(node)->propertyType() != PropertyNode::PropertyType::StandardProperty)
2841 generateRequiredLinks(node);
2845
2846
2847
2848
2849
2856 const auto en =
static_cast<
const ExampleNode *>(node);
2859 if (exampleUrl.isEmpty()) {
2860 if (!en->noAutoList()) {
2861 generateFileList(en,
false);
2862 generateFileList(en,
true);
2865 generateLinkToExample(en, exampleUrl);
2870
2871
2872
2873
2874
2878 QString exampleUrl(baseUrl);
2880#ifndef QT_BOOTSTRAPPED
2881 link = QUrl(exampleUrl).host();
2883 if (!link.isEmpty())
2884 link.prepend(
" @ ");
2885 link.prepend(
"Example project");
2887 const QLatin1Char separator(
'/');
2888 const QLatin1Char placeholder(
'\1');
2889 if (!exampleUrl.contains(placeholder)) {
2890 if (!exampleUrl.endsWith(separator))
2891 exampleUrl += separator;
2892 exampleUrl += placeholder;
2896 QStringList path = QStringList()
2898 path.removeAll(QString());
2902 startSection(
"Example project");
2904 m_writer->writeStartElement(dbNamespace,
"para");
2905 generateSimpleLink(exampleUrl.replace(placeholder, path.join(separator)), link);
2906 m_writer->writeEndElement();
2915
2916
2917
2918
2919
2920
2936 paths = en->images();
2939 paths = en->files();
2942 std::sort(paths.begin(), paths.end(), Generator::comparePaths);
2944 if (paths.isEmpty())
2947 startSection(
"",
"List of Files");
2949 m_writer->writeStartElement(dbNamespace,
"para");
2950 m_writer->writeCharacters(tag);
2951 m_writer->writeEndElement();
2954 startSection(
"List of Files");
2956 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
2959 for (
const auto &path : std::as_const(paths)) {
2960 auto maybe_resolved_file{file_resolver.resolve(path)};
2961 if (!maybe_resolved_file) {
2963 QString details = std::transform_reduce(
2964 file_resolver.get_search_directories().cbegin(),
2965 file_resolver.get_search_directories().cend(),
2966 u"Searched directories:"_s,
2968 [](
const DirectoryPath &directory_path) -> QString {
return u' ' + directory_path.value(); }
2971 en->location().warning(u"Cannot find file to quote from: %1"_s.arg(path), details);
2976 const auto &file{*maybe_resolved_file};
2977 if (images) addImageToCopy(en, file);
2978 else generateExampleFilePage(en, file);
2980 m_writer->writeStartElement(dbNamespace,
"listitem");
2982 m_writer->writeStartElement(dbNamespace,
"para");
2983 generateSimpleLink(file.get_query(), file.get_query());
2984 m_writer->writeEndElement();
2985 m_writer->writeEndElement();
2989 m_writer->writeEndElement();
2996
2997
3007 const auto en =
static_cast<
const ExampleNode *>(node);
3010 QXmlStreamWriter *currentWriter = m_writer;
3011 m_writer = startDocument(en, resolved_file.get_query());
3017 QString code = quoter.quoteTo(en->location(), QString(), QString());
3018 CodeMarker *codeMarker = CodeMarker::markerForFileName(resolved_file.get_path());
3024 m_writer = currentWriter;
3030 if (fn->overridesThis().isEmpty() || !fn
->parent()->isClassNode())
3035 if (
const FunctionNode *overrides = cn->findOverriddenFunction(fn);
3038 m_writer->writeStartElement(dbNamespace,
"para");
3039 m_writer->writeCharacters(
"Reimplements: ");
3042 generateFullName(overrides
->parent(), fullName, overrides);
3043 m_writer->writeCharacters(
".");
3044 m_writer->writeEndElement();
3050 if (
const PropertyNode *sameName = cn->findOverriddenProperty(fn); sameName && sameName
->hasDoc()) {
3051 m_writer->writeStartElement(dbNamespace,
"para");
3052 m_writer->writeCharacters(
"Reimplements an access function for property: ");
3053 QString fullName = sameName
->parent()->name() +
"::" + sameName->name();
3054 generateFullName(sameName
->parent(), fullName, sameName);
3055 m_writer->writeCharacters(
".");
3056 m_writer->writeEndElement();
3065 QList<Text> alsoList = node
->doc().alsoList();
3066 supplementAlsoList(node, alsoList);
3068 if (!alsoList.isEmpty()) {
3069 startSection(
"See Also");
3071 m_writer->writeStartElement(dbNamespace,
"para");
3072 m_writer->writeStartElement(dbNamespace,
"emphasis");
3073 m_writer->writeCharacters(
"See also ");
3074 m_writer->writeEndElement();
3077 m_writer->writeStartElement(dbNamespace,
"simplelist");
3078 m_writer->writeAttribute(
"type",
"vert");
3079 m_writer->writeAttribute(
"role",
"see-also");
3082 for (
const Text &text : alsoList) {
3083 m_writer->writeStartElement(dbNamespace,
"member");
3084 generateText(text, node);
3085 m_writer->writeEndElement();
3089 m_writer->writeEndElement();
3092 m_writer->writeEndElement();
3100
3101
3102
3103QXmlStreamWriter *
DocBookGenerator::startGenericDocument(
const Node *node,
const QString &fileName)
3106 QFile *outFile = openSubPageFile(
static_cast<
const PageNode*>(node), fileName);
3107 m_writer =
new QXmlStreamWriter(outFile);
3108 m_writer->setAutoFormatting(
false);
3110 m_writer->writeStartDocument();
3112 m_writer->writeNamespace(dbNamespace,
"db");
3113 m_writer->writeNamespace(xlinkNamespace,
"xlink");
3115 m_writer->writeNamespace(itsNamespace,
"its");
3116 m_writer->writeStartElement(dbNamespace,
"article");
3117 m_writer->writeAttribute(
"version",
"5.2");
3118 if (!m_naturalLanguage.isEmpty())
3119 m_writer->writeAttribute(
"xml:lang", m_naturalLanguage);
3123 sectionLevels.resize(0);
3132 m_hasSection =
false;
3135 QString fileName = Generator::fileName(node, fileExtension());
3136 return startGenericDocument(node, fileName);
3141 m_hasSection =
false;
3143 QString fileName = linkForExampleFile(file);
3144 return startGenericDocument(en, fileName);
3149 m_writer->writeEndElement();
3150 m_writer->writeEndDocument();
3152 m_writer->device()->close();
3153 delete m_writer->device();
3159
3160
3161
3166 const auto aggregate =
static_cast<
const Aggregate *>(node);
3170 const QString typeWord{aggregate->typeWord(
true)};
3171 if (aggregate->isNamespace()) {
3172 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3173 }
else if (aggregate->isClass()) {
3174 title =
"%1 %2"_L1.arg(aggregate->plainFullName(), typeWord);
3175 }
else if (aggregate->isHeader()) {
3176 title = aggregate->fullTitle();
3177 if (!aggregate->doc().title().isEmpty())
3178 titleText << aggregate->name() <<
" - "_L1 << aggregate->doc().title();
3182 m_writer = startDocument(node);
3188 if (aggregate->isClass()) {
3189 if (
auto templateDecl = node->templateDecl()) {
3195 m_writer->writeStartElement(dbNamespace,
"subtitle");
3196 if (isApiGenus(aggregate->genus()) && m_useITS)
3197 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
3198 generateTemplateDecl(&*templateDecl, aggregate);
3199 m_writer->writeCharacters(
" "_L1 + aggregate->typeWord(
false) +
" "_L1
3200 + aggregate->plainFullName());
3201 m_writer->writeEndElement();
3225 if (!aggregate->doc().isEmpty()) {
3226 startSection(
"details",
"Detailed Description");
3228 generateBody(aggregate);
3236 for (
const Section §ion : sectionVector) {
3237 if (section.members().isEmpty())
3240 startSection(section.title().toLower(), section.title());
3242 for (
const Node *member : section.members()) {
3243 if (member->nodeType() != NodeType::Class) {
3245 generateDetailedMember(member, aggregate);
3247 startSectionBegin();
3248 m_writer->writeCharacters(
"class ");
3249 generateFullName(member, aggregate);
3252 generateBrief(member);
3261 generateObsoleteMembers(sections);
3266void DocBookGenerator::generateSynopsisInfo(
const QString &key,
const QString &value)
3268 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3269 m_writer->writeAttribute(
"role", key);
3270 m_writer->writeCharacters(value);
3271 m_writer->writeEndElement();
3277 m_writer->writeTextElement(dbNamespace,
"modifier", value);
3282
3283
3293 if (!m_useDocBook52)
3303 node->isAggregate() ?
static_cast<
const Aggregate *>(node) :
nullptr;
3304 const ClassNode *classNode = node->isClass() ?
static_cast<
const ClassNode *>(node) :
nullptr;
3306 node->isFunction() ?
static_cast<
const FunctionNode *>(node) :
nullptr;
3308 node->isProperty() ?
static_cast<
const PropertyNode *>(node) :
nullptr;
3310 node->isVariable() ?
static_cast<
const VariableNode *>(node) :
nullptr;
3311 const EnumNode *enumNode = node->isEnumType() ?
static_cast<
const EnumNode *>(node) :
nullptr;
3313 node->isQmlProperty() ?
static_cast<
const QmlPropertyNode *>(node) :
nullptr;
3314 const QmlTypeNode *qcn = node->isQmlType() ?
static_cast<
const QmlTypeNode *>(node) :
nullptr;
3320 QString synopsisTag = nodeToSynopsisTag(node);
3321 m_writer->writeStartElement(dbNamespace, synopsisTag);
3326 m_writer->writeStartElement(dbNamespace,
"ooclass");
3327 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3328 m_writer->writeEndElement();
3331 m_writer->writeTextElement(dbNamespace,
"namespacename", node->plainName());
3334 m_writer->writeStartElement(dbNamespace,
"ooclass");
3335 m_writer->writeTextElement(dbNamespace,
"classname", node->plainName());
3336 m_writer->writeEndElement();
3338 if (!qcn->groupNames().isEmpty())
3339 m_writer->writeAttribute(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3341 m_writer->writeTextElement(dbNamespace,
"modifier",
"(Qt property)");
3343 m_writer->writeTextElement(dbNamespace,
"type", propertyNode->dataType());
3345 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3349 m_writer->writeTextElement(dbNamespace,
"modifier",
"static");
3352 m_writer->writeTextElement(dbNamespace,
"type", variableNode->dataType());
3354 m_writer->writeTextElement(dbNamespace,
"varname", node->plainName());
3358 m_writer->writeTextElement(dbNamespace,
"enumname", node->plainName());
3362 QString name = node->name();
3364 name.prepend(qpn->element() + QLatin1Char(
'.'));
3366 m_writer->writeTextElement(dbNamespace,
"type", qpn->dataType());
3368 m_writer->writeTextElement(dbNamespace,
"varname", name);
3376 m_writer->writeTextElement(dbNamespace,
"modifier",
"attached");
3380 m_writer->writeTextElement(dbNamespace,
"modifier",
"writable");
3384 m_writer->writeTextElement(dbNamespace,
"modifier",
"required");
3389 generateModifier(
"[read-only]");
3393 generateModifier(
"[default]");
3397 if (functionNode->virtualness() !=
"non")
3398 generateModifier(
"virtual");
3399 if (functionNode->isConst())
3400 generateModifier(
"const");
3401 if (functionNode->isStatic())
3402 generateModifier(
"static");
3407 if (functionNode->returnType() ==
"void")
3408 m_writer->writeEmptyElement(dbNamespace,
"void");
3410 m_writer->writeTextElement(dbNamespace,
"type", functionNode->returnTypeString());
3415 QString name = node->plainName();
3416 if (name.endsWith(
"()"))
3418 m_writer->writeTextElement(dbNamespace,
"methodname", name);
3422 m_writer->writeEmptyElement(dbNamespace,
"void");
3427 for (
int i = 0; i < lp
.count(); ++i) {
3429 m_writer->writeStartElement(dbNamespace,
"methodparam");
3431 m_writer->writeTextElement(dbNamespace,
"type", parameter.type());
3433 m_writer->writeTextElement(dbNamespace,
"parameter", parameter.name());
3435 if (!parameter.defaultValue().isEmpty()) {
3436 m_writer->writeTextElement(dbNamespace,
"initializer", parameter.defaultValue());
3439 m_writer->writeEndElement();
3443 if (functionNode->isImplicitlyGenerated())
3444 generateModifier(
"implicit");
3445 else if (functionNode->isExplicitlyDefaulted())
3446 generateModifier(
"default");
3447 else if (functionNode->isDeletedAsWritten())
3448 generateModifier(
"delete");
3449 if (functionNode->isFinal())
3450 generateModifier(
"final");
3451 if (functionNode->isOverride())
3452 generateModifier(
"override");
3454 m_writer->writeTextElement(dbNamespace,
"typedefname", node->plainName());
3458 QStringLiteral(
"Unexpected node type in generateDocBookSynopsis: %1")
3459 .arg(node->nodeTypeString()));
3465 for (
const EnumItem &item : enumNode->items()) {
3466 m_writer->writeStartElement(dbNamespace,
"enumitem");
3468 m_writer->writeTextElement(dbNamespace,
"enumidentifier", item.name());
3470 m_writer->writeTextElement(dbNamespace,
"enumvalue", item.value());
3472 m_writer->writeEndElement();
3476 if (enumNode->items().isEmpty()) {
3479 m_writer->writeStartElement(dbNamespace,
"enumitem");
3481 m_writer->writeEmptyElement(dbNamespace,
"enumidentifier");
3483 m_writer->writeEndElement();
3494 generateSynopsisInfo(
"meta", functionNode->metanessString());
3497 generateSynopsisInfo(
"overload",
"overload");
3498 generateSynopsisInfo(
"overload-number",
3499 QString::number(functionNode->overloadNumber()));
3502 if (functionNode->isRef())
3503 generateSynopsisInfo(
"refness", QString::number(1));
3504 else if (functionNode->isRefRef())
3505 generateSynopsisInfo(
"refness", QString::number(2));
3508 QStringList associatedProperties;
3509 const auto &nodes = functionNode->associatedProperties();
3510 for (
const Node *n : nodes) {
3511 const auto pn =
static_cast<
const PropertyNode *>(n);
3512 associatedProperties << pn->name();
3514 associatedProperties.sort();
3515 generateSynopsisInfo(
"associated-property",
3516 associatedProperties.join(QLatin1Char(
',')));
3522 signature +=
" final";
3524 signature +=
" override";
3526 signature +=
" = 0";
3528 signature +=
" = default";
3530 signature +=
" = delete";
3531 if (
const auto &req = functionNode->trailingRequiresClause(); req && !req->isEmpty())
3532 signature +=
" requires " + *req;
3533 generateSynopsisInfo(
"signature", signature);
3539 case Access::Public:
3540 generateSynopsisInfo(
"access",
"public");
3542 case Access::Protected:
3543 generateSynopsisInfo(
"access",
"protected");
3545 case Access::Private:
3546 generateSynopsisInfo(
"access",
"private");
3551 if (node->isAbstract())
3552 generateSynopsisInfo(
"abstract",
"true");
3557 case Status::Active:
3558 generateSynopsisInfo(
"status",
"active");
3560 case Status::Preliminary:
3561 generateSynopsisInfo(
"status",
3564 case Status::Deprecated:
3565 generateSynopsisInfo(
"status",
"deprecated");
3567 case Status::Internal:
3568 case Status::InternalAuto:
3569 generateSynopsisInfo(
"status",
"internal");
3572 generateSynopsisInfo(
"status",
"main");
3579 if (aggregate->includeFile()) generateSynopsisInfo(
"headers", *aggregate->includeFile());
3582 if (!aggregate->since().isEmpty())
3583 generateSynopsisInfo(
"since", formatSince(aggregate));
3587 if (!aggregate->physicalModuleName().isEmpty()) {
3589 m_qdb->getCollectionNode(aggregate->physicalModuleName(), NodeType::Module);
3591 if (
const auto result = cmakeRequisite(cn)) {
3592 generateSynopsisInfo(
"cmake-find-package", result->first);
3593 generateSynopsisInfo(
"cmake-target-link-libraries", result->second);
3596 if (cn && !cn->qtVariable().isEmpty())
3597 generateSynopsisInfo(
"qmake",
"QT += " + cn->qtVariable());
3603 auto *classe =
const_cast<ClassNode *>(
static_cast<
const ClassNode *>(aggregate));
3604 if (classe && classe->isQmlNativeType() && !classe->isInternal()) {
3605 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3606 m_writer->writeAttribute(
"role",
"nativeTypeFor");
3608 QList<QmlTypeNode *> nativeTypes { classe->qmlNativeTypes().cbegin(), classe->qmlNativeTypes().cend()};
3611 for (
auto item : std::as_const(nativeTypes)) {
3612 const Node *otherNode{
nullptr};
3613 Atom a = Atom(Atom::LinkNode, Utilities::stringForNode(item));
3614 const QString &link = getAutoLink(&a, aggregate, &otherNode);
3615 generateSimpleLink(link, item->name());
3618 m_writer->writeEndElement();
3622 QList<RelatedClass>::ConstIterator r;
3623 if (!classe->baseClasses().isEmpty()) {
3624 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3625 m_writer->writeAttribute(
"role",
"inherits");
3627 r = classe->baseClasses().constBegin();
3629 while (r != classe->baseClasses().constEnd()) {
3631 generateFullName((*r).m_node, classe);
3633 if ((*r).m_access == Access::Protected) {
3634 m_writer->writeCharacters(
" (protected)");
3635 }
else if ((*r).m_access == Access::Private) {
3636 m_writer->writeCharacters(
" (private)");
3638 m_writer->writeCharacters(
3639 TextUtils::comma(index++, classe->baseClasses().size()));
3644 m_writer->writeEndElement();
3649 if (!classe->derivedClasses().isEmpty()) {
3650 m_writer->writeStartElement(dbNamespace,
"synopsisinfo");
3651 m_writer->writeAttribute(
"role",
"inheritedBy");
3652 generateSortedNames(classe, classe->derivedClasses());
3653 m_writer->writeEndElement();
3662 QString logicalModuleVersion;
3664 m_qdb->getCollectionNode(qcn->logicalModuleName(), qcn->nodeType());
3666 logicalModuleVersion = collection->logicalModuleVersion();
3668 logicalModuleVersion = qcn->logicalModuleVersion();
3670 QStringList importText;
3671 importText <<
"import " + qcn->logicalModuleName();
3672 if (!logicalModuleVersion.isEmpty())
3673 importText << logicalModuleVersion;
3674 generateSynopsisInfo(
"import", importText.join(
' '));
3677 if (!qcn->since().isEmpty())
3678 generateSynopsisInfo(
"since", formatSince(qcn));
3681 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
3689 QStringList knownTypeNames{qcn->name()};
3691 knownTypeNames << base->name();
3696 if (!subs.isEmpty()) {
3697 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3698 m_writer->writeAttribute(
"role",
"inheritedBy");
3699 generateSortedQmlNames(qcn, knownTypeNames, subs);
3700 m_writer->writeEndElement();
3706 const Node *otherNode =
nullptr;
3708 QString link = getAutoLink(&a, base, &otherNode);
3710 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3711 m_writer->writeAttribute(
"role",
"inherits");
3712 generateSimpleLink(link, base->name());
3714 for (
const auto sub : std::as_const(subs)) {
3715 if (knownTypeNames.contains(sub->name())) {
3716 m_writer->writeCharacters(
" (%1)"_L1.arg(base->logicalModuleName()));
3720 m_writer->writeEndElement();
3728 const Node *otherNode =
nullptr;
3730 QString link = getAutoLink(&a, cn, &otherNode);
3732 m_writer->writeTextElement(dbNamespace,
"synopsisinfo");
3733 m_writer->writeAttribute(
"role",
"nativeType");
3734 generateSimpleLink(link, cn->name());
3735 m_writer->writeEndElement();
3742 case Node::UnspecifiedSafeness:
3743 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3745 case Node::NonReentrant:
3746 generateSynopsisInfo(
"threadsafeness",
"non-reentrant");
3748 case Node::Reentrant:
3749 generateSynopsisInfo(
"threadsafeness",
"reentrant");
3751 case Node::ThreadSafe:
3752 generateSynopsisInfo(
"threadsafeness",
"thread safe");
3755 generateSynopsisInfo(
"threadsafeness",
"unspecified");
3760 if (!node->physicalModuleName().isEmpty())
3761 generateSynopsisInfo(
"module", node->physicalModuleName());
3764 if (classNode && !classNode->groupNames().isEmpty()) {
3765 generateSynopsisInfo(
"groups", classNode->groupNames().join(QLatin1Char(
',')));
3766 }
else if (qcn && !qcn->groupNames().isEmpty()) {
3767 generateSynopsisInfo(
"groups", qcn->groupNames().join(QLatin1Char(
',')));
3772 for (
const Node *fnNode : propertyNode->getters()) {
3774 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3775 generateSynopsisInfo(
"getter", funcNode->name());
3778 for (
const Node *fnNode : propertyNode->setters()) {
3780 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3781 generateSynopsisInfo(
"setter", funcNode->name());
3784 for (
const Node *fnNode : propertyNode->resetters()) {
3786 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3787 generateSynopsisInfo(
"resetter", funcNode->name());
3790 for (
const Node *fnNode : propertyNode->notifiers()) {
3792 const auto funcNode =
static_cast<
const FunctionNode *>(fnNode);
3793 generateSynopsisInfo(
"notifier", funcNode->name());
3798 m_writer->writeEndElement();
3804 m_writer->writeStartElement(dbNamespace,
"typedefsynopsis");
3807 m_writer->writeTextElement(dbNamespace,
"typedefname",
3808 enumNode->flagsType()->fullDocumentName());
3811 m_writer->writeEndElement();
3822 return node->name().mid(4);
3823 return node->name();
3827
3828
3829
3830void DocBookGenerator::typified(
const QString &string,
const Node *relative,
bool trailingSpace,
3835 QString pendingWord;
3837 for (
int i = 0; i <= string.size(); ++i) {
3839 if (i != string.size())
3842 QChar lower = ch.toLower();
3843 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
3844 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
3847 if (!pendingWord.isEmpty()) {
3848 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
3849 if (generateType && isProbablyType) {
3851 m_writer->writeCharacters(result);
3855 const Node *n = m_qdb->findTypeNode(pendingWord, relative, Genus::DontCare);
3860 href = linkForNode(n, relative);
3863 m_writer->writeStartElement(dbNamespace,
"type");
3865 m_writer->writeCharacters(pendingWord);
3867 generateSimpleLink(href, pendingWord);
3868 m_writer->writeEndElement();
3870 result += pendingWord;
3873 pendingWord.clear();
3875 if (ch.unicode() !=
'\0')
3880 if (trailingSpace && string.size()) {
3881 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
3882 result += QLatin1Char(
' ');
3885 m_writer->writeCharacters(result);
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3905 const QStringList &concepts,
3906 const Node *relative)
3908 if (concepts.isEmpty()) {
3909 m_writer->writeCharacters(text);
3913 QStringList sorted = concepts;
3914 std::sort(sorted.begin(), sorted.end(),
3915 [](
const QString &a,
const QString &b) {
return a.size() > b.size(); });
3921 struct Match { qsizetype offset; qsizetype length; QString name; QString target; };
3922 QList<Match> matches;
3923 QList<
bool> occupied(text.size(),
false);
3925 for (
const QString &concept_name : sorted) {
3926 const QString unqualified = concept_name.section(
"::"_L1, -1);
3927 const QRegularExpression re(
"\\b"_L1
3928 + QRegularExpression::escape(unqualified) +
"\\b"_L1);
3929 auto it = re.globalMatch(text);
3930 while (it.hasNext()) {
3931 const auto m = it.next();
3932 const qsizetype start = m.capturedStart();
3933 const qsizetype len = m.capturedLength();
3935 for (qsizetype i = start; i < start + len; ++i) {
3943 for (qsizetype i = start; i < start + len; ++i)
3945 matches.append({start, len, unqualified, concept_name});
3949 std::sort(matches.begin(), matches.end(),
3950 [](
const Match &a,
const Match &b) {
return a.offset < b.offset; });
3953 for (
const auto &m : matches) {
3955 m_writer->writeCharacters(text.mid(pos, m.offset - pos));
3956 const Node *n = m_qdb->findConceptNode(m.target);
3958 generateSimpleLink(linkForNode(n, relative), m.name);
3960 m_writer->writeCharacters(m.name);
3961 pos = m.offset + m.length;
3963 if (pos < text.size())
3964 m_writer->writeCharacters(text.mid(pos));
3968
3969
3970
3971
3972
3973
3974
3975
3976
3978 const Node *relative)
3982 if (param.template_declaration) {
3987 m_writer->writeCharacters(
"template <"_L1);
3989 for (
const auto &sub : param.template_declaration->parameters) {
3990 if (sub.sfinae_constraint)
3993 m_writer->writeCharacters(
", "_L1);
3994 generateTemplateParameter(sub, relative);
3997 m_writer->writeCharacters(
"> "_L1);
4000 switch (param
.kind) {
4002 if (param.concept_name) {
4003 const QString fq = QString::fromStdString(*param.concept_name);
4004 const QString unqualified = fq.section(
"::"_L1, -1);
4005 const Node *n = m_qdb->findConceptNode(fq);
4007 generateSimpleLink(linkForNode(n, relative), unqualified);
4011 m_writer->writeCharacters(fq);
4013 m_writer->writeCharacters(
"typename"_L1);
4016 case RelaxedTemplateParameter::Kind::NonTypeTemplateParameter:
4017 if (!decl.type.empty())
4018 typified(QString::fromStdString(decl.type), relative,
false,
true);
4020 case RelaxedTemplateParameter::Kind::TemplateTemplateParameter:
4021 m_writer->writeCharacters(
"typename"_L1);
4025 if (param.is_parameter_pack)
4026 m_writer->writeCharacters(
"..."_L1);
4028 if (!decl
.name.empty()) {
4029 m_writer->writeCharacters(
" "_L1);
4030 m_writer->writeCharacters(QString::fromStdString(decl.name));
4034 m_writer->writeCharacters(
" = "_L1);
4037 typified(QString::fromStdString(decl.initializer), relative,
false,
true);
4039 m_writer->writeCharacters(QString::fromStdString(decl.initializer));
4045
4046
4047
4048
4049
4050
4051
4052
4053
4055 const Node *relative)
4063 m_writer->writeCharacters(
"template <"_L1);
4065 m_writer->writeCharacters(
"\n"_L1);
4068 for (
const auto ¶m : templateDecl->parameters) {
4069 if (param.sfinae_constraint)
4072 m_writer->writeCharacters(multiline ?
",\n"_L1 :
", "_L1);
4074 m_writer->writeCharacters(
" "_L1);
4075 generateTemplateParameter(param, relative);
4080 m_writer->writeCharacters(
"\n"_L1);
4081 m_writer->writeCharacters(
">"_L1);
4083 if (templateDecl->requires_clause && !templateDecl->requires_clause->empty()) {
4084 m_writer->writeCharacters(
" requires "_L1);
4085 QStringList concepts;
4086 concepts.reserve(
int(templateDecl->referenced_concepts.size()));
4087 for (
const auto &s : templateDecl->referenced_concepts)
4088 concepts.append(QString::fromStdString(s));
4089 generateRequiresClauseText(QString::fromStdString(*templateDecl->requires_clause),
4090 concepts, relative);
4095 bool generateNameLink)
4099 QString name = taggedNode(node);
4101 if (!generateNameLink) {
4102 m_writer->writeCharacters(name);
4106 m_writer->writeStartElement(dbNamespace,
"emphasis");
4107 m_writer->writeAttribute(
"role",
"bold");
4108 generateSimpleLink(linkForNode(node, relative), name);
4109 m_writer->writeEndElement();
4113 bool generateExtra,
bool generateType)
4115 const QString &pname = parameter.name();
4116 const QString &ptype = parameter.type();
4118 qsizetype insertPos = !pname.isEmpty() ? parameter.nameInsertionPoint() : -1;
4119 if (!pname.isEmpty()) {
4120 if (insertPos >= 0) {
4122 typified(ptype.left(insertPos), relative,
false, generateType);
4124 typified(ptype, relative,
true, generateType);
4131 if (generateExtra || pname.isEmpty()) {
4132 m_writer->writeStartElement(dbNamespace,
"emphasis");
4133 m_writer->writeCharacters(paramName);
4134 m_writer->writeEndElement();
4138 typified(ptype.mid(insertPos), relative,
false, generateType);
4140 const QString &pvalue = parameter.defaultValue();
4141 if (generateExtra && !pvalue.isEmpty())
4142 m_writer->writeCharacters(
" = " + pvalue);
4154 const int MaxEnumValues = 6;
4156 if (generateExtra) {
4157 if (
auto extra = CodeMarker::extraSynopsis(node, style); !extra.isEmpty()) {
4158 generateExtraSynopsis(extra);
4159 m_writer->writeCharacters(u" "_s);
4164 QString namePrefix {};
4168 namePrefix = taggedNode(node->parent()) +
"::";
4173 case NodeType::Namespace:
4174 m_writer->writeCharacters(
"namespace ");
4175 m_writer->writeCharacters(namePrefix);
4176 generateSynopsisName(node, relative, generateNameLink);
4178 case NodeType::Class:
4179 m_writer->writeCharacters(
"class ");
4180 m_writer->writeCharacters(namePrefix);
4181 generateSynopsisName(node, relative, generateNameLink);
4187 if (
auto templateDecl = func->templateDecl()) {
4188 generateTemplateDecl(&*templateDecl, relative);
4189 if (templateDecl->visibleParameterCount() > QDoc::MultilineTemplateParamThreshold)
4190 m_writer->writeCharacters(
"\n"_L1);
4192 m_writer->writeCharacters(
" "_L1);
4198 if (!func->isNonvirtual())
4199 m_writer->writeCharacters(QStringLiteral(
"virtual "));
4203 if (style != Section::AllMembers && !func->returnType().isEmpty())
4204 typified(func->returnTypeString(), relative,
true, generateType);
4205 m_writer->writeCharacters(namePrefix);
4206 generateSynopsisName(node, relative, generateNameLink);
4209 m_writer->writeCharacters(QStringLiteral(
"("));
4212 for (
int i = 0; i < parameters
.count(); i++) {
4214 m_writer->writeCharacters(QStringLiteral(
", "));
4215 generateParameter(parameters
.at(i
), relative, generateExtra, generateType);
4218 m_writer->writeCharacters(QStringLiteral(
")"));
4221 if (func->isConst())
4222 m_writer->writeCharacters(QStringLiteral(
" const"));
4228 synopsis += QStringLiteral(
" final");
4230 synopsis += QStringLiteral(
" override");
4232 synopsis += QStringLiteral(
" = 0");
4234 synopsis += QStringLiteral(
" &");
4236 synopsis += QStringLiteral(
" &&");
4237 m_writer->writeCharacters(synopsis);
4239 if (!func->returnType().isEmpty() && func->returnType() !=
"void") {
4240 m_writer->writeCharacters(QStringLiteral(
" : "));
4241 typified(func->returnTypeString(), relative,
false, generateType);
4246 synopsis +=
" &"_L1;
4247 else if (func->isRefRef())
4248 synopsis +=
" &&"_L1;
4249 m_writer->writeCharacters(synopsis);
4251 if (
const auto &req = func->trailingRequiresClause(); req && !req->isEmpty()) {
4252 m_writer->writeCharacters(
" requires "_L1);
4253 generateRequiresClauseText(*req, func->referencedConcepts(), relative);
4258 const auto enume =
static_cast<
const EnumNode *>(node);
4259 if (!enume->isAnonymous()) {
4260 m_writer->writeCharacters(
"enum "_L1);
4261 m_writer->writeCharacters(namePrefix);
4262 generateSynopsisName(node, relative, generateNameLink);
4263 }
else if (generateNameLink) {
4264 m_writer->writeStartElement(dbNamespace,
"emphasis");
4265 m_writer->writeAttribute(
"role",
"bold");
4266 generateSimpleLink(linkForNode(node, relative),
"enum");
4267 m_writer->writeEndElement();
4269 m_writer->writeCharacters(
"enum"_L1);
4276 QStringList documentedItems = enume->doc().enumItemNames();
4277 if (documentedItems.isEmpty()) {
4278 const auto &enumItems = enume->items();
4279 for (
const auto &item : enumItems)
4280 documentedItems << item.name();
4282 const QStringList omitItems = enume->doc().omitEnumItemNames();
4283 for (
const auto &item : omitItems)
4284 documentedItems.removeAll(item);
4286 if (documentedItems.size() > MaxEnumValues) {
4288 const QString last = documentedItems.last();
4289 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
4290 documentedItems +=
"…";
4291 documentedItems += last;
4293 synopsis += documentedItems.join(QLatin1String(
", "));
4295 if (!documentedItems.isEmpty())
4296 synopsis += QLatin1Char(
' ');
4297 synopsis += QLatin1Char(
'}');
4299 m_writer->writeCharacters(synopsis);
4303 if (
auto templateDecl = node->templateDecl()) {
4304 generateTemplateDecl(&*templateDecl, relative);
4305 if (templateDecl->visibleParameterCount() > QDoc::MultilineTemplateParamThreshold)
4306 m_writer->writeCharacters(
"\n"_L1);
4308 m_writer->writeCharacters(
" "_L1);
4311 m_writer->writeCharacters(namePrefix);
4312 generateSynopsisName(node, relative, generateNameLink);
4315 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
4316 m_writer->writeCharacters(
"flags ");
4317 m_writer->writeCharacters(namePrefix);
4318 generateSynopsisName(node, relative, generateNameLink);
4321 const auto property =
static_cast<
const PropertyNode *>(node);
4322 m_writer->writeCharacters(namePrefix);
4323 generateSynopsisName(node, relative, generateNameLink);
4324 m_writer->writeCharacters(
" : ");
4325 typified(property->qualifiedDataType(), relative,
false, generateType);
4328 const auto variable =
static_cast<
const VariableNode *>(node);
4330 generateSynopsisName(node, relative, generateNameLink);
4331 m_writer->writeCharacters(
" : ");
4332 typified(variable->dataType(), relative,
false, generateType);
4334 typified(variable->leftType(), relative,
false, generateType);
4335 m_writer->writeCharacters(
" ");
4336 m_writer->writeCharacters(namePrefix);
4337 generateSynopsisName(node, relative, generateNameLink);
4338 m_writer->writeCharacters(variable->rightType());
4342 m_writer->writeCharacters(namePrefix);
4343 generateSynopsisName(node, relative, generateNameLink);
4362 if (nativeEnum && nativeEnum
->enumNode() && !enumValue.startsWith(
"%1."_L1.arg(nativeEnum->prefix()))) {
4363 m_writer->writeCharacters(
"%1.%2"_L1.arg(nativeEnum->prefix(), enumValue));
4369 && enumValue.section(
' ', 0, 0).contains(
'.'_L1))) {
4370 m_writer->writeCharacters(enumValue);
4374 QList<
const Node *> parents;
4376 parents.prepend(node);
4381 if (
static_cast<
const EnumNode *>(relative)->isScoped())
4382 parents << relative;
4384 m_writer->writeStartElement(dbNamespace,
"code");
4385 for (
auto parent : parents) {
4386 generateSynopsisName(parent, relative,
true);
4387 m_writer->writeCharacters((relative->genus() == Genus::QML) ?
"."_L1 :
"::"_L1);
4390 m_writer->writeCharacters(enumValue);
4391 m_writer->writeEndElement();
4395
4396
4397
4402 Q_ASSERT(node && !node->name().isEmpty());
4408 m_writer->writeStartElement(dbNamespace,
"note");
4415 m_writer->writeStartElement(dbNamespace,
"para");
4416 m_writer->writeCharacters(
4417 "This function can be invoked via the meta-object system and from QML. See ");
4418 generateSimpleLink(node->url(),
"Q_INVOKABLE");
4419 m_writer->writeCharacters(
".");
4420 m_writer->writeEndElement();
4424 m_writer->writeTextElement(
4425 dbNamespace,
"para",
4426 "This is a private signal. It can be used in signal connections but "
4427 "cannot be emitted by the user.");
4431 QString handler(node->name());
4432 int prefixLocation = handler.lastIndexOf(
'.', -2) + 1;
4433 handler[prefixLocation] = handler[prefixLocation].toTitleCase();
4434 handler.insert(prefixLocation, QLatin1String(
"on"));
4435 m_writer->writeStartElement(dbNamespace,
"para");
4436 m_writer->writeCharacters(
"The corresponding handler is ");
4437 m_writer->writeTextElement(dbNamespace,
"code", handler);
4438 m_writer->writeCharacters(
".");
4439 m_writer->writeEndElement();
4447 const auto *fn =
static_cast<
const FunctionNode *>(node);
4448 auto nodes = fn->associatedProperties();
4449 if (nodes.isEmpty())
4454 QMap<PropertyNode::FunctionRole, QList<
const PropertyNode *>> roleGroups;
4455 for (
const auto *n : std::as_const(nodes)) {
4456 const auto *pn =
static_cast<
const PropertyNode *>(n);
4457 PropertyNode::FunctionRole role = pn->role(fn);
4458 roleGroups[role].append(pn);
4470 for (
auto role : roleOrder) {
4471 const auto it = roleGroups.constFind(role);
4472 if (it == roleGroups.cend())
4475 const auto &properties = it.value();
4480 msg = QStringLiteral(
"Getter function");
4483 msg = QStringLiteral(
"Setter function");
4486 msg = QStringLiteral(
"Resetter function");
4489 msg = QStringLiteral(
"Notifier signal");
4492 msg = QStringLiteral(
"Bindable function");
4498 m_writer->writeStartElement(dbNamespace,
"para");
4499 if (properties.size() == 1) {
4500 const auto *pn = properties.first();
4501 m_writer->writeCharacters(msg +
" for property ");
4502 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4503 m_writer->writeCharacters(
". ");
4505 m_writer->writeCharacters(msg +
" for properties ");
4506 for (qsizetype i = 0; i < properties.size(); ++i) {
4507 const auto *pn = properties.at(i);
4508 generateSimpleLink(linkForNode(pn,
nullptr), pn->name());
4509 m_writer->writeCharacters(TextUtils::separator(i, properties.size()));
4511 m_writer->writeCharacters(
" ");
4513 m_writer->writeEndElement();
4520 const Node *linkNode;
4522 QString link = getAutoLink(&linkAtom, node, &linkNode);
4523 m_writer->writeStartElement(dbNamespace,
"para");
4524 m_writer->writeCharacters(
"This property supports ");
4525 generateSimpleLink(link,
"QProperty");
4526 m_writer->writeCharacters(
" bindings.");
4527 m_writer->writeEndElement();
4532 const auto *func =
static_cast<
const FunctionNode *>(node);
4535 if (func->isPrimaryOverload())
4538 m_writer->writeStartElement(dbNamespace,
"para");
4540 if (func->isSignal() || func->isSlot()) {
4541 auto writeDocBookLink = [&](
const QString &target,
const QString &label) {
4542 const Node *linkNode =
nullptr;
4544 const QString &link = getAutoLink(&linkAtom, node, &linkNode);
4546 m_writer->writeStartElement(dbNamespace,
"link");
4547 if (!link.isEmpty() && linkNode) {
4548 m_writer->writeAttribute(xlinkNamespace,
"href", link);
4550 m_writer->writeAttribute(dbNamespace,
"linkend", target);
4552 m_writer->writeCharacters(label);
4553 m_writer->writeEndElement();
4556 const QString &functionType = func->isSignal() ?
"signal" :
"slot";
4557 const QString &configKey = func->isSignal() ?
"overloadedsignalstarget" :
"overloadedslotstarget";
4558 const QString &defaultTarget = func->isSignal() ?
"connecting-overloaded-signals" :
"connecting-overloaded-slots";
4559 const QString &linkTarget = Config::instance().get(configKey).asString(defaultTarget);
4561 m_writer->writeCharacters(
"This " + functionType +
" is overloaded. ");
4563 QString snippet = generateOverloadSnippet(func);
4564 if (!snippet.isEmpty()) {
4565 m_writer->writeCharacters(
"To connect to this " + functionType +
":");
4566 m_writer->writeEndElement();
4568 m_writer->writeStartElement(dbNamespace,
"programlisting");
4569 m_writer->writeCharacters(snippet);
4570 m_writer->writeEndElement();
4575 m_writer->writeStartElement(dbNamespace,
"para");
4576 if (!linkTarget.isEmpty()) {
4577 m_writer->writeCharacters(
"For more examples and approaches, see ");
4578 writeDocBookLink(linkTarget,
"connecting to overloaded " + functionType +
"s");
4579 m_writer->writeCharacters(
".");
4581 }
else if (!linkTarget.isEmpty()) {
4582 m_writer->writeCharacters(
"For more examples and approaches, see ");
4583 writeDocBookLink(linkTarget,
"connecting to overloaded " + functionType +
"s");
4584 m_writer->writeCharacters(
".");
4588 const auto &args = node
->doc().overloadList();
4589 if (args.first().first.isEmpty()) {
4590 m_writer->writeCharacters(
"This is an overloaded function.");
4592 QString target = args.first().first;
4595 if (!target.contains(
"::")) {
4598 target = parent->name() +
"::" + target;
4601 m_writer->writeCharacters(
"This function overloads ");
4603 const Node *linkNode =
nullptr;
4605 QString link = getAutoLink(&linkAtom, node, &linkNode);
4606 if (!link.isEmpty() && linkNode)
4607 generateSimpleLink(link, target);
4609 m_writer->writeCharacters(target);
4610 m_writer->writeCharacters(
".");
4614 m_writer->writeEndElement();
4623 m_writer->writeEndElement();
4631 bool closeSupplementarySection =
false;
4635 const QList<Node *> &collective = scn->collective();
4637 bool firstFunction =
true;
4638 for (
const auto *sharedNode : collective) {
4639 if (firstFunction) {
4640 startSectionBegin(sharedNode);
4642 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4643 m_writer->writeAttribute(
"renderas",
"sect2");
4644 writeXmlId(sharedNode);
4647 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4649 generateSynopsis(sharedNode, relative, Section::Details);
4651 if (firstFunction) {
4653 firstFunction =
false;
4655 m_writer->writeEndElement();
4661 if (node->isEnumType(Genus::CPP) && (etn =
static_cast<
const EnumNode *>(node))->flagsType()) {
4662 startSectionBegin(node);
4664 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4668 m_writer->writeStartElement(dbNamespace,
"bridgehead");
4669 m_writer->writeAttribute(
"renderas",
"sect2");
4671 m_writer->writeEndElement();
4674 startSectionBegin(node);
4676 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4681 Q_ASSERT(m_hasSection);
4690 closeSupplementarySection =
true;
4691 startSection(
"",
"Notes");
4695 const auto *func =
static_cast<
const FunctionNode *>(node);
4696 if (func->hasOverloads() && (func->isSignal() || func->isSlot()))
4704 const auto property =
static_cast<
const PropertyNode *>(node);
4713 m_writer->writeStartElement(dbNamespace,
"para");
4715 m_writer->writeStartElement(dbNamespace,
"emphasis");
4716 m_writer->writeAttribute(
"role",
"bold");
4717 m_writer->writeCharacters(
"Access functions:");
4719 m_writer->writeEndElement();
4721 m_writer->writeEndElement();
4723 generateSectionList(section, node);
4730 m_writer->writeStartElement(dbNamespace,
"para");
4732 m_writer->writeStartElement(dbNamespace,
"emphasis");
4733 m_writer->writeAttribute(
"role",
"bold");
4734 m_writer->writeCharacters(
"Notifier signal:");
4736 m_writer->writeEndElement();
4738 m_writer->writeEndElement();
4740 generateSectionList(notifiers, node);
4744 const auto en =
static_cast<
const EnumNode *>(node);
4746 if (m_qflagsHref.isEmpty()) {
4747 Node *qflags = m_qdb->findClassNode(QStringList(
"QFlags"));
4749 m_qflagsHref = linkForNode(qflags,
nullptr);
4752 if (en->flagsType()) {
4753 m_writer->writeStartElement(dbNamespace,
"para");
4754 m_writer->writeCharacters(
"The ");
4755 m_writer->writeStartElement(dbNamespace,
"code");
4756 m_writer->writeCharacters(en->flagsType()->name());
4757 m_writer->writeEndElement();
4758 m_writer->writeCharacters(
" type is a typedef for ");
4759 m_writer->writeStartElement(dbNamespace,
"code");
4760 generateSimpleLink(m_qflagsHref,
"QFlags");
4761 m_writer->writeCharacters(
"<" + en->name() +
">. ");
4762 m_writer->writeEndElement();
4763 m_writer->writeCharacters(
"It stores an OR combination of ");
4764 m_writer->writeStartElement(dbNamespace,
"code");
4765 m_writer->writeCharacters(en->name());
4766 m_writer->writeEndElement();
4767 m_writer->writeCharacters(
" values.");
4768 m_writer->writeEndElement();
4773 if (closeSupplementarySection)
4784 bool useObsoleteMembers)
4789 if (!members.isEmpty()) {
4790 bool hasPrivateSignals =
false;
4791 bool isInvokable =
false;
4793 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4795 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4798 NodeVector::ConstIterator m = members.constBegin();
4799 while (m != members.constEnd()) {
4800 if ((*m)->access() == Access::Private) {
4805 m_writer->writeStartElement(dbNamespace,
"listitem");
4807 m_writer->writeStartElement(dbNamespace,
"para");
4810 generateSynopsis(*m, relative, section
.style());
4811 if ((*m)->isFunction()) {
4813 if (fn->isPrivateSignal())
4814 hasPrivateSignals =
true;
4815 else if (fn->isInvokable())
4819 m_writer->writeEndElement();
4821 m_writer->writeEndElement();
4827 m_writer->writeEndElement();
4830 if (hasPrivateSignals)
4837 && !section.inheritedMembers().isEmpty()) {
4838 m_writer->writeStartElement(dbNamespace,
"itemizedlist");
4840 m_writer->writeAttribute(itsNamespace,
"translate",
"no");
4843 generateSectionInheritedList(section, relative);
4845 m_writer->writeEndElement();
4853 QList<std::pair<
const Aggregate *,
int>>::ConstIterator p = section.inheritedMembers().constBegin();
4854 while (p != section.inheritedMembers().constEnd()) {
4855 m_writer->writeStartElement(dbNamespace,
"listitem");
4856 m_writer->writeCharacters(QString::number((*p).second) + u' ');
4857 if ((*p).second == 1)
4858 m_writer->writeCharacters(section.singular());
4860 m_writer->writeCharacters(section.plural());
4861 m_writer->writeCharacters(
" inherited from ");
4862 generateSimpleLink(fileName((*p).first) +
'#'
4863 + Generator::cleanRef(section.title().toLower()),
4864 (*p).first->plainFullName(relative));
4870
4871
4872
4876 Q_ASSERT(m_writer ==
nullptr);
4877 m_writer = startDocument(pn);
4888
4889
4894 Q_ASSERT(m_writer ==
nullptr);
4895 m_writer = startDocument(qcn);
4898 QString title = qcn->name();
4900 title.append(
" QML Value Type");
4902 title.append(
" QML Type");
4905 title.append(
" (Singleton)");
4907 title.append(
" (Uncreatable)");
4918 m_writer->writeStartElement(dbNamespace,
"note");
4919 m_writer->writeStartElement(dbNamespace,
"para");
4920 m_writer->writeStartElement(dbNamespace,
"emphasis");
4921 m_writer->writeAttribute(
"role",
"bold");
4922 m_writer->writeCharacters(
"Note: ");
4923 m_writer->writeEndElement();
4924 if (qcn->isSingleton())
4925 m_writer->writeCharacters(
"This type is a QML singleton. "
4926 "There is only one instance of this type in the QML engine.");
4928 m_writer->writeCharacters(
"This is an uncreatable type. "
4929 "It cannot be instantiated in QML.");
4930 m_writer->writeEndElement();
4931 m_writer->writeEndElement();
4934 startSection(
"details",
"Detailed Description");
4942 for (
const auto §ion : sections.detailsSections()) {
4943 if (!section.isEmpty()) {
4944 startSection(section.title().toLower(), section.title());
4946 for (
const auto &member : section.members())
4947 generateDetailedQmlMember(member, qcn);
4953 generateObsoleteQmlMembers(sections);
4962
4963
4964
4971 if (!title.isEmpty())
4975 title += n->element() + QLatin1Char(
'.');
4976 title += n->name() +
" : " + n->dataType();
4981 auto generateQmlMethodTitle = [&](
Node *node) {
4986 const auto *scn =
static_cast<
const SharedCommentNode *>(node);
4989 if (!scn->name().isEmpty())
4990 heading = scn->name() +
" group";
4992 heading = node->name();
4993 startSection(scn, heading);
4998 const QList<Node *> sharedNodes = scn->collective();
4999 for (
const auto &sharedNode : sharedNodes) {
5000 if (sharedNode->isQmlProperty()) {
5001 auto *qpn =
static_cast<QmlPropertyNode *>(sharedNode);
5003 m_writer->writeStartElement(dbNamespace,
"bridgehead");
5004 m_writer->writeAttribute(
"renderas",
"sect2");
5006 m_writer->writeCharacters(getQmlPropertyTitle(qpn));
5007 m_writer->writeEndElement();
5010 generateDocBookSynopsis(qpn);
5014 auto qpn =
static_cast<QmlPropertyNode *>(node);
5015 startSection(qpn, getQmlPropertyTitle(qpn));
5019 const QList<Node *> &sharedNodes = scn->collective();
5024 for (
const auto &sharedNode : sharedNodes) {
5026 if (!sharedNode->isFunction(Genus::QML) && !sharedNode->isQmlProperty()) {
5032 startSectionBegin(sharedNode);
5034 m_writer->writeStartElement(dbNamespace,
"bridgehead");
5035 m_writer->writeAttribute(
"renderas",
"sect2");
5039 if (sharedNode->isFunction(Genus::QML))
5040 generateQmlMethodTitle(sharedNode);
5041 else if (sharedNode->isQmlProperty())
5042 m_writer->writeCharacters(
5043 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(sharedNode)));
5049 m_writer->writeEndElement();
5050 generateDocBookSynopsis(sharedNode);
5056 startSectionBegin(refForNode(node));
5059 generateQmlMethodTitle(node);
5060 else if (node->isQmlProperty())
5061 m_writer->writeCharacters(
5062 getQmlPropertyTitle(
static_cast<QmlPropertyNode *>(node)));
5067 startSectionBegin(node);
5071 startSectionBegin(node);
5072 generateQmlMethodTitle(node);
5086
5087
5094 if (!node->url().isNull())
5098 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126 auto cn =
static_cast<CollectionNode *>(node);
5127 if (cn->wasSeen()) {
5128 m_qdb->mergeCollections(cn);
5129 generateCollectionNode(cn);
5130 }
else if (cn->isGenericCollection()) {
5134 generateGenericCollectionPage(cn);
5137 generatePageNode(
static_cast<PageNode *>(node));
5141 generateCppReferencePage(
static_cast<Aggregate *>(node));
5143 generateQmlTypePage(
static_cast<QmlTypeNode *>(node));
5145 generateProxyPage(
static_cast<Aggregate *>(node));
5151 auto *aggregate =
static_cast<Aggregate *>(node);
5152 for (
auto c : aggregate->childNodes()) {
5153 if (node->isPageNode())
5154 generateDocumentation(c);
5165 Q_ASSERT(m_writer ==
nullptr);
5166 m_writer = startDocument(aggregate);
5174 if (!aggregate
->doc().isEmpty()) {
5175 startSection(
"details",
"Detailed Description");
5177 generateBody(aggregate);
5186 for (
const auto §ion : detailsSections) {
5187 if (section.isEmpty())
5190 startSection(section.title().toLower(), section.title());
5192 const QList<Node *> &members = section.members();
5193 for (
const auto &member : members) {
5194 if (!member->isClassNode()) {
5195 generateDetailedMember(member, aggregate);
5197 startSectionBegin();
5198 generateFullName(member, aggregate);
5201 generateBrief(member);
5215
5216
5221 Q_ASSERT(m_writer ==
nullptr);
5222 m_writer = startDocument(cn);
5231 if (cn
->genus() != Genus::DOC && cn
->genus() != Genus::DontCare) {
5242 if (!nmm.isEmpty()) {
5243 startSection(
"namespaces",
"Namespaces");
5244 generateAnnotatedList(cn, nmm.values(),
"namespaces");
5248 if (!nmm.isEmpty()) {
5249 startSection(
"classes",
"Classes");
5250 generateAnnotatedList(cn, nmm.values(),
"classes");
5256 bool generatedTitle =
false;
5258 startSection(
"details",
"Detailed Description");
5259 generatedTitle =
true;
5264 !cn
->doc().body().isEmpty() ||
5266 !cn
->doc().alsoList().empty() ||
5269 writeAnchor(
"details");
5275 if (!cn->noAutoList() && (cn->isGroup() || cn->isQmlModule()))
5276 generateAnnotatedList(cn, cn->members(),
"members", AutoSection);
5287
5288
5289
5290
5295 QString name = cn->name().toLower();
5296 name.replace(QChar(
' '), QString(
"-"));
5297 QString filename = cn->tree()->physicalModuleName() +
"-" + name +
"." + fileExtension();
5300 Q_ASSERT(m_writer ==
nullptr);
5301 m_writer = startGenericDocument(cn, filename);
5310 m_writer->writeStartElement(dbNamespace,
"para");
5311 m_writer->writeCharacters(
"Each function or type documented here is related to a class or "
5312 "namespace that is documented in a different module. The reference "
5313 "page for that class or namespace will link to the function or type "
5315 m_writer->writeEndElement();
5319 for (
const auto &member : members)
5320 generateDetailedMember(member, cnc);
5333 m_writer->writeStartElement(dbNamespace,
"link");
5334 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(node));
5335 m_writer->writeAttribute(xlinkNamespace,
"role", targetType(node));
5336 m_writer->writeCharacters(node->fullName(relative));
5337 m_writer->writeEndElement();
5341 const Node *actualNode)
5343 Q_ASSERT(apparentNode);
5344 Q_ASSERT(actualNode);
5347 m_writer->writeStartElement(dbNamespace,
"link");
5348 m_writer->writeAttribute(xlinkNamespace,
"href", fullDocumentLocation(actualNode));
5349 m_writer->writeAttribute(
"role", targetType(actualNode));
5350 m_writer->writeCharacters(fullName);
5351 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
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 generateHeader(const Text &title, const Node *node)
Generates the opening portion of the DocBook header — {<db:info>} and the title element.
void initializeGenerator() override
Initializes the DocBook output generator's data structures from the configuration (Config).
bool generateText(const Text &text, const Node *relative) override
Generate the documentation for relative.
void finishHeader(const Node *node)
Emits the tail of the DocBook header — product, edition, titleabbrev, navigation links,...
void generateCppReferencePage(Node *node)
Generate a reference page for the C++ class, namespace, or header file documented in node.
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.
void generateHeader(const Text &title, const QString &subtitle, const Node *node)
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 format() const override
Returns the format identifier for this producer (e.g., "HTML", "DocBook", "template").
void generateExampleFilePage(const PageNode *en, ResolvedFile resolved_file, CodeMarker *=nullptr) override
Generate a file with the contents of a C++ or QML source file.
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, CodeMarker *marker=nullptr)
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 hasOverloads() const
Returns true if this function has overloads.
bool isMacro() const override
returns true if either FunctionNode::isMacroWithParams() or FunctionNode::isMacroWithoutParams() retu...
bool isDeletedAsWritten() const
bool isExplicitlyDefaulted() const
bool hasAssociatedProperties() const
bool generateComparisonCategory(const Node *node, CodeMarker *marker=nullptr)
static void setQmlTypeContext(QmlTypeNode *t)
const Atom * generateAtomList(const Atom *atom, const Node *relative, CodeMarker *marker, bool generate, int &numGeneratedAtoms)
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 generateComparisonTable(const Node *node)
Generates a table of comparison categories for node, combining both self-comparison (from \compares) ...
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.
const EnumNode * enumNode() const
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.
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
static QDocDatabase * qdocDB()
Creates the singleton.
Status
Specifies the status of the QQmlIncubator.
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() const
Const overloads that delegate to the resolving non-const versions when the attribute hasn't been cach...
bool isAttached() const override
Returns true if the QML property or QML method node is marked as attached.
ClassNode * classNode() const override
If this is a QmlTypeNode, this function returns the pointer to the C++ ClassNode that this QML type r...
bool isUncreatable() const
static void subclasses(const Node *base, NodeList &subs, bool recurse=false)
Loads the list subs with the nodes of all the subclasses of base.
QmlTypeNode * qmlBaseNode() const override
If this Aggregate is a QmlTypeNode, this function returns a pointer to the QmlTypeNode that is its ba...
CollectionNode * logicalModule() const override
If this is a QmlTypeNode, a pointer to its QML module is returned, which is a pointer to a Collection...
A class for containing the elements of one documentation section.
const NodeVector & obsoleteMembers() const
void appendMembers(const NodeVector &nv)
const NodeVector & members() const
A class for creating vectors of collections for documentation.
const Aggregate * aggregate() const
Sections(const Aggregate *aggregate)
This constructor builds the section vectors based on the type of the aggregate node.
bool hasObsoleteMembers(SectionPtrVector *summary_spv, SectionPtrVector *details_spv) const
Returns true if any sections in this object contain obsolete members.
SectionVector & detailsSections()
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 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_PRELIMINARY
#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[]
Provides human-readable descriptions of QDoc nodes.
constexpr std::size_t MultilineTemplateParamThreshold
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 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.
virtual bool isInternal() const
Returns true if the node's status is Internal, or if its parent is a class with Internal status.
bool isHeader() const
Returns true if the node type is HeaderFile.
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, that is, the aggregate under which the node is documented.
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.
Aggregate * declarationParent() const
Returns the aggregate in whose C++ scope the node was declared, or null if the node was not adopted b...
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
std::size_t visibleParameterCount() const
Returns the number of template parameters that are visible in rendered output — SFINAE-annotated para...
ValuedDeclaration valued_declaration
@ TemplateTemplateParameter
Represents a file that is reachable by QDoc based on its current configuration.