Qt 6.x
The Qt SDK
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 <QDirIterator>
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
29{
33};
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 QDirIterator dit(modulesDir, { QLatin1String("*.json") }, QDir::Files);
138 while (dit.hasNext()) {
139 QString filePath = dit.next();
140 QtModule module = moduleFromJsonFile(filePath, errorString);
141 if (!errorString->isEmpty())
142 return false;
143 if (module.internal)
144 continue;
145 module.id = modules.size();
146 if (module.id == QtModule::InvalidId) {
147 *errorString = "Internal Error: too many modules for ModuleBitset to hold."_L1;
148 return false;
149 }
150
151 {
152 auto it = moduleToCatalogMap.find(module.name);
153 if (it != moduleToCatalogMap.end())
154 module.translationCatalog = it->second;
155 }
156 if (module.translationCatalog.isEmpty()) {
157 auto it = repositoryToCatalogMap.find(module.repository);
158 if (it != repositoryToCatalogMap.end())
159 module.translationCatalog = it->second;
160 }
161 if (verbose)
162 dump(module);
163 modules.emplace_back(std::move(module));
164 }
165
166 return true;
167}
168
170{
171 return modules.at(id);
172}
173
175{
176 auto moduleHasPluginType = [&pluginType] (const QtModule &module) {
177 return module.pluginTypes.contains(pluginType);
178 };
179
180 auto it = std::find_if(modules.begin(), modules.end(), moduleHasPluginType);
181 if (it != modules.end())
182 return it->id ;
183
184 return QtModule::InvalidId;
185}
The QDirIterator class provides an iterator for directory entrylists.
@ Files
Definition qdir.h:22
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
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:127
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
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:160
GLhandleARB obj
[2]
GLuint64EXT * result
[6]
static QString dump(const QByteArray &)
#define qUtf8Printable(string)
Definition qstring.h:1395
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
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
ParseError error
QString errorString() const
\variable QJsonParseError::error
QString name
static constexpr size_t InvalidId
QString translationCatalog
QStringList pluginTypes
QString repository
bool internal
size_t id
QStringList repositories