Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmljsresourcefilemapper.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 <QFileInfo>
7#include <QDir>
8#include <QXmlStreamReader>
9
11
13 return Filter {
14 QString(),
17 };
18}
19
21{
22 return Filter {
25 File
26 };
27}
28
30{
31 return Filter {
32 file,
35 };
36}
37
39 const QString &directory)
40{
41 return Filter {
43 QStringList { QStringLiteral("qml") },
45 };
46}
47
49{
50 for (const QString &fileName: resourceFiles) {
52 if (!f.open(QIODevice::ReadOnly))
53 continue;
54 populateFromQrcFile(f);
55 }
56}
57
59{
60 return qrcPathToFileSystemPath.isEmpty();
61}
62
63bool QQmlJSResourceFileMapper::isFile(const QString &resourcePath) const
64{
65 for (const auto &entry : qrcPathToFileSystemPath) {
66 if (entry.resourcePath == resourcePath)
67 return true;
68 }
69 return false;
70}
71
72static bool hasSuffix(const QString &qrcPath, const QStringList &suffixes)
73{
74 if (suffixes.isEmpty())
75 return true;
76 const QString suffix = QFileInfo(qrcPath).suffix();
77 return suffixes.contains(suffix);
78}
79
80template<typename HandleMatch>
81void doFilter(const QList<QQmlJSResourceFileMapper::Entry> &qrcPathToFileSystemPath,
83 const HandleMatch &handler)
84{
86 const QString terminatedDirectory = filter.path.endsWith(u'/')
87 ? filter.path : (filter.path + u'/');
88
89 for (auto it = qrcPathToFileSystemPath.constBegin(),
90 end = qrcPathToFileSystemPath.constEnd(); it != end; ++it) {
91
92 const QString candidate = (filter.flags & QQmlJSResourceFileMapper::Resource)
93 ? it->resourcePath
94 : it->filePath;
95
96 if (!filter.path.isEmpty() && !candidate.startsWith(terminatedDirectory))
97 continue;
98
99 if (!hasSuffix(candidate, filter.suffixes))
100 continue;
101
103 // Crude. But shall we really allow slashes in QRC file names?
104 || !candidate.mid(terminatedDirectory.size()).contains(u'/')) {
105 if (handler(*it))
106 return;
107 }
108 }
109 return;
110 }
111
112 if (!hasSuffix(filter.path, filter.suffixes))
113 return;
114
115 for (auto it = qrcPathToFileSystemPath.constBegin(),
116 end = qrcPathToFileSystemPath.constEnd(); it != end; ++it) {
118 if (it->resourcePath == filter.path && handler(*it))
119 return;
120 } else if (it->filePath == filter.path && handler(*it)) {
121 return;
122 }
123 }
124}
125
128{
130 doFilter(qrcPathToFileSystemPath, filter, [&](const Entry &entry) {
131 result.append(entry);
132 return false;
133 });
134 return result;
135}
136
139{
141 doFilter(qrcPathToFileSystemPath, filter, [&](const Entry &entry) {
142 result.append(entry.filePath);
143 return false;
144 });
145 return result;
146}
147
150{
152 doFilter(qrcPathToFileSystemPath, filter, [&](const Entry &entry) {
153 result.append(entry.resourcePath);
154 return false;
155 });
156 return result;
157}
158
161{
163 doFilter(qrcPathToFileSystemPath, filter, [&](const Entry &entry) {
164 result = entry;
165 return true;
166 });
167 return result;
168}
169
170void QQmlJSResourceFileMapper::populateFromQrcFile(QFile &file)
171{
172 enum State {
173 InitialState,
174 InRCC,
175 InResource,
176 InFile
177 };
178 State state = InitialState;
179
180 QDir qrcDir = QFileInfo(file).absoluteDir();
181
182 QString prefix;
183 QString currentFileName;
184 QXmlStreamAttributes currentFileAttributes;
185
186 QXmlStreamReader reader(&file);
187 while (!reader.atEnd()) {
188 switch (reader.readNext()) {
189 case QXmlStreamReader::StartElement:
190 if (reader.name() == QStringLiteral("RCC")) {
191 if (state != InitialState)
192 return;
193 state = InRCC;
194 continue;
195 } else if (reader.name() == QStringLiteral("qresource")) {
196 if (state != InRCC)
197 return;
198 state = InResource;
199 QXmlStreamAttributes attributes = reader.attributes();
200 if (attributes.hasAttribute(QStringLiteral("prefix")))
201 prefix = attributes.value(QStringLiteral("prefix")).toString();
202 if (!prefix.startsWith(QLatin1Char('/')))
203 prefix.prepend(QLatin1Char('/'));
204 if (!prefix.endsWith(QLatin1Char('/')))
205 prefix.append(QLatin1Char('/'));
206 continue;
207 } else if (reader.name() == QStringLiteral("file")) {
208 if (state != InResource)
209 return;
210 state = InFile;
211 currentFileAttributes = reader.attributes();
212 continue;
213 }
214 return;
215
216 case QXmlStreamReader::EndElement:
217 if (reader.name() == QStringLiteral("file")) {
218 if (state != InFile)
219 return;
220 state = InResource;
221 continue;
222 } else if (reader.name() == QStringLiteral("qresource")) {
223 if (state != InResource)
224 return;
225 state = InRCC;
226 continue;
227 } else if (reader.name() == QStringLiteral("RCC")) {
228 if (state != InRCC)
229 return;
230 state = InitialState;
231 continue;
232 }
233 return;
234
235 case QXmlStreamReader::Characters: {
236 if (reader.isWhitespace())
237 break;
238 if (state != InFile)
239 return;
240 currentFileName = reader.text().toString();
241 if (currentFileName.isEmpty())
242 continue;
243
244 const QString fsPath = QDir::cleanPath(qrcDir.absoluteFilePath(currentFileName));
245
246 if (currentFileAttributes.hasAttribute(QStringLiteral("alias")))
247 currentFileName = currentFileAttributes.value(QStringLiteral("alias")).toString();
248
249 currentFileName = QDir::cleanPath(currentFileName);
250 while (currentFileName.startsWith(QLatin1String("../")))
251 currentFileName.remove(0, 3);
252
253 const QString qrcPath = prefix + currentFileName;
254 if (QFile::exists(fsPath))
255 qrcPathToFileSystemPath.append({qrcPath, fsPath});
256 continue;
257 }
258
259 default: break;
260 }
261 }
262}
263
\inmodule QtCore
Definition qdir.h:19
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2395
QString absoluteFilePath(const QString &fileName) const
Returns the absolute path name of a file in the directory.
Definition qdir.cpp:809
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString suffix() const
Returns the suffix (extension) of the file.
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
QDir absoluteDir() const
Returns the file's absolute path as a QDir object.
\inmodule QtCore
Definition qfile.h:93
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
QString text(const QString &key) const
Definition qlist.h:74
const_iterator constBegin() const noexcept
Definition qlist.h:615
const_iterator constEnd() const noexcept
Definition qlist.h:616
\inmodule QtCore
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1014
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5350
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.h:1217
QString & append(QChar c)
Definition qstring.cpp:3227
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition qstring.cpp:3435
QString & prepend(QChar c)
Definition qstring.h:411
bool hasAttribute(QAnyStringView qualifiedName) const
Definition qxmlstream.h:91
Q_CORE_EXPORT QStringView value(QAnyStringView namespaceUri, QAnyStringView name) const noexcept
QSet< QString >::iterator it
else opt state
[0]
Combined button and popup list for selecting options.
QImageReader reader("image.png")
[1]
GLuint GLuint end
GLfloat GLfloat f
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint entry
GLuint64EXT * result
[6]
static bool hasSuffix(const QString &qrcPath, const QStringList &suffixes)
void doFilter(const QList< QQmlJSResourceFileMapper::Entry > &qrcPathToFileSystemPath, const QQmlJSResourceFileMapper::Filter &filter, const HandleMatch &handler)
#define QStringLiteral(str)
QFile file
[0]
\inmodule QtCore \reentrant
Definition qchar.h:17
Entry entry(const Filter &filter) const
static Filter resourceFileFilter(const QString &file)
static Filter resourceQmlDirectoryFilter(const QString &directory)
bool isFile(const QString &resourcePath) const
QList< Entry > filter(const Filter &filter) const
QStringList filePaths(const Filter &filter) const
static Filter localFileFilter(const QString &file)
QQmlJSResourceFileMapper(const QStringList &resourceFiles)
QStringList resourcePaths(const Filter &filter) const