Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qmimedatabase.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include <qplatformdefs.h> // always first
6
7#include "qmimedatabase.h"
8#include "qmimedatabase_p.h"
9
10#include "qmimeprovider_p.h"
11#include "qmimetype_p.h"
12
13#include <private/qfilesystementry_p.h>
14
15#include <QtCore/QMap>
16#include <QtCore/QFile>
17#include <QtCore/QFileInfo>
18#include <QtCore/QStandardPaths>
19#include <QtCore/QBuffer>
20#include <QtCore/QUrl>
21#include <QtCore/QDebug>
22
23#include <algorithm>
24#include <functional>
25#include <stack>
26
28
29using namespace Qt::StringLiterals;
30
32{
33 return QStringLiteral("inode/directory");
34}
36{
37 return QStringLiteral("text/plain");
38}
39
40Q_GLOBAL_STATIC(QMimeDatabasePrivate, staticQMimeDatabase)
41
43{
44 return staticQMimeDatabase();
45}
46
48 : m_defaultMimeType(QStringLiteral("application/octet-stream"))
49{
50}
51
53{
54}
55
56Q_CONSTINIT
57#ifdef QT_BUILD_INTERNAL
58Q_CORE_EXPORT
59#else
60static const
61#endif
63
64bool QMimeDatabasePrivate::shouldCheck()
65{
66 if (m_lastCheck.isValid() && m_lastCheck.elapsed() < qmime_secondsBetweenChecks * 1000)
67 return false;
68 m_lastCheck.start();
69 return true;
70}
71
73{
75}
76
77#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
78# define QT_USE_MMAP
79#endif
80
81void QMimeDatabasePrivate::loadProviders()
82{
83 // We use QStandardPaths every time to check if new files appeared
84 const QStringList mimeDirs = locateMimeDirectories();
85 const auto fdoIterator = std::find_if(mimeDirs.constBegin(), mimeDirs.constEnd(), [](const QString &mimeDir) -> bool {
86 return QFileInfo::exists(mimeDir + "/packages/freedesktop.org.xml"_L1); }
87 );
88 const bool needInternalDB = QMimeXMLProvider::InternalDatabaseAvailable && fdoIterator == mimeDirs.constEnd();
89 //qDebug() << "mime dirs:" << mimeDirs;
90
91 Providers currentProviders;
92 std::swap(m_providers, currentProviders);
93
94 m_providers.reserve(mimeDirs.size() + (needInternalDB ? 1 : 0));
95
96 for (const QString &mimeDir : mimeDirs) {
97 const QString cacheFile = mimeDir + "/mime.cache"_L1;
98 // Check if we already have a provider for this dir
99 const auto predicate = [mimeDir](const std::unique_ptr<QMimeProviderBase> &prov)
100 {
101 return prov && prov->directory() == mimeDir;
102 };
103 const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), predicate);
104 if (it == currentProviders.end()) {
105 std::unique_ptr<QMimeProviderBase> provider;
106#if defined(QT_USE_MMAP)
107 if (qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE") && QFileInfo::exists(cacheFile)) {
108 provider.reset(new QMimeBinaryProvider(this, mimeDir));
109 //qDebug() << "Created binary provider for" << mimeDir;
110 if (!provider->isValid()) {
111 provider.reset();
112 }
113 }
114#endif
115 if (!provider) {
116 provider.reset(new QMimeXMLProvider(this, mimeDir));
117 //qDebug() << "Created XML provider for" << mimeDir;
118 }
119 m_providers.push_back(std::move(provider));
120 } else {
121 auto provider = std::move(*it); // take provider out of the vector
122 provider->ensureLoaded();
123 if (!provider->isValid()) {
124 provider.reset(new QMimeXMLProvider(this, mimeDir));
125 //qDebug() << "Created XML provider to replace binary provider for" << mimeDir;
126 }
127 m_providers.push_back(std::move(provider));
128 }
129 }
130 // mimeDirs is sorted "most local first, most global last"
131 // so the internal XML DB goes at the end
132 if (needInternalDB) {
133 // Check if we already have a provider for the InternalDatabase
134 const auto isInternal = [](const std::unique_ptr<QMimeProviderBase> &prov)
135 {
136 return prov && prov->isInternalDatabase();
137 };
138 const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), isInternal);
139 if (it == currentProviders.end()) {
140 m_providers.push_back(Providers::value_type(new QMimeXMLProvider(this, QMimeXMLProvider::InternalDatabase)));
141 } else {
142 m_providers.push_back(std::move(*it));
143 }
144 }
145
146 // Handle mimetypes with glob-deleteall tags (from XML providers)
147 auto it = m_providers.begin();
148 const auto end = m_providers.end();
149 for (;it != end; ++it) {
150 const QStringList &list = (*it)->m_mimeTypesWithDeletedGlobs;
151 if (list.isEmpty())
152 continue;
153 // Each Provider affects Providers with lower precedence
154 auto nextIt = it + 1;
155 for (; nextIt != end; ++nextIt)
156 (*nextIt)->excludeMimeTypeGlobs(list);
157 }
158}
159
160const QMimeDatabasePrivate::Providers &QMimeDatabasePrivate::providers()
161{
162#ifndef Q_OS_WASM // stub implementation always returns true
163 Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex
164#endif
165 if (m_providers.empty()) {
166 loadProviders();
167 m_lastCheck.start();
168 } else {
169 if (shouldCheck())
170 loadProviders();
171 }
172 return m_providers;
173}
174
176{
177 for (const auto &provider : providers()) {
178 const QString ret = provider->resolveAlias(nameOrAlias);
179 if (!ret.isEmpty())
180 return ret;
181 }
182 return nameOrAlias;
183}
184
190{
191 const QString mimeName = resolveAlias(nameOrAlias);
192 for (const auto &provider : providers()) {
193 QMimeType mime = provider->mimeTypeForName(mimeName);
194 if (mime.isValid())
195 return mime;
196 }
197 return {};
198}
199
201{
202 if (fileName.endsWith(u'/'))
203 return { directoryMimeType() };
204
206 QStringList matchingMimeTypes = result.m_matchingMimeTypes;
207 matchingMimeTypes.sort(); // make it deterministic
208 return matchingMimeTypes;
209}
210
212{
214 const QString fileNameExcludingPath = QFileSystemEntry(fileName).fileName();
215 for (const auto &provider : providers())
216 provider->addFileNameMatches(fileNameExcludingPath, result);
217 return result;
218}
219
221{
222 QMutexLocker locker(&mutex);
223 if (mimePrivate.name.isEmpty())
224 return; // invalid mimetype
225 if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand
226 Q_ASSERT(mimePrivate.fromCache);
227 bool found = false;
228 for (const auto &provider : providers()) {
229 if (provider->loadMimeTypePrivate(mimePrivate)) {
230 found = true;
231 break;
232 }
233 }
234 if (!found) {
235 const QString file = mimePrivate.name + ".xml"_L1;
236 qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.\n"
237 "Either it was just removed, or the directory doesn't have executable permission..."
239 }
240 mimePrivate.loaded = true;
241 }
242}
243
245{
246 QMutexLocker locker(&mutex);
247 if (mimePrivate.fromCache) {
248 mimePrivate.genericIconName.clear();
249 for (const auto &provider : providers()) {
250 provider->loadGenericIcon(mimePrivate);
251 if (!mimePrivate.genericIconName.isEmpty())
252 break;
253 }
254 }
255}
256
258{
259 QMutexLocker locker(&mutex);
260 if (mimePrivate.fromCache) {
261 mimePrivate.iconName.clear();
262 for (const auto &provider : providers()) {
263 provider->loadIcon(mimePrivate);
264 if (!mimePrivate.iconName.isEmpty())
265 break;
266 }
267 }
268}
269
270QString QMimeDatabasePrivate::fallbackParent(const QString &mimeTypeName) const
271{
272 const QStringView myGroup = QStringView{mimeTypeName}.left(mimeTypeName.indexOf(u'/'));
273 // All text/* types are subclasses of text/plain.
274 if (myGroup == "text"_L1 && mimeTypeName != plainTextMimeType())
275 return plainTextMimeType();
276 // All real-file mimetypes implicitly derive from application/octet-stream
277 if (myGroup != "inode"_L1 &&
278 // ignore non-file extensions
279 myGroup != "all"_L1 && myGroup != "fonts"_L1 && myGroup != "print"_L1 && myGroup != "uri"_L1
280 && mimeTypeName != defaultMimeType()) {
281 return defaultMimeType();
282 }
283 return QString();
284}
285
287{
288 QMutexLocker locker(&mutex);
289 return parents(mimeName);
290}
291
293{
296 for (const auto &provider : providers())
297 provider->addParents(mimeName, result);
298 if (result.isEmpty()) {
299 const QString parent = fallbackParent(mimeName);
300 if (!parent.isEmpty())
301 result.append(parent);
302 }
303 return result;
304}
305
307{
308 QMutexLocker locker(&mutex);
310 for (const auto &provider : providers())
311 provider->addAliases(mimeName, result);
312 return result;
313}
314
316{
317 QMutexLocker locker(&mutex);
318 return inherits(mime, parent);
319}
320
321static inline bool isTextFile(const QByteArray &data)
322{
323 // UTF16 byte order marks
324 static const char bigEndianBOM[] = "\xFE\xFF";
325 static const char littleEndianBOM[] = "\xFF\xFE";
326 if (data.startsWith(bigEndianBOM) || data.startsWith(littleEndianBOM))
327 return true;
328
329 // Check the first 128 bytes (see shared-mime spec)
330 const char *p = data.constData();
331 const char *e = p + qMin(128, data.size());
332 for ( ; p < e; ++p) {
333 if (static_cast<unsigned char>(*p) < 32 && *p != 9 && *p !=10 && *p != 13)
334 return false;
335 }
336
337 return true;
338}
339
341{
342 if (data.isEmpty()) {
343 *accuracyPtr = 100;
344 return mimeTypeForName(QStringLiteral("application/x-zerosize"));
345 }
346
347 *accuracyPtr = 0;
348 QMimeType candidate;
349 for (const auto &provider : providers())
350 provider->findByMagic(data, accuracyPtr, candidate);
351
352 if (candidate.isValid())
353 return candidate;
354
355 if (isTextFile(data)) {
356 *accuracyPtr = 5;
358 }
359
361}
362
364{
365 // First, glob patterns are evaluated. If there is a match with max weight,
366 // this one is selected and we are done. Otherwise, the file contents are
367 // evaluated and the match with the highest value (either a magic priority or
368 // a glob pattern weight) is selected. Matching starts from max level (most
369 // specific) in both cases, even when there is already a suffix matching candidate.
370
371 // Pass 1) Try to match on the file name
372 QMimeGlobMatchResult candidatesByName = findByFileName(fileName);
373 if (candidatesByName.m_allMatchingMimeTypes.size() == 1) {
374 const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
375 if (mime.isValid())
376 return mime;
377 candidatesByName = {};
378 }
379
380 // Extension is unknown, or matches multiple mimetypes.
381 // Pass 2) Match on content, if we can read the data
382 const auto matchOnContent = [this, &candidatesByName](QIODevice *device) {
383 const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
384 if (device->isOpen()) {
385 // Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
386 // This is much faster than seeking back and forth into QIODevice.
387 const QByteArray data = device->peek(16384);
388
389 if (openedByUs)
390 device->close();
391
392 int magicAccuracy = 0;
393 QMimeType candidateByData(findByData(data, &magicAccuracy));
394
395 // Disambiguate conflicting extensions (if magic matching found something)
396 if (candidateByData.isValid() && magicAccuracy > 0) {
397 const QString sniffedMime = candidateByData.name();
398 // If the sniffedMime matches a highest-weight glob match, use it
399 if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) {
400 return candidateByData;
401 }
402 for (const QString &m : std::as_const(candidatesByName.m_allMatchingMimeTypes)) {
403 if (inherits(m, sniffedMime)) {
404 // We have magic + pattern pointing to this, so it's a pretty good match
405 return mimeTypeForName(m);
406 }
407 }
408 if (candidatesByName.m_allMatchingMimeTypes.isEmpty()) {
409 // No glob, use magic
410 return candidateByData;
411 }
412 }
413 }
414
415 if (candidatesByName.m_allMatchingMimeTypes.size() > 1) {
416 candidatesByName.m_matchingMimeTypes.sort(); // make it deterministic
417 const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
418 if (mime.isValid())
419 return mime;
420 }
421
423 };
424
425 if (device)
426 return matchOnContent(device);
427
428 QFile fallbackFile(fileName);
429 return matchOnContent(&fallbackFile);
430}
431
433{
435 if (matches.isEmpty()) {
437 } else {
438 // We have to pick one in case of multiple matches.
439 return mimeTypeForName(matches.first());
440 }
441}
442
444{
445 int accuracy = 0;
446 const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);
447 if (device->isOpen()) {
448 // Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
449 // This is much faster than seeking back and forth into QIODevice.
450 const QByteArray data = device->peek(16384);
451 QMimeType result = findByData(data, &accuracy);
452 if (openedByUs)
453 device->close();
454 return result;
455 }
457}
458
460 const QFileInfo &fileInfo,
462{
463 if (false) {
464#ifdef Q_OS_UNIX
465 } else if (fileInfo.isNativePath()) {
466 // If this is a local file, we'll want to do a stat() ourselves so we can
467 // detect additional inode types. In addition we want to follow symlinks.
468 const QByteArray nativeFilePath = QFile::encodeName(fileName);
469 QT_STATBUF statBuffer;
470 if (QT_STAT(nativeFilePath.constData(), &statBuffer) == 0) {
471 if (S_ISDIR(statBuffer.st_mode))
473 if (S_ISCHR(statBuffer.st_mode))
474 return mimeTypeForName(QStringLiteral("inode/chardevice"));
475 if (S_ISBLK(statBuffer.st_mode))
476 return mimeTypeForName(QStringLiteral("inode/blockdevice"));
477 if (S_ISFIFO(statBuffer.st_mode))
478 return mimeTypeForName(QStringLiteral("inode/fifo"));
479 if (S_ISSOCK(statBuffer.st_mode))
480 return mimeTypeForName(QStringLiteral("inode/socket"));
481 }
482#endif
483 } else if (fileInfo.isDir()) {
485 }
486
487 switch (mode) {
489 break;
494 return mimeTypeForData(&file);
495 }
496 }
497 // MatchDefault:
498 return mimeTypeForFileNameAndData(fileName, nullptr);
499}
500
502{
504 for (const auto &provider : providers())
505 provider->addAllMimeTypes(result);
506 return result;
507}
508
510{
511 const QString resolvedParent = resolveAlias(parent);
512 std::stack<QString, QStringList> toCheck;
513 toCheck.push(mime);
514 while (!toCheck.empty()) {
515 if (toCheck.top() == resolvedParent)
516 return true;
517 const QString mimeName = toCheck.top();
518 toCheck.pop();
519 const auto parentList = parents(mimeName);
520 for (const QString &par : parentList)
521 toCheck.push(resolveAlias(par));
522 }
523 return false;
524}
525
576 d(staticQMimeDatabase())
577{
578}
579
585{
586 d = nullptr;
587}
588
594{
595 QMutexLocker locker(&d->mutex);
596
597 return d->mimeTypeForName(nameOrAlias);
598}
599
629{
630 QMutexLocker locker(&d->mutex);
631
632 return d->mimeTypeForFile(fileInfo.filePath(), fileInfo, mode);
633}
634
641{
642 QMutexLocker locker(&d->mutex);
643
644 if (mode == MatchExtension) {
646 } else {
647 QFileInfo fileInfo(fileName);
648 return d->mimeTypeForFile(fileName, fileInfo, mode);
649 }
650}
651
665{
666 QMutexLocker locker(&d->mutex);
667
669 QList<QMimeType> mimes;
670 mimes.reserve(matches.size());
671 for (const QString &mime : matches)
672 mimes.append(d->mimeTypeForName(mime));
673 return mimes;
674}
682{
683 QMutexLocker locker(&d->mutex);
684 const qsizetype suffixLength = d->findByFileName(fileName).m_knownSuffixLength;
685 return fileName.right(suffixLength);
686}
687
696{
697 QMutexLocker locker(&d->mutex);
698
699 int accuracy = 0;
700 return d->findByData(data, &accuracy);
701}
702
711{
712 QMutexLocker locker(&d->mutex);
713
714 return d->mimeTypeForData(device);
715}
716
732{
733 if (url.isLocalFile())
735
736 const QString scheme = url.scheme();
737 if (scheme.startsWith("http"_L1) || scheme == "mailto"_L1)
738 return mimeTypeForName(d->defaultMimeType());
739
741}
742
763{
764 QMutexLocker locker(&d->mutex);
765
766 if (fileName.endsWith(u'/'))
768
770 return result;
771}
772
790{
791 QMutexLocker locker(&d->mutex);
792
793 if (fileName.endsWith(u'/'))
795
796 QBuffer buffer(const_cast<QByteArray *>(&data));
799}
800
809{
810 QMutexLocker locker(&d->mutex);
811
812 return d->allMimeTypes();
813}
814
IOBluetoothDevice * device
\inmodule QtCore \reentrant
Definition qbuffer.h:16
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
qint64 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
void start() noexcept
Starts this timer.
bool isValid() const noexcept
Returns false if the timer has never been started or invalidated by a call to invalidate().
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
bool isNativePath() const
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
QString filePath() const
Returns the file name, including the path (which may be absolute or relative).
bool exists() const
Returns true if the file exists; otherwise returns false.
Q_AUTOTEST_EXPORT QString fileName() const
\inmodule QtCore
Definition qfile.h:93
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
\inmodule QtCore \reentrant
Definition qiodevice.h:34
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
QString resolveAlias(const QString &nameOrAlias)
QStringList listAliases(const QString &mimeName)
QList< QMimeType > allMimeTypes()
bool mimeInherits(const QString &mime, const QString &parent)
QMimeType mimeTypeForFileExtension(const QString &fileName)
QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device)
void loadIcon(QMimeTypePrivate &mimePrivate)
QMimeType mimeTypeForData(QIODevice *device)
QStringList mimeTypeForFileName(const QString &fileName)
bool inherits(const QString &mime, const QString &parent)
QMimeType mimeTypeForName(const QString &nameOrAlias)
void loadGenericIcon(QMimeTypePrivate &mimePrivate)
QStringList mimeParents(const QString &mimeName)
const QString & defaultMimeType() const
void loadMimeTypePrivate(QMimeTypePrivate &mimePrivate)
QMimeType mimeTypeForFile(const QString &fileName, const QFileInfo &fileInfo, QMimeDatabase::MatchMode mode)
QStringList parents(const QString &mimeName)
QMimeGlobMatchResult findByFileName(const QString &fileName)
QMimeType findByData(const QByteArray &data, int *priorityPtr)
QMimeType mimeTypeForName(const QString &nameOrAlias) const
Returns a MIME type for nameOrAlias or an invalid one if none found.
~QMimeDatabase()
Destroys the QMimeDatabase object.
QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const
Returns a MIME type for the given fileName and device data.
QList< QMimeType > mimeTypesForFileName(const QString &fileName) const
Returns the MIME types for the file name fileName.
QMimeDatabase()
Constructs a QMimeDatabase object.
QMimeType mimeTypeForUrl(const QUrl &url) const
Returns a MIME type for url.
QMimeType mimeTypeForData(const QByteArray &data) const
Returns a MIME type for data.
QString suffixForFileName(const QString &fileName) const
Returns the suffix for the file fileName, as known by the MIME database.
MatchMode
This enum specifies how matching a file to a MIME type is performed.
QList< QMimeType > allMimeTypes() const
Returns the list of all available MIME types.
QMimeType mimeTypeForFile(const QString &fileName, MatchMode mode=MatchDefault) const
Returns a MIME type for the file named fileName using mode.
QString genericIconName
Definition qmimetype_p.h:45
\inmodule QtCore
Definition qmimetype.h:25
bool isValid() const
QString name
the name of the MIME type
Definition qmimetype.h:29
\inmodule QtCore
Definition qmutex.h:317
bool tryLock(int timeout=0) noexcept
Attempts to lock the mutex.
Definition qmutex.h:291
iterator end()
Definition qset.h:140
static QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options=LocateFile)
[0]
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
\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
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
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
\inmodule QtCore
Definition qurl.h:94
bool isLocalFile() const
Definition qurl.cpp:3431
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1983
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3411
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2465
double e
const auto predicate
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qWarning
Definition qlogging.h:162
return ret
static Q_CONSTINIT const int qmime_secondsBetweenChecks
static bool isTextFile(const QByteArray &data)
static QStringList locateMimeDirectories()
static QString directoryMimeType()
static QString plainTextMimeType()
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
static bool matches(const QJsonObject &object, const QString &osName, const QVersionNumber &kernelVersion, const QString &osRelease, const QOpenGLConfig::Gpu &gpu)
Definition qopengl.cpp:270
GLenum mode
const GLfloat * m
GLuint GLuint end
GLenum GLuint buffer
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
ptrdiff_t qsizetype
Definition qtypes.h:70
QList< int > list
[14]
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
application x qt windows mime
[2]
The QMimeGlobMatchResult class accumulates results from glob matching.
QStringList m_allMatchingMimeTypes
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent