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
qdocgenerator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5
6#include <QtCore/qdir.h>
7
8#include <iostream>
9
10using namespace Qt::Literals::StringLiterals;
11
12namespace QDocGenerator {
13
14// See definition of idstring and licenseid in https://spdx.org/spdx-specification-21-web-version
15static bool isSpdxLicenseId(const QString &str) {
16 if (str.isEmpty())
17 return false;
18 for (auto iter(str.cbegin()); iter != str.cend(); ++iter) {
19 const QChar c = *iter;
20 if (!((c >= QLatin1Char('A') && c <= QLatin1Char('Z'))
21 || (c >= QLatin1Char('a') && c <= QLatin1Char('z'))
22 || (c >= QLatin1Char('0') && c <= QLatin1Char('9'))
23 || (c == QLatin1Char('-')) || (c == QLatin1Char('.'))))
24 return false;
25 }
26 return true;
27}
28
29static QString languageJoin(const QStringList &list)
30{
31 QString result;
32 for (int i = 0; i < list.size(); ++i) {
33 QString delimiter = u", "_s;
34 if (i == list.size() - 1) // last item
35 delimiter.clear();
36 else if (list.size() == 2)
37 delimiter = u" and "_s;
38 else if (list.size() > 2 && i == list.size() - 2)
39 delimiter = u", and "_s; // oxford comma
40 result += list[i] + delimiter;
41 }
42
43 return result;
44}
45
46// Embed source code between \badcode ... \endbadcode
47// Also, avoid '*/' breaking qdoc by passing the star as argument
48static void sourceCode(QTextStream &out, const QString &src)
49{
50 out << "\\badcode *\n";
51 out << QString(src).replace(u"*/"_s, u"\\1/"_s);
52 out << "\n\\endcode\n\n";
53}
54
55static void generate(QTextStream &out, const Package &package, const QDir &baseDir)
56{
57 out << "/*!\n\n";
58 for (const QString &part : package.qtParts) {
59 out << "\\ingroup attributions-" << package.qdocModule << "-" << part << "\n";
60 out << "\\ingroup attributions-" << part << "\n";
61 }
62
63 if (package.qtParts.contains("libs"_L1)) {
64 // show up in xxx-index.html page of module
65 out << "\\ingroup attributions-" << package.qdocModule << "\n";
66 // include in '\generatelist annotatedattributions'
67 out << "\\page " << package.qdocModule << "-attribution-" << package.id
68 << ".html\n";
69 out << "\\attribution\n";
70 } else {
71 out << "\\page " << package.qdocModule << "-attribution-" << package.id
72 << ".html \n";
73 }
74
75 // Suppress a potential QDoc warning by marking an attribution as an auxiliary
76 // page that's not required to be included in a TOC.
77 out << "\\meta {toc} {nonessential}\n";
78
79 out << "\\target " << package.id << "\n\n";
80 out << "\\title " << package.name;
81 if (!package.version.isEmpty())
82 out << ", version " << package.version;
83 out << "\n\n\\brief " << package.license << "\n\n";
84
85 if (!package.description.isEmpty())
86 out << package.description << "\n\n";
87
88 if (!package.qtUsage.isEmpty())
89 out << package.qtUsage << "\n\n";
90
91 if (package.origin == Package::Origin::InSource) {
92 QStringList sourcePaths;
93 if (package.files.isEmpty()) {
94 sourcePaths << baseDir.relativeFilePath(package.path);
95 } else {
96 const QDir packageDir(package.path);
97 for (const QString &filePath : package.files) {
98 const QString absolutePath = packageDir.absoluteFilePath(filePath);
99 sourcePaths << baseDir.relativeFilePath(absolutePath);
100 }
101 }
102
103 out << "The sources can be found in " << languageJoin(sourcePaths) << ".\n\n";
104 }
105
106 const bool hasPackageVersion = !package.version.isEmpty();
107 const bool hasPackageDownloadLocation = !package.downloadLocation.isEmpty();
108 if (!package.homepage.isEmpty()) {
109 out << "\\l{" << package.homepage << "}{Project Homepage}";
110 if (hasPackageVersion)
111 out << ", ";
112 }
113 if (hasPackageVersion) {
114 out << "upstream version: ";
115 if (hasPackageDownloadLocation)
116 out << "\\l{" << package.downloadLocation << "}{";
117 out << package.version;
118 if (hasPackageDownloadLocation)
119 out << "}";
120 }
121
122 out << "\n\n";
123
124 QString copyright;
125 if (!package.copyright.isEmpty())
126 copyright = package.copyright;
127 else if (!package.copyrightFileContents.isEmpty())
128 copyright = package.copyrightFileContents;
129
130 if (!copyright.isEmpty()) {
131 out << "\n";
132 sourceCode(out, copyright);
133 }
134
135 if (isSpdxLicenseId(package.licenseId) && !package.licenseId.startsWith("LicenseRef-"_L1)
136 && package.licenseId != "NONE"_L1) {
137 out << "\\l{https://spdx.org/licenses/" << package.licenseId << ".html}"
138 << "{" << package.license << "}.\n\n";
139 } else {
140 out << package.license << ".\n\n";
141 }
142
143 for (const QString &license : package.licenseFilesContents)
144 sourceCode(out, license);
145
146 out << "*/\n";
147}
148
149void generate(QTextStream &out, const QList<Package> &packages, const QString &baseDirectory,
150 LogLevel logLevel)
151{
152 if (logLevel == VerboseLog)
153 std::cerr << qPrintable(tr("Generating qdoc file...")) << std::endl;
154
155 QDir baseDir(baseDirectory);
156 for (const Package &package : packages)
157 generate(out, package, baseDir);
158}
159
160} // namespace QDocGenerator
LogLevel
Definition logging.h:9
@ VerboseLog
Definition logging.h:10
void generate(QTextStream &out, const QList< Package > &packages, const QString &baseDirectory, LogLevel logLevel)
static void generate(QTextStream &out, const Package &package, const QDir &baseDir)
static QString languageJoin(const QStringList &list)
static void sourceCode(QTextStream &out, const QString &src)
static bool isSpdxLicenseId(const QString &str)