1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "qdocgenerator.h"
30
31#include <QtCore/qdir.h>
32
33#include <iostream>
34
35namespace QDocGenerator {
36
37// See definition of idstring and licenseid in https://spdx.org/spdx-specification-21-web-version
38static bool isSpdxLicenseId(const QString &str) {
39 if (str.isEmpty())
40 return false;
41 for (auto iter(str.cbegin()); iter != str.cend(); ++iter) {
42 const QChar c = *iter;
43 if (!((c >= QLatin1Char('A') && c <= QLatin1Char('Z'))
44 || (c >= QLatin1Char('a') && c <= QLatin1Char('z'))
45 || (c >= QLatin1Char('0') && c <= QLatin1Char('9'))
46 || (c == QLatin1Char('-')) || (c == QLatin1Char('.'))))
47 return false;
48 }
49 return true;
50}
51
52static QString languageJoin(const QStringList &list)
53{
54 QString result;
55 for (int i = 0; i < list.size(); ++i) {
56 QString delimiter = QStringLiteral(", ");
57 if (i == list.size() - 1) // last item
58 delimiter.clear();
59 else if (list.size() == 2)
60 delimiter = QStringLiteral(" and ");
61 else if (list.size() > 2 && i == list.size() - 2)
62 delimiter = QStringLiteral(", and "); // oxford comma
63 result += list[i] + delimiter;
64 }
65
66 return result;
67}
68
69static void generate(QTextStream &out, const Package &package, const QDir &baseDir,
70 LogLevel logLevel)
71{
72 out << "/*!\n\n";
73 for (const QString &part: package.qtParts)
74 out << "\\ingroup attributions-" << part << "\n";
75
76 if (package.qtParts.contains(str: QLatin1String("libs"))) {
77 // show up in xxx-index.html page of module
78 out << "\\ingroup attributions-" << package.qdocModule << "\n";
79 // include in '\generatelist annotatedattributions'
80 out << "\\page " << package.qdocModule << "-attribution-" << package.id
81 << ".html attribution\n";
82 } else {
83 out << "\\page " << package.qdocModule << "-attribution-" << package.id
84 << ".html \n";
85 }
86
87 out << "\\target " << package.id << "\n\n";
88 out << "\\title " << package.name;
89 if (!package.version.isEmpty())
90 out << ", version " << package.version;
91 out << "\n\n\\brief " << package.license << "\n\n";
92
93 if (!package.description.isEmpty())
94 out << package.description << "\n\n";
95
96 if (!package.qtUsage.isEmpty())
97 out << package.qtUsage << "\n\n";
98
99 QStringList sourcePaths;
100 if (package.files.isEmpty()) {
101 sourcePaths << baseDir.relativeFilePath(fileName: package.path);
102 } else {
103 const QDir packageDir(package.path);
104 for (const QString &filePath: package.files) {
105 const QString absolutePath = packageDir.absoluteFilePath(fileName: filePath);
106 sourcePaths << baseDir.relativeFilePath(fileName: absolutePath);
107 }
108 }
109
110 out << "The sources can be found in " << languageJoin(list: sourcePaths) << ".\n\n";
111
112 const bool hasPackageVersion = !package.version.isEmpty();
113 const bool hasPackageDownloadLocation = !package.downloadLocation.isEmpty();
114 if (!package.homepage.isEmpty()) {
115 out << "\\l{" << package.homepage << "}{Project Homepage}";
116 if (hasPackageVersion)
117 out << ", ";
118 }
119 if (hasPackageVersion) {
120 out << "upstream version: ";
121 if (hasPackageDownloadLocation)
122 out << "\\l{" << package.downloadLocation << "}{";
123 out << package.version;
124 if (hasPackageDownloadLocation)
125 out << "}";
126 }
127
128 out << "\n\n";
129
130 if (!package.copyright.isEmpty())
131 out << "\n\\badcode\n" << package.copyright << "\n\\endcode\n\n";
132
133 if (isSpdxLicenseId(str: package.licenseId) && package.licenseId != QLatin1String("NONE")) {
134 out << "\\l{https://spdx.org/licenses/" << package.licenseId << ".html}"
135 << "{" << package.license << "}.\n\n";
136 } else if (package.licenseId.startsWith(s: QLatin1String("urn:dje:license:"))) {
137 out << "\\l{https://enterprise.dejacode.com/licenses/public/" << package.licenseId.mid(position: 16)
138 << "/}{" << package.license << "}.\n\n";
139 } else {
140 out << package.license << ".\n\n";
141 }
142
143 if (!package.licenseFile.isEmpty()) {
144 QFile file(package.licenseFile);
145 if (!file.open(flags: QIODevice::ReadOnly)) {
146 if (logLevel != SilentLog)
147 std::cerr << qPrintable(
148 tr("Path %1 : cannot open license file %2.")
149 .arg(QDir::toNativeSeparators(package.path))
150 .arg(QDir::toNativeSeparators(package.licenseFile))
151 ) << "*/\n";
152 return;
153 }
154 out << "\\badcode\n";
155 out << QString::fromUtf8(str: file.readAll()).trimmed();
156 out << "\n\\endcode\n";
157 }
158 out << "*/\n";
159}
160
161void generate(QTextStream &out, const QVector<Package> &packages, const QString &baseDirectory,
162 LogLevel logLevel)
163{
164 if (logLevel == VerboseLog)
165 std::cerr << qPrintable(tr("Generating qdoc file...")) << std::endl;
166
167 QDir baseDir(baseDirectory);
168 for (const Package &package : packages)
169 generate(out, package, baseDir, logLevel);
170}
171
172} // namespace QDocGenerator
173

source code of qttools/src/qtattributionsscanner/qdocgenerator.cpp