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
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:
44 const QStringList &filterNames, const QStringList &m_entries);
46
47 bool advance() override;
48 QString currentFileName() const override;
49
50private:
51 const QStringList m_entries;
52 int m_index;
53};
54
56 QDir::Filters filters,
57 const QStringList &filterNames,
58 const QStringList &entries)
59 : QAbstractFileEngineIterator(path, filters, filterNames), m_entries(entries), m_index(0)
60{
61}
62
66
68{
69 if (m_index >= m_entries.size())
70 return false;
71
72 ++m_index;
73 return true;
74}
75
77{
78 if (m_index == 0 || m_index > m_entries.size())
79 return QString();
80 return m_entries.at(m_index - 1);
81}
82
84 QQmlPreviewFileLoader *loader) :
85 m_name(file), m_absolute(absolute), m_loader(loader)
86{
87 load();
88}
89
91{
92 m_name = file;
93 m_absolute = absolutePath(file);
94 m_fallback.reset();
95 m_contents.close();
96 m_contents.setData(QByteArray());
97 m_entries.clear();
98 load();
99}
100
101bool QQmlPreviewFileEngine::open(QIODevice::OpenMode flags,
102 std::optional<QFile::Permissions> permissions)
103{
104 switch (m_result) {
106 return m_contents.open(flags);
108 return false;
110 return m_fallback->open(flags, permissions);
111 default:
112 Q_UNREACHABLE_RETURN(false);
113 }
114}
115
117{
118 switch (m_result) {
120 return m_fallback->close();
122 m_contents.close();
123 return true;
125 return false;
126 default:
127 Q_UNREACHABLE_RETURN(false);
128 }
129}
130
132{
133 return m_fallback ? m_fallback->size() : m_contents.size();
134}
135
137{
138 return m_fallback ? m_fallback->pos() : m_contents.pos();
139}
140
142{
143 return m_fallback? m_fallback->seek(newPos) : m_contents.seek(newPos);
144}
145
147{
148 return m_fallback ? m_fallback->read(data, maxlen) : m_contents.read(data, maxlen);
149}
150
151QAbstractFileEngine::FileFlags QQmlPreviewFileEngine::fileFlags(
152 QAbstractFileEngine::FileFlags type) const
153{
154 if (m_fallback)
155 return m_fallback->fileFlags(type);
156
157 QAbstractFileEngine::FileFlags ret;
158
159 if (type & PermsMask) {
160 ret |= QAbstractFileEngine::FileFlags(
162 }
163
164 if (type & TypesMask) {
165 if (m_result == QQmlPreviewFileLoader::Directory)
167 else
168 ret |= FileType;
169 }
170
171 if (type & FlagsMask) {
172 ret |= ExistsFlag;
173 if (isRootPath(m_name))
174 ret |= RootFlag;
175 }
176
177 return ret;
178}
179
181{
182 if (m_fallback)
183 return m_fallback->fileName(file);
184
185 if (file == BaseName) {
186 int slashPos = m_name.lastIndexOf('/');
187 if (slashPos == -1)
188 return m_name;
189 return m_name.mid(slashPos + 1);
190 } else if (file == PathName || file == AbsolutePathName) {
191 const QString path = (file == AbsolutePathName) ? m_absolute : m_name;
192 const int slashPos = path.lastIndexOf('/');
193 if (slashPos == -1)
194 return QString();
195 else if (slashPos == 0)
196 return "/";
197 return path.left(slashPos);
198 } else if (file == CanonicalName || file == CanonicalPathName) {
199 if (file == CanonicalPathName) {
200 const int slashPos = m_absolute.lastIndexOf('/');
201 if (slashPos != -1)
202 return m_absolute.left(slashPos);
203 }
204 return m_absolute;
205 }
206 return m_name;
207}
208
210{
211 return m_fallback ? m_fallback->ownerId(owner) : static_cast<uint>(-2);
212}
213
215 const QString &path, QDir::Filters filters, const QStringList &filterNames)
216{
217 return m_fallback ? m_fallback->beginEntryList(path, filters, filterNames)
218 : std::make_unique<QQmlPreviewFileEngineIterator>(
219 path, filters, filterNames, m_entries);
220}
221
223{
224 return m_fallback ? m_fallback->endEntryList() : nullptr;
225}
226
228{
229 return m_fallback ? m_fallback->flush() : true;
230}
231
233{
234 return m_fallback ? m_fallback->syncToDisk() : false;
235}
236
238{
239 return m_fallback ? m_fallback->isSequential() : m_contents.isSequential();
240}
241
243{
244 return m_fallback ? m_fallback->remove() : false;
245}
246
248{
249 return m_fallback ? m_fallback->copy(newName) : false;
250}
251
253{
254 return m_fallback ? m_fallback->rename(newName) : false;
255}
256
258{
259 return m_fallback ? m_fallback->renameOverwrite(newName) : false;
260}
261
263{
264 return m_fallback ? m_fallback->link(newName) : false;
265}
266
267bool QQmlPreviewFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
268 std::optional<QFile::Permissions> permissions) const
269{
270 return m_fallback ? m_fallback->mkdir(dirName, createParentDirectories, permissions) : false;
271}
272
273bool QQmlPreviewFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
274{
275 return m_fallback ? m_fallback->rmdir(dirName, recurseParentDirectories) : false;
276}
277
279{
280 switch (m_result) {
282 return m_fallback->setSize(size);
284 if (size < 0 || size > std::numeric_limits<int>::max())
285 return false;
286 m_contents.buffer().resize(static_cast<int>(size));
287 return true;
289 return false;
290 default:
291 Q_UNREACHABLE_RETURN(false);
292 }
293}
294
296{
297 return m_fallback ? m_fallback->caseSensitive() : true;
298}
299
301{
302 return m_fallback ? m_fallback->isRelativePath() : isRelative(m_name);
303}
304
306 const QStringList &filterNames) const
307{
308 return m_fallback ? m_fallback->entryList(filters, filterNames)
310}
311
313{
314 return m_fallback ? m_fallback->setPermissions(perms) : false;
315}
316
318{
319 return m_fallback ? m_fallback->id() : QByteArray();
320}
321
323{
324 return m_fallback ? m_fallback->owner(owner) : QString();
325}
326
328{
329 // Files we replace are always newer than the ones we had before. This makes the QML engine
330 // actually recompile them, rather than pick them from the cache.
331 return m_fallback ? m_fallback->fileTime(time) : QDateTime::currentDateTime();
332}
333
335{
336 return m_fallback ? m_fallback->handle() : -1;
337}
338
340{
341 return m_fallback ? m_fallback->readLine(data, maxlen) : m_contents.readLine(data, maxlen);
342}
343
345{
346 return m_fallback ? m_fallback->write(data, len) : m_contents.write(data, len);
347}
348
350{
351 return m_fallback ? m_fallback->extension(extension, option, output) : false;
352}
353
355{
356 return m_fallback ? m_fallback->supportsExtension(extension) : false;
357}
358
359void QQmlPreviewFileEngine::load() const
360{
361 // We can get here from different threads on different instances of QQmlPreviewFileEngine.
362 // However, there is only one loader per QQmlPreviewFileEngineHandler and it is not thread-safe.
363 // Its content mutex doesn't help us here because we explicitly wait on it in load(), which
364 // causes it to be released. Therefore, lock the load mutex first.
365 // This doesn't cause any deadlocks because the only thread that wakes the loader on the content
366 // mutex never calls load(). It's the QML debug server thread that handles the debug protocol.
367 QMutexLocker loadLocker(m_loader->loadMutex());
368
369 m_result = m_loader->load(m_absolute);
370 switch (m_result) {
372 m_contents.setData(m_loader->contents());
373 break;
375 m_entries = m_loader->entries();
376 break;
378 m_fallback = QAbstractFileEngine::create(m_name);
379 break;
381 Q_UNREACHABLE();
382 break;
383 }
384}
385
390
391std::unique_ptr<QAbstractFileEngine> QQmlPreviewFileEngineHandler::create(
392 const QString &fileName) const
393{
394 // Don't load compiled QML/JS over the network
395 if (fileName.endsWith(".qmlc") || fileName.endsWith(".jsc") || isRootPath(fileName)) {
396 return nullptr;
397 }
398
399 QString relative = fileName;
400 while (relative.endsWith('/'))
401 relative.chop(1);
402
403 if (relative.isEmpty() || relative == ":")
404 return nullptr;
405
406 const QString absolute = relative.startsWith(':') ? relative : absolutePath(relative);
407
408 if (m_loader->isBlacklisted(absolute))
409 return {};
410
411 return std::make_unique<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.
FileOwner
\value OwnerUser The user who owns the file.
static std::unique_ptr< QAbstractFileEngine > create(const QString &fileName)
Creates and returns a QAbstractFileEngine suitable for processing fileName.
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 ...
std::unique_ptr< Iterator > IteratorUniquePtr
FileName
These values are used to request a file name in a particular format.
bool open(OpenMode openMode) override
\reimp
Definition qbuffer.cpp:295
qint64 pos() const override
\reimp
Definition qbuffer.cpp:323
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:315
qint64 size() const override
\reimp
Definition qbuffer.cpp:331
bool seek(qint64 off) override
\reimp
Definition qbuffer.cpp:340
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:283
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:2398
static QString currentPath()
Returns the absolute path of the application's current directory.
Definition qdir.cpp:2054
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:313
T * data() const noexcept
Definition qpointer.h:73
std::unique_ptr< QAbstractFileEngine > create(const QString &fileName) const override
If this file handler can handle fileName, this method creates a file engine and returns it wrapped in...
QQmlPreviewFileEngineHandler(QQmlPreviewFileLoader *loader)
QString currentFileName() const override
This pure virtual function returns the name of the current directory entry, excluding the path.
QQmlPreviewFileEngineIterator(const QString &path, QDir::Filters filters, const QStringList &filterNames, const QStringList &m_entries)
bool advance() override
This pure virtual function advances the iterator to the next directory entry; if the operation was su...
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)
QDateTime fileTime(QFile::FileTime time) const override
If time is BirthTime, return when the file was born (created).
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.
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.
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
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.
IteratorUniquePtr beginEntryList(const QString &path, QDir::Filters filters, const QStringList &filterNames) override
Returns a QAbstractFileEngine::IteratorUniquePtr, that can be used to iterate over the entries in pat...
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.
IteratorUniquePtr endEntryList() override
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)
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString left(qsizetype n) const &
Definition qstring.h:363
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:296
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:5455
void chop(qsizetype n)
Removes n characters from the end of the string.
Definition qstring.cpp:6340
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
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:5506
void extension()
[6]
Definition dialogs.cpp:230
Combined button and popup list for selecting options.
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
return ret
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLbitfield flags
GLsizei const GLchar *const * path
GLuint GLenum option
GLenum GLsizei len
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:34
long long qint64
Definition qtypes.h:60
QT_BEGIN_NAMESPACE typedef uchar * output
QFile file
[0]
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]