9#include <QXmlStreamReader>
13QQmlJSResourceFileMapper::Filter QQmlJSResourceFileMapper::allQmlJSFilter() {
16 QStringList { QStringLiteral(
"qml"), QStringLiteral(
"js"), QStringLiteral(
"mjs") },
21QQmlJSResourceFileMapper::Filter QQmlJSResourceFileMapper::localFileFilter(
const QString &file)
24 QDir::cleanPath(QFileInfo(file).absoluteFilePath()),
30QQmlJSResourceFileMapper::Filter QQmlJSResourceFileMapper::resourceFileFilter(
const QString &file)
39QQmlJSResourceFileMapper::Filter QQmlJSResourceFileMapper::resourceQmlDirectoryFilter(
40 const QString &directory)
44 QStringList { QStringLiteral(
"qml") },
49QQmlJSResourceFileMapper::QQmlJSResourceFileMapper(
const QStringList &resourceFiles)
51 for (
const QString &fileName: resourceFiles) {
53 if (!f.open(QIODevice::ReadOnly))
55 populateFromQrcFile(f);
59bool QQmlJSResourceFileMapper::isEmpty()
const
61 return qrcPathToFileSystemPath.isEmpty();
64bool QQmlJSResourceFileMapper::isFile(QStringView resourcePath)
const
66 for (
const auto &entry : qrcPathToFileSystemPath) {
67 if (entry.resourcePath == resourcePath)
73static bool hasSuffix(
const QString &qrcPath,
const QStringList &suffixes)
75 if (suffixes.isEmpty())
77 const QString suffix = QFileInfo(qrcPath).suffix();
78 return suffixes.contains(suffix);
81template<
typename HandleMatch>
82void doFilter(
const QList<QQmlJSResourceFileMapper::Entry> &qrcPathToFileSystemPath,
83 const QQmlJSResourceFileMapper::Filter &filter,
84 const HandleMatch &handler)
86 if (filter.flags & QQmlJSResourceFileMapper::Directory) {
87 const QString terminatedDirectory = filter.path.endsWith(u'/')
88 ? filter.path : (filter.path + u'/');
90 for (
auto it = qrcPathToFileSystemPath.constBegin(),
91 end = qrcPathToFileSystemPath.constEnd(); it != end; ++it) {
93 const QString candidate = (filter.flags & QQmlJSResourceFileMapper::Resource)
97 if (!filter.path.isEmpty() && !candidate.startsWith(terminatedDirectory))
100 if (!hasSuffix(candidate, filter.suffixes))
103 if ((filter.flags & QQmlJSResourceFileMapper::Recurse)
105 || !candidate.mid(terminatedDirectory.size()).contains(u'/')) {
113 if (!hasSuffix(filter.path, filter.suffixes))
116 for (
auto it = qrcPathToFileSystemPath.constBegin(),
117 end = qrcPathToFileSystemPath.constEnd(); it != end; ++it) {
118 if (filter.flags & QQmlJSResourceFileMapper::Resource) {
119 if (it->resourcePath == filter.path && handler(*it))
121 }
else if (it->filePath == filter.path && handler(*it)) {
127QList<QQmlJSResourceFileMapper::Entry> QQmlJSResourceFileMapper::filter(
128 const QQmlJSResourceFileMapper::Filter &filter)
const
131 doFilter(qrcPathToFileSystemPath, filter, [&](
const Entry &entry) {
132 result.append(entry);
138QStringList QQmlJSResourceFileMapper::filePaths(
139 const QQmlJSResourceFileMapper::Filter &filter)
const
142 doFilter(qrcPathToFileSystemPath, filter, [&](
const Entry &entry) {
143 result.append(entry.filePath);
149QStringList QQmlJSResourceFileMapper::resourcePaths(
150 const QQmlJSResourceFileMapper::Filter &filter)
const
153 doFilter(qrcPathToFileSystemPath, filter, [&](
const Entry &entry) {
154 result.append(entry.resourcePath);
160QQmlJSResourceFileMapper::Entry QQmlJSResourceFileMapper::entry(
161 const QQmlJSResourceFileMapper::Filter &filter)
const
164 doFilter(qrcPathToFileSystemPath, filter, [&](
const Entry &entry) {
171void QQmlJSResourceFileMapper::populateFromQrcFile(QFile &file)
179 State state = InitialState;
181 QDir qrcDir = QFileInfo(file).absoluteDir();
184 QString currentFileName;
185 QXmlStreamAttributes currentFileAttributes;
187 QXmlStreamReader reader(&file);
188 while (!reader.atEnd()) {
189 switch (reader.readNext()) {
190 case QXmlStreamReader::StartElement:
191 if (reader.name() == QStringLiteral(
"RCC")) {
192 if (state != InitialState)
196 }
else if (reader.name() == QStringLiteral(
"qresource")) {
200 QXmlStreamAttributes attributes = reader.attributes();
201 if (attributes.hasAttribute(QStringLiteral(
"prefix")))
202 prefix = attributes.value(QStringLiteral(
"prefix")).toString();
203 if (!prefix.startsWith(QLatin1Char(
'/')))
204 prefix.prepend(QLatin1Char(
'/'));
205 if (!prefix.endsWith(QLatin1Char(
'/')))
206 prefix.append(QLatin1Char(
'/'));
208 }
else if (reader.name() == QStringLiteral(
"file")) {
209 if (state != InResource)
212 currentFileAttributes = reader.attributes();
217 case QXmlStreamReader::EndElement:
218 if (reader.name() == QStringLiteral(
"file")) {
223 }
else if (reader.name() == QStringLiteral(
"qresource")) {
224 if (state != InResource)
228 }
else if (reader.name() == QStringLiteral(
"RCC")) {
231 state = InitialState;
236 case QXmlStreamReader::Characters: {
237 if (reader.isWhitespace())
241 currentFileName = reader.text().toString();
242 if (currentFileName.isEmpty())
245 const QString fsPath = QDir::cleanPath(qrcDir.absoluteFilePath(currentFileName));
247 if (currentFileAttributes.hasAttribute(QStringLiteral(
"alias")))
248 currentFileName = currentFileAttributes.value(QStringLiteral(
"alias")).toString();
250 currentFileName = QDir::cleanPath(currentFileName);
251 while (currentFileName.startsWith(QLatin1String(
"../")))
252 currentFileName.remove(0, 3);
254 const QString qrcPath = prefix + currentFileName;
255 if (QFile::exists(fsPath))
256 qrcPathToFileSystemPath.append({qrcPath, fsPath});
static bool hasSuffix(const QString &qrcPath, const QStringList &suffixes)
void doFilter(const QList< QQmlJSResourceFileMapper::Entry > &qrcPathToFileSystemPath, const QQmlJSResourceFileMapper::Filter &filter, const HandleMatch &handler)