Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmlpreviewfileengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#include <QtCore/qlibraryinfo.h>
8#include <QtCore/qthread.h>
9#include <QtCore/qwaitcondition.h>
10
11#include <cstring>
12
14
15static bool isRelative(const QString &path)
16{
17 if (path.isEmpty())
18 return true;
19 if (path.at(0) == '/')
20 return false;
21 if (path.at(0) == ':' && path.size() >= 2 && path.at(1) == '/')
22 return false;
23#ifdef Q_OS_WIN
24 if (path.length() >= 2 && path.at(1) == ':')
25 return false;
26#endif
27 return true;
28}
29
31{
33}
34
36{
38}
39
41{
42public:
43 QQmlPreviewFileEngineIterator(QDir::Filters filters, const QStringList &filterNames,
44 const QStringList &m_entries);
46
47 QString next() override;
48 bool hasNext() const override;
49 QString currentFileName() const override;
50
51private:
52 const QStringList m_entries;
53 int m_index;
54};
55
57 const QStringList &filterNames,
58 const QStringList &entries)
59 : QAbstractFileEngineIterator(filters, filterNames), m_entries(entries), m_index(0)
60{
61}
62
64{
65}
66
68{
69 if (!hasNext())
70 return QString();
71 ++m_index;
72 return currentFilePath();
73}
74
76{
77 return m_index < m_entries.size();
78}
79
81{
82 if (m_index == 0 || m_index > m_entries.size())
83 return QString();
84 return m_entries.at(m_index - 1);
85}
86
89 m_name(file), m_absolute(absolute), m_loader(loader)
90{
91 load();
92}
93
95{
96 m_name = file;
97 m_absolute = absolutePath(file);
98 m_fallback.reset();
99 m_contents.close();
100 m_contents.setData(QByteArray());
101 m_entries.clear();
102 load();
103}
104
105bool QQmlPreviewFileEngine::open(QIODevice::OpenMode flags,
106 std::optional<QFile::Permissions> permissions)
107{
108 switch (m_result) {
110 return m_contents.open(flags);
112 return false;
114 return m_fallback->open(flags, permissions);
115 default:
116 Q_UNREACHABLE_RETURN(false);
117 }
118}
119
121{
122 switch (m_result) {
124 return m_fallback->close();
126 m_contents.close();
127 return true;
129 return false;
130 default:
131 Q_UNREACHABLE_RETURN(false);
132 }
133}
134
136{
137 return m_fallback ? m_fallback->size() : m_contents.size();
138}
139
141{
142 return m_fallback ? m_fallback->pos() : m_contents.pos();
143}
144
146{
147 return m_fallback? m_fallback->seek(newPos) : m_contents.seek(newPos);
148}
149
151{
152 return m_fallback ? m_fallback->read(data, maxlen) : m_contents.read(data, maxlen);
153}
154
155QAbstractFileEngine::FileFlags QQmlPreviewFileEngine::fileFlags(
156 QAbstractFileEngine::FileFlags type) const
157{
158 if (m_fallback)
159 return m_fallback->fileFlags(type);
160
161 QAbstractFileEngine::FileFlags ret;
162
163 if (type & PermsMask) {
164 ret |= QAbstractFileEngine::FileFlags(
166 }
167
168 if (type & TypesMask) {
169 if (m_result == QQmlPreviewFileLoader::Directory)
171 else
172 ret |= FileType;
173 }
174
175 if (type & FlagsMask) {
176 ret |= ExistsFlag;
177 if (isRootPath(m_name))
178 ret |= RootFlag;
179 }
180
181 return ret;
182}
183
185{
186 if (m_fallback)
187 return m_fallback->fileName(file);
188
189 if (file == BaseName) {
190 int slashPos = m_name.lastIndexOf('/');
191 if (slashPos == -1)
192 return m_name;
193 return m_name.mid(slashPos + 1);
194 } else if (file == PathName || file == AbsolutePathName) {
195 const QString path = (file == AbsolutePathName) ? m_absolute : m_name;
196 const int slashPos = path.lastIndexOf('/');
197 if (slashPos == -1)
198 return QString();
199 else if (slashPos == 0)
200 return "/";
201 return path.left(slashPos);
202 } else if (file == CanonicalName || file == CanonicalPathName) {
203 if (file == CanonicalPathName) {
204 const int slashPos = m_absolute.lastIndexOf('/');
205 if (slashPos != -1)
206 return m_absolute.left(slashPos);
207 }
208 return m_absolute;
209 }
210 return m_name;
211}
212
214{
215 return m_fallback ? m_fallback->ownerId(owner) : static_cast<uint>(-2);
216}
217
219 const QStringList &filterNames)
220{
221 return m_fallback ? m_fallback->beginEntryList(filters, filterNames)
222 : new QQmlPreviewFileEngineIterator(filters, filterNames, m_entries);
223}
224
226{
227 return m_fallback ? m_fallback->endEntryList() : nullptr;
228}
229
231{
232 return m_fallback ? m_fallback->flush() : true;
233}
234
236{
237 return m_fallback ? m_fallback->syncToDisk() : false;
238}
239
241{
242 return m_fallback ? m_fallback->isSequential() : m_contents.isSequential();
243}
244
246{
247 return m_fallback ? m_fallback->remove() : false;
248}
249
251{
252 return m_fallback ? m_fallback->copy(newName) : false;
253}
254
256{
257 return m_fallback ? m_fallback->rename(newName) : false;
258}
259
261{
262 return m_fallback ? m_fallback->renameOverwrite(newName) : false;
263}
264
266{
267 return m_fallback ? m_fallback->link(newName) : false;
268}
269
270bool QQmlPreviewFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
271 std::optional<QFile::Permissions> permissions) const
272{
273 return m_fallback ? m_fallback->mkdir(dirName, createParentDirectories, permissions) : false;
274}
275
276bool QQmlPreviewFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
277{
278 return m_fallback ? m_fallback->rmdir(dirName, recurseParentDirectories) : false;
279}
280
282{
283 switch (m_result) {
285 return m_fallback->setSize(size);
287 if (size < 0 || size > std::numeric_limits<int>::max())
288 return false;
289 m_contents.buffer().resize(static_cast<int>(size));
290 return true;
292 return false;
293 default:
294 Q_UNREACHABLE_RETURN(false);
295 }
296}
297
299{
300 return m_fallback ? m_fallback->caseSensitive() : true;
301}
302
304{
305 return m_fallback ? m_fallback->isRelativePath() : isRelative(m_name);
306}
307
309 const QStringList &filterNames) const
310{
311 return m_fallback ? m_fallback->entryList(filters, filterNames)
313}
314
316{
317 return m_fallback ? m_fallback->setPermissions(perms) : false;
318}
319
321{
322 return m_fallback ? m_fallback->id() : QByteArray();
323}
324
326{
327 return m_fallback ? m_fallback->owner(owner) : QString();
328}
329
331{
332 // Files we replace are always newer than the ones we had before. This makes the QML engine
333 // actually recompile them, rather than pick them from the cache.
334 return m_fallback ? m_fallback->fileTime(time) : QDateTime::currentDateTime();
335}
336
338{
339 return m_fallback ? m_fallback->handle() : -1;
340}
341
343{
344 return m_fallback ? m_fallback->readLine(data, maxlen) : m_contents.readLine(data, maxlen);
345}
346
348{
349 return m_fallback ? m_fallback->write(data, len) : m_contents.write(data, len);
350}
351
353{
354 return m_fallback ? m_fallback->extension(extension, option, output) : false;
355}
356
358{
359 return m_fallback ? m_fallback->supportsExtension(extension) : false;
360}
361
362void QQmlPreviewFileEngine::load() const
363{
364 // We can get here from different threads on different instances of QQmlPreviewFileEngine.
365 // However, there is only one loader per QQmlPreviewFileEngineHandler and it is not thread-safe.
366 // Its content mutex doesn't help us here because we explicitly wait on it in load(), which
367 // causes it to be released. Therefore, lock the load mutex first.
368 // This doesn't cause any deadlocks because the only thread that wakes the loader on the content
369 // mutex never calls load(). It's the QML debug server thread that handles the debug protocol.
370 QMutexLocker loadLocker(m_loader->loadMutex());
371
372 m_result = m_loader->load(m_absolute);
373 switch (m_result) {
375 m_contents.setData(m_loader->contents());
376 break;
378 m_entries = m_loader->entries();
379 break;
381 m_fallback.reset(QAbstractFileEngine::create(m_name));
382 break;
384 Q_UNREACHABLE();
385 break;
386 }
387}
388
390 : m_loader(loader)
391{
392}
393
395{
396 // Don't load compiled QML/JS over the network
397 if (fileName.endsWith(".qmlc") || fileName.endsWith(".jsc") || isRootPath(fileName)) {
398 return nullptr;
399 }
400
401 QString relative = fileName;
402 while (relative.endsWith('/'))
403 relative.chop(1);
404
405 if (relative.isEmpty() || relative == ":")
406 return nullptr;
407
408 const QString absolute = relative.startsWith(':') ? relative : absolutePath(relative);
409
410 return m_loader->isBlacklisted(absolute)
411 ? nullptr : new QQmlPreviewFileEngine(relative, absolute, m_loader.data());
412}
413
The QAbstractFileEngineIterator class provides an iterator interface for custom file engines.
QDir::Filters filters() const
Returns the entry filters for this iterator.
virtual QString currentFilePath() const
Returns the path to the current directory entry.
\inmodule QtCore \reentrant
virtual bool remove()
Requests that the file is deleted from the file system.
virtual bool renameOverwrite(const QString &newName)
FileOwner
\value OwnerUser The user who owns the file.
virtual bool supportsExtension(Extension extension) const
virtual bool copy(const QString &newName)
Copies the contents of this file to a file with the name newName.
virtual bool setPermissions(uint perms)
Requests that the file's permissions be set to perms.
virtual bool isRelativePath() const
Return true if the file referred to by this file engine has a relative path; otherwise return false.
virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const
Requests that the directory dirName is deleted from the file system.
virtual bool close()
Closes the file, returning true if successful; otherwise returns false.
virtual qint64 write(const char *data, qint64 len)
Writes len bytes from data to the file.
virtual int handle() const
Returns the native file handle for this file engine.
virtual bool flush()
Flushes the open file, returning true if successful; otherwise returns false.
virtual Iterator * endEntryList()
virtual bool seek(qint64 pos)
Sets the file position to the given offset.
virtual bool mkdir(const QString &dirName, bool createParentDirectories, std::optional< QFile::Permissions > permissions=std::nullopt) const
Requests that the directory dirName be created with the specified permissions.
virtual qint64 readLine(char *data, qint64 maxlen)
This function reads one line, terminated by a '\n' character, from the file info data.
virtual qint64 read(char *data, qint64 maxlen)
Reads a number of characters from the file into data.
virtual bool rename(const QString &newName)
Requests that the file be renamed to newName in the file system.
virtual QDateTime fileTime(FileTime time) const
If time is BirthTime, return when the file was born (created).
virtual bool link(const QString &newName)
Creates a link from the file currently specified by fileName() to newName.
FileTime
These are used by the fileTime() function.
virtual qint64 size() const
Returns the size of the file.
virtual uint ownerId(FileOwner) const
If owner is OwnerUser return the ID of the user who owns the file.
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const
Requests that a list of all the files matching the filters list based on the filterNames in the file ...
virtual QString fileName(FileName file=DefaultName) const
Return the file engine's current file name in the format specified by file.
virtual bool isSequential() const
Returns true if the file is a sequential access device; returns false if the file is a direct access ...
virtual QByteArray id() const
static QAbstractFileEngine * create(const QString &fileName)
Creates and returns a QAbstractFileEngine suitable for processing fileName.
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const
This function should return the set of OR'd flags that are true for the file engine's file,...
virtual Iterator * beginEntryList(QDir::Filters filters, const QStringList &filterNames)
Returns an instance of a QAbstractFileEngineIterator using filters for entry filtering and filterName...
FileName
These values are used to request a file name in a particular format.
virtual bool extension(Extension extension, const ExtensionOption *option=nullptr, ExtensionReturn *output=nullptr)
virtual qint64 pos() const
Returns the current file position.
virtual QString owner(FileOwner) const
If owner is OwnerUser return the name of the user who owns the file.
virtual bool caseSensitive() const
Should return true if the underlying file system is case-sensitive; otherwise return false.
virtual bool setSize(qint64 size)
Requests that the file be set to size size.
virtual bool open(QIODevice::OpenMode openMode, std::optional< QFile::Permissions > permissions=std::nullopt)
Opens the file in the specified mode.
bool open(OpenMode openMode) override
\reimp
Definition qbuffer.cpp:296
qint64 pos() const override
\reimp
Definition qbuffer.cpp:324
void setData(const QByteArray &data)
Sets the contents of the internal buffer to be data.
Definition qbuffer.cpp:259
void close() override
\reimp
Definition qbuffer.cpp:316
qint64 size() const override
\reimp
Definition qbuffer.cpp:332
bool seek(qint64 off) override
\reimp
Definition qbuffer.cpp:341
QByteArray & buffer()
Returns a reference to the QBuffer's internal buffer.
Definition qbuffer.cpp:218
\inmodule QtCore
Definition qbytearray.h:57
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
\inmodule QtCore\reentrant
Definition qdatetime.h:257
static QDateTime currentDateTime()
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2395
static QString currentPath()
Returns the absolute path of the application's current directory.
Definition qdir.cpp:2051
static Q_CORE_EXPORT bool isRootPath(const QString &path)
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes,...
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
\inmodule QtCore
Definition qmutex.h:317
T * data() const
Definition qpointer.h:56
QAbstractFileEngine * create(const QString &fileName) const override
Creates a file engine for file fileName.
QQmlPreviewFileEngineHandler(QQmlPreviewFileLoader *loader)
QString currentFileName() const override
This pure virtual function returns the name of the current directory entry, excluding the path.
bool hasNext() const override
This pure virtual function returns true if there is at least one more entry in the current directory ...
QString next() override
This pure virtual function advances the iterator to the next directory entry, and returns the file pa...
QQmlPreviewFileEngineIterator(QDir::Filters filters, const QStringList &filterNames, const QStringList &m_entries)
bool supportsExtension(Extension extension) const override
bool link(const QString &newName) override
Creates a link from the file currently specified by fileName() to newName.
QQmlPreviewFileEngine(const QString &file, const QString &absolute, QQmlPreviewFileLoader *loader)
uint ownerId(FileOwner) const override
If owner is OwnerUser return the ID of the user who owns the file.
bool setPermissions(uint perms) override
Requests that the file's permissions be set to perms.
Iterator * endEntryList() override
bool caseSensitive() const override
Should return true if the underlying file system is case-sensitive; otherwise return false.
FileFlags fileFlags(FileFlags type) const override
This function should return the set of OR'd flags that are true for the file engine's file,...
bool seek(qint64) override
Sets the file position to the given offset.
void setFileName(const QString &file) override
Sets the file engine's file name to file.
QDateTime fileTime(FileTime time) const override
If time is BirthTime, return when the file was born (created).
bool mkdir(const QString &dirName, bool createParentDirectories, std::optional< QFile::Permissions > permissions=std::nullopt) const override
Requests that the directory dirName be created with the specified permissions.
bool extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) override
Iterator * beginEntryList(QDir::Filters filters, const QStringList &filterNames) override
Returns an instance of a QAbstractFileEngineIterator using filters for entry filtering and filterName...
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override
Requests that a list of all the files matching the filters list based on the filterNames in the file ...
bool flush() override
Flushes the open file, returning true if successful; otherwise returns false.
qint64 read(char *data, qint64 maxlen) override
Reads a number of characters from the file into data.
qint64 write(const char *data, qint64 len) override
Writes len bytes from data to the file.
bool open(QIODevice::OpenMode flags, std::optional< QFile::Permissions > permissions) override
Opens the file in the specified mode.
qint64 pos() const override
Returns the current file position.
qint64 readLine(char *data, qint64 maxlen) override
This function reads one line, terminated by a '\n' character, from the file info data.
bool copy(const QString &newName) override
Copies the contents of this file to a file with the name newName.
bool setSize(qint64 size) override
Requests that the file be set to size size.
bool isRelativePath() const override
Return true if the file referred to by this file engine has a relative path; otherwise return false.
bool rmdir(const QString &dirName, bool recurseParentDirectories) const override
Requests that the directory dirName is deleted from the file system.
QString owner(FileOwner) const override
If owner is OwnerUser return the name of the user who owns the file.
bool renameOverwrite(const QString &newName) override
bool isSequential() const override
Returns true if the file is a sequential access device; returns false if the file is a direct access ...
QString fileName(QAbstractFileEngine::FileName file) const override
Return the file engine's current file name in the format specified by file.
int handle() const override
Returns the native file handle for this file engine.
bool rename(const QString &newName) override
Requests that the file be renamed to newName in the file system.
qint64 size() const override
Returns the size of the file.
bool remove() override
Requests that the file is deleted from the file system.
bool close() override
Closes the file, returning true if successful; otherwise returns false.
QByteArray id() const override
Result load(const QString &file)
bool isBlacklisted(const QString &file)
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
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
void chop(qsizetype n)
Removes n characters from the end of the string.
Definition qstring.cpp:6180
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
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
void extension()
[6]
Definition dialogs.cpp:230
Combined button and popup list for selecting options.
return ret
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum type
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLsizei len
GLsizei const GLchar *const * path
GLuint GLenum option
static QT_BEGIN_NAMESPACE bool isRelative(const QString &path)
static QString absolutePath(const QString &path)
bool isRootPath(const QString &path)
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
QT_BEGIN_NAMESPACE typedef uchar * output
QFile file
[0]
QObject::connect nullptr
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]