Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtmoduleinfo.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 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 "qtmoduleinfo.h"
5#include "utils.h"
6
7#include <QDirListing>
8#include <QJsonDocument>
9#include <QJsonArray>
10#include <QDebug>
11
12#include <iostream>
13#include <algorithm>
14#include <unordered_map>
15
16using namespace Qt::StringLiterals;
17
18static QStringList toStringList(const QJsonArray &jsonArray)
19{
21 for (const auto &item : jsonArray) {
22 if (item.isString())
23 result.append(item.toString());
24 }
25 return result;
26}
27
34
35using TranslationCatalogs = std::vector<TranslationCatalog>;
36
38 bool verbose,
39 QString *errorString)
40{
41 QFile file(translationsDir + QLatin1String("/catalogs.json"));
42 if (verbose) {
43 std::wcerr << "Trying to read translation catalogs from \""
44 << qUtf8Printable(file.fileName()) << "\".\n";
45 }
47 *errorString = QLatin1String("Cannot open ") + file.fileName();
48 return {};
49 }
50
51 QJsonParseError jsonParseError;
52 QJsonDocument document = QJsonDocument::fromJson(file.readAll(), &jsonParseError);
53 if (jsonParseError.error != QJsonParseError::NoError) {
54 *errorString = jsonParseError.errorString();
55 return {};
56 }
57
58 if (!document.isArray()) {
59 *errorString = QLatin1String("Expected an array as root element of ") + file.fileName();
60 return {};
61 }
62
63 TranslationCatalogs catalogs;
64 for (const QJsonValueRef &item : document.array()) {
65 TranslationCatalog catalog;
66 catalog.name = item[QLatin1String("name")].toString();
67 catalog.repositories = toStringList(item[QLatin1String("repositories")].toArray());
68 catalog.modules = toStringList(item[QLatin1String("modules")].toArray());
69 if (verbose)
70 std::wcerr << "Found catalog \"" << qUtf8Printable(catalog.name) << "\".\n";
71 catalogs.emplace_back(std::move(catalog));
72 }
73
74 return catalogs;
75}
76
77static QtModule moduleFromJsonFile(const QString &filePath, QString *errorString)
78{
79 QFile file(filePath);
81 *errorString = QLatin1String("Cannot open ") + file.fileName();
82 return {};
83 }
84
85 QJsonParseError jsonParseError;
86 QJsonDocument document = QJsonDocument::fromJson(file.readAll(), &jsonParseError);
87 if (jsonParseError.error != QJsonParseError::NoError) {
88 *errorString = jsonParseError.errorString();
89 return {};
90 }
91
92 if (!document.isObject()) {
93 *errorString = QLatin1String("Expected an object as root element of ") + file.fileName();
94 return {};
95 }
96
97 const QJsonObject obj = document.object();
98 QtModule module;
99 module.name = "Qt6"_L1 + obj[QLatin1String("name")].toString();
100 module.repository = obj[QLatin1String("repository")].toString();
101 module.internal = obj[QLatin1String("internal")].toBool();
102 module.pluginTypes = toStringList(obj[QLatin1String("plugin_types")].toArray());
103 return module;
104}
105
106static void dump(const QtModule &module)
107{
108 std::wcerr << "Found module \"" << qUtf8Printable(module.name) << "\".\n";
109 if (!module.pluginTypes.isEmpty())
110 qDebug().nospace() << " plugin types: " << module.pluginTypes;
111 if (!module.translationCatalog.isEmpty())
112 qDebug().nospace() << " translation catalog: "<< module.translationCatalog;
113}
114
115bool QtModuleInfoStore::populate(const QString &modulesDir, const QString &translationsDir,
116 bool verbose, QString *errorString)
117{
118 const TranslationCatalogs catalogs = readTranslationsCatalogs(translationsDir, verbose,
119 errorString);
120 if (!errorString->isEmpty()) {
121 std::wcerr << "Warning: Translations will not be available due to the following error."
122 << std::endl << *errorString << std::endl;
123 errorString->clear();
124 }
125 std::unordered_map<QString, QString> moduleToCatalogMap;
126 std::unordered_map<QString, QString> repositoryToCatalogMap;
127 for (const TranslationCatalog &catalog : catalogs) {
128 for (const QString &module : catalog.modules) {
129 moduleToCatalogMap.insert(std::make_pair(module, catalog.name));
130 }
131 for (const QString &repository : catalog.repositories) {
132 repositoryToCatalogMap.insert(std::make_pair(repository, catalog.name));
133 }
134 }
135
136 // Read modules, and assign a bit as ID.
137 for (const auto &dirEntry : QDirListing(modulesDir, {u"*.json"_s}, QDir::Files)) {
138 QtModule module = moduleFromJsonFile(dirEntry.filePath(), errorString);
139 if (!errorString->isEmpty())
140 return false;
141 if (module.internal && module.name.endsWith(QStringLiteral("Private")))
142 module.name.chop(7);
143 module.id = modules.size();
144 if (module.id == QtModule::InvalidId) {
145 *errorString = "Internal Error: too many modules for ModuleBitset to hold."_L1;
146 return false;
147 }
148
149 {
150 auto it = moduleToCatalogMap.find(module.name);
151 if (it != moduleToCatalogMap.end())
152 module.translationCatalog = it->second;
153 }
154 if (module.translationCatalog.isEmpty()) {
155 auto it = repositoryToCatalogMap.find(module.repository);
156 if (it != repositoryToCatalogMap.end())
157 module.translationCatalog = it->second;
158 }
159 if (verbose)
160 dump(module);
161 modules.emplace_back(std::move(module));
162 }
163
164 return true;
165}
166
168{
169 return modules.at(id);
170}
171
173{
174 auto moduleHasPluginType = [&pluginType] (const QtModule &module) {
175 return module.pluginTypes.contains(pluginType);
176 };
177
178 auto it = std::find_if(modules.begin(), modules.end(), moduleHasPluginType);
179 if (it != modules.end())
180 return it->id ;
181
182 return QtModule::InvalidId;
183}
The QDirListing class provides an STL-style iterator for directory entries.
Definition qdirlisting.h:18
@ Files
Definition qdir.h:23
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
Definition qfile.cpp:277
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
\inmodule QtCore\reentrant
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=nullptr)
Parses json as a UTF-8 encoded JSON document, and creates a QJsonDocument from it.
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
\inmodule QtCore \reentrant
iterator end()
Definition qset.h:140
iterator find(const T &value)
Definition qset.h:159
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void chop(qsizetype n)
Removes n characters from the end of the string.
Definition qstring.cpp:6340
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
bool populate(const QString &modulesDir, const QString &translationsDir, bool verbose, QString *errorString)
const QtModule & moduleById(size_t id) const
size_t moduleIdForPluginType(const QString &pluginType) const
QSet< QString >::iterator it
#define qDebug
[1]
Definition qlogging.h:164
GLhandleARB obj
[2]
GLuint64EXT * result
[6]
static QString dump(const QByteArray &)
#define qUtf8Printable(string)
Definition qstring.h:1535
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
static QtModule moduleFromJsonFile(const QString &filePath, QString *errorString)
std::vector< TranslationCatalog > TranslationCatalogs
static TranslationCatalogs readTranslationsCatalogs(const QString &translationsDir, bool verbose, QString *errorString)
static QStringList toStringList(const QJsonArray &jsonArray)
static void dump(const QtModule &module)
QFile file
[0]
QGraphicsItem * item
\inmodule QtCore\reentrant
QString name
static constexpr size_t InvalidId
QString translationCatalog
QStringList pluginTypes
QStringList repositories