Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
tocwriter.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "tocwriter.h"
5
6#include "generator.h"
7#include "location.h"
8#include "qdocdatabase.h"
9#include "node.h"
10
11#include <QtCore/qfile.h>
12#include <QtCore/qxmlstream.h>
13
15
16using namespace Qt::StringLiterals;
17
18/*!
19 \class TOCWriter
20 \brief Table of contents writer.
21
22 Generates an XML file for the table of contents (TOC) for the documentation
23 project. The TOC consists of (a nested) list of sub-pages
24 documented with \\toc command(s).
25*/
26
27
28/*!
29 Constructs a new TOCWriter, using a Generator \a g to
30 to fetch links (hrefs) for each TOC entry. A \a project
31 name is used in error reporting.
32*/
33TOCWriter::TOCWriter(Generator *g, const QString &project)
34: m_gen(g),
36 m_project(project)
37{
38}
39
40/*!
41 Writes the TOC entries for \a project to \a fileName,
42 starting from a page with a title matching \a indexTitle.
43
44 Does nothing if \a indexTitle is an empty string.
45*/
46void TOCWriter::generateTOC(const QString &fileName, const QString &indexTitle)
47{
48 if (indexTitle.isEmpty())
49 return;
50
51 auto *root = m_qdb->findNodeForTarget(indexTitle, nullptr);
52 if (!root)
53 return;
54
55 // Do not write an empty file
56 if (!getEntries(root))
57 return;
58
59 QFile file(fileName);
60 if (!file.open(QFile::WriteOnly)) {
61 Location().error("Failed to open %1 for writing"_L1.arg(fileName));
62 return;
63 }
64
65 QXmlStreamWriter writer(&file);
66 writer.setAutoFormatting(true);
67 writer.writeStartDocument();
68 writer.writeStartElement(u"section"_s);
69 writer.writeAttribute(u"ref"_s, m_gen->fullDocumentLocation(root));
70 writer.writeAttribute(u"title"_s, indexTitle);
71 writeEntry(writer, root);
72 writer.writeEndElement(); // root section
73 writer.writeEndDocument();
74 file.close();
75}
76
77
78/*!
79 Recursively writes the TOC entries (`section` elements) for \a node,
80 using \a writer.
81*/
82void TOCWriter::writeEntry(QXmlStreamWriter &writer, const Node *node)
83{
84 const auto entries{getEntries(node)};
85 if (!entries)
86 return;
87
88 // Max allowed recursion depth
89 constexpr int maxDepth{16};
90
91 if (++m_recursionDepth > maxDepth) {
92 Location().error("Maximum nesting level (%1) exceeded "
93 "when writing table of contents for '%2'"_L1
94 .arg(QString::number(maxDepth), m_project));
95 } else {
96 for (const auto &e : *entries) {
97 writer.writeStartElement(u"section"_s);
98 writer.writeAttribute(u"ref"_s, m_gen->fullDocumentLocation(e.first));
99 writer.writeAttribute(u"title"_s, e.second);
100 writeEntry(writer, e.first);
101 writer.writeEndElement(); // section
102 }
103 }
104 --m_recursionDepth;
105}
106
107/*!
108 Returns a list of TOC entries for \a node. A single TOC entry is
109 a pair consisting of a Node pointer and a user-visible link text.
110*/
111std::optional<TOCWriter::TitledNodeList> TOCWriter::getEntries(const Node *node) const
112{
113 const auto *atom = node->doc().body().firstAtom();
114 if (atom)
115 atom = atom->find(Atom::TableOfContentsLeft);
116 if (!atom)
117 return std::nullopt;
118
119 TitledNodeList result;
120 while (atom->next() && !atom->next(Atom::TableOfContentsRight)) {
121 atom = atom->next();
122 if (atom->type() == Atom::Link) {
123 QString ref{};
124 if (const auto *target = m_qdb->findNodeForAtom(atom, nullptr, ref))
125 result.append(std::make_pair(target, atom->linkText()));
126 else if (!Generator::noLinkErrors())
127 node->doc().location().warning("Can't link to '%1'"_L1.arg(atom->string()));
128 }
129 }
130
131 if (result.isEmpty())
132 return std::nullopt;
133 return result;
134}
135
136QT_END_NAMESPACE
The Atom class is the fundamental unit for representing documents internally.
Definition atom.h:19
AtomType type() const
Return the type of this atom.
Definition atom.h:151
@ TableOfContentsLeft
Definition atom.h:102
@ TableOfContentsRight
Definition atom.h:103
@ Link
Definition atom.h:61
const Atom * next() const
Return the next atom in the atom list.
Definition atom.h:148
const Atom * next(AtomType t) const
Return the next Atom in the list if it is of AtomType t.
Definition atom.cpp:301
const Text & body() const
Definition doc.cpp:115
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
static QDocDatabase * qdocDB()
Creates the singleton.
Table of contents writer.
Definition tocwriter.h:22
const Atom * firstAtom() const
Definition text.h:34
The Node class is the base class for all the nodes in QDoc's parse tree.
const Doc & doc() const
Returns a reference to the node's Doc data member.
Definition node.h:242