summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/mimetypes/mimetypes.qrc2
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp193
-rw-r--r--src/corelib/mimetypes/qmimedatabase_p.h13
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern.cpp5
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern_p.h2
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp461
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h51
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp7
-rw-r--r--src/corelib/mimetypes/qmimetype_p.h3
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp1
10 files changed, 391 insertions, 347 deletions
diff --git a/src/corelib/mimetypes/mimetypes.qrc b/src/corelib/mimetypes/mimetypes.qrc
index f0cf47cd49..19bc1d3e2a 100644
--- a/src/corelib/mimetypes/mimetypes.qrc
+++ b/src/corelib/mimetypes/mimetypes.qrc
@@ -1,5 +1,5 @@
<RCC>
- <qresource prefix="/qt-project.org/qmime">
+ <qresource prefix="/qt-project.org/qmime/packages">
<file alias="freedesktop.org.xml">mime/packages/freedesktop.org.xml</file>
</qresource>
</RCC>
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index 38b940d6db..864e9edc61 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -51,6 +51,7 @@
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QSet>
+#include <QtCore/QStandardPaths>
#include <QtCore/QBuffer>
#include <QtCore/QUrl>
#include <QtCore/QDebug>
@@ -69,14 +70,13 @@ QMimeDatabasePrivate *QMimeDatabasePrivate::instance()
}
QMimeDatabasePrivate::QMimeDatabasePrivate()
- : m_provider(0), m_defaultMimeType(QLatin1String("application/octet-stream"))
+ : m_defaultMimeType(QLatin1String("application/octet-stream"))
{
}
QMimeDatabasePrivate::~QMimeDatabasePrivate()
{
- delete m_provider;
- m_provider = 0;
+ qDeleteAll(m_providers);
}
Q_CORE_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test
@@ -89,24 +89,80 @@ bool QMimeDatabasePrivate::shouldCheck()
return true;
}
-QMimeProviderBase *QMimeDatabasePrivate::provider()
-{
- Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex
- if (!m_provider) {
- QMimeProviderBase *binaryProvider = new QMimeBinaryProvider(this);
- if (binaryProvider->isValid()) {
- m_provider = binaryProvider;
+#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
+#define QT_USE_MMAP
+#endif
+
+void QMimeDatabasePrivate::loadProviders()
+{
+ // We use QStandardPaths every time to check if new files appeared
+ QStringList mimeDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory);
+ const auto fdoIterator = std::find_if(mimeDirs.constBegin(), mimeDirs.constEnd(), [](const QString &mimeDir) -> bool {
+ return QFileInfo::exists(mimeDir + QStringLiteral("/packages/freedesktop.org.xml")); }
+ );
+ if (fdoIterator == mimeDirs.constEnd())
+ mimeDirs.prepend(QLatin1String(":/qt-project.org/qmime"));
+ //qDebug() << "mime dirs:" << mimeDirs;
+
+ m_providers.reserve(mimeDirs.size());
+ for (const QString &mimeDir : qAsConst(mimeDirs)) {
+ const QString cacheFile = mimeDir + QStringLiteral("/mime.cache");
+ QFileInfo fileInfo(cacheFile);
+ // Check if we already have a provider for this dir
+ // [This could be optimized by keeping a copy of mimeDirs and comparing the stringlists]
+ const auto it = std::find_if(m_providers.begin(), m_providers.end(), [mimeDir](QMimeProviderBase *prov) { return prov->directory() == mimeDir; });
+ if (it == m_providers.end()) {
+ QMimeProviderBase *provider = nullptr;
+#if defined(QT_USE_MMAP)
+ if (qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE") && fileInfo.exists()) {
+ provider = new QMimeBinaryProvider(this, mimeDir);
+ //qDebug() << "Created binary provider for" << mimeDir;
+ if (!provider->isValid()) {
+ delete provider;
+ provider = nullptr;
+ }
+ }
+#endif
+ if (!provider) {
+ provider = new QMimeXMLProvider(this, mimeDir);
+ //qDebug() << "Created XML provider for" << mimeDir;
+ }
+ m_providers.append(provider);
} else {
- delete binaryProvider;
- m_provider = new QMimeXMLProvider(this);
+ QMimeProviderBase *provider = *it;
+ provider->ensureLoaded();
+ if (!provider->isValid()) {
+ delete provider;
+ provider = new QMimeXMLProvider(this, mimeDir);
+ //qDebug() << "Created XML provider to replace binary provider for" << mimeDir;
+ *it = provider;
+ }
}
- m_provider->ensureLoaded();
+ }
+}
+
+QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers()
+{
+ Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex
+ if (m_providers.isEmpty()) {
+ loadProviders();
m_lastCheck.start();
} else {
if (shouldCheck())
- m_provider->ensureLoaded();
+ loadProviders();
+ }
+ return m_providers;
+}
+
+QString QMimeDatabasePrivate::resolveAlias(const QString &nameOrAlias)
+{
+ const auto allProviders = providers();
+ for (QMimeProviderBase *provider : allProviders) {
+ const QString ret = provider->resolveAlias(nameOrAlias);
+ if (!ret.isEmpty())
+ return ret;
}
- return m_provider;
+ return nameOrAlias;
}
/*!
@@ -115,7 +171,14 @@ QMimeProviderBase *QMimeDatabasePrivate::provider()
*/
QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)
{
- return provider()->mimeTypeForName(provider()->resolveAlias(nameOrAlias));
+ const auto allProviders = providers();
+ const QString mimeName = resolveAlias(nameOrAlias);
+ for (QMimeProviderBase *provider : allProviders) {
+ const QMimeType mime = provider->mimeTypeForName(mimeName);
+ if (mime.isValid())
+ return mime;
+ }
+ return {};
}
QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName)
@@ -123,44 +186,105 @@ QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName)
if (fileName.endsWith(QLatin1Char('/')))
return QStringList() << QLatin1String("inode/directory");
- QStringList matchingMimeTypes = provider()->findByFileName(QFileInfo(fileName).fileName()).m_matchingMimeTypes;
+ const QString shortName = QFileInfo(fileName).fileName();
+ const QMimeGlobMatchResult result = findByFileName(shortName);
+ QStringList matchingMimeTypes = result.m_matchingMimeTypes;
matchingMimeTypes.sort(); // make it deterministic
return matchingMimeTypes;
}
QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileName)
{
- return provider()->findByFileName(fileName);
+ QMimeGlobMatchResult result;
+ // TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
+ const auto allProviders = providers();
+ for (QMimeProviderBase *provider : allProviders)
+ provider->addFileNameMatches(fileName, result);
+ return result;
}
void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate)
{
QMutexLocker locker(&mutex);
- provider()->loadMimeTypePrivate(mimePrivate);
+ if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand
+ Q_ASSERT(mimePrivate.fromCache);
+ QMimeBinaryProvider::loadMimeTypePrivate(mimePrivate);
+ }
}
void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate)
{
QMutexLocker locker(&mutex);
- provider()->loadGenericIcon(mimePrivate);
+ if (mimePrivate.fromCache) {
+ mimePrivate.genericIconName.clear();
+ const auto allProviders = providers();
+ for (QMimeProviderBase *provider : allProviders) {
+ provider->loadGenericIcon(mimePrivate);
+ if (!mimePrivate.genericIconName.isEmpty())
+ break;
+ }
+ }
}
void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate)
{
QMutexLocker locker(&mutex);
- provider()->loadIcon(mimePrivate);
+ if (mimePrivate.fromCache) {
+ mimePrivate.iconName.clear();
+ const auto allProviders = providers();
+ for (QMimeProviderBase *provider : allProviders) {
+ provider->loadIcon(mimePrivate);
+ if (!mimePrivate.iconName.isEmpty())
+ break;
+ }
+ }
}
-QStringList QMimeDatabasePrivate::parents(const QString &mimeName)
+static QString fallbackParent(const QString &mimeTypeName)
+{
+ const QStringRef myGroup = mimeTypeName.leftRef(mimeTypeName.indexOf(QLatin1Char('/')));
+ // All text/* types are subclasses of text/plain.
+ if (myGroup == QLatin1String("text") && mimeTypeName != QLatin1String("text/plain"))
+ return QLatin1String("text/plain");
+ // All real-file mimetypes implicitly derive from application/octet-stream
+ if (myGroup != QLatin1String("inode") &&
+ // ignore non-file extensions
+ myGroup != QLatin1String("all") && myGroup != QLatin1String("fonts") && myGroup != QLatin1String("print") && myGroup != QLatin1String("uri")
+ && mimeTypeName != QLatin1String("application/octet-stream")) {
+ return QLatin1String("application/octet-stream");
+ }
+ return QString();
+}
+
+QStringList QMimeDatabasePrivate::mimeParents(const QString &mimeName)
{
QMutexLocker locker(&mutex);
- return provider()->parents(mimeName);
+ return parents(mimeName);
+}
+
+QStringList QMimeDatabasePrivate::parents(const QString &mimeName)
+{
+ Q_ASSERT(!mutex.tryLock());
+ QStringList result;
+ const auto allProviders = providers();
+ for (QMimeProviderBase *provider : allProviders)
+ provider->addParents(mimeName, result);
+ if (result.isEmpty()) {
+ const QString parent = fallbackParent(mimeName);
+ if (!parent.isEmpty())
+ result.append(parent);
+ }
+ return result;
}
QStringList QMimeDatabasePrivate::listAliases(const QString &mimeName)
{
QMutexLocker locker(&mutex);
- return provider()->listAliases(mimeName);
+ QStringList result;
+ const auto allProviders = providers();
+ for (QMimeProviderBase *provider : allProviders)
+ provider->addAliases(mimeName, result);
+ return result;
}
bool QMimeDatabasePrivate::mimeInherits(const QString &mime, const QString &parent)
@@ -196,7 +320,10 @@ QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracy
}
*accuracyPtr = 0;
- QMimeType candidate = provider()->findByMagic(data, accuracyPtr);
+ QMimeType candidate;
+ const auto allProviders = providers();
+ for (QMimeProviderBase *provider : allProviders)
+ provider->findByMagic(data, accuracyPtr, candidate);
if (candidate.isValid())
return candidate;
@@ -223,7 +350,7 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
if (fileName.endsWith(QLatin1Char('/')))
candidatesByName.addMatch(QLatin1String("inode/directory"), 100, QString());
else
- candidatesByName = provider()->findByFileName(QFileInfo(fileName).fileName());
+ candidatesByName = findByFileName(QFileInfo(fileName).fileName());
if (candidatesByName.m_allMatchingMimeTypes.count() == 1) {
*accuracyPtr = 100;
const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
@@ -273,21 +400,25 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
QList<QMimeType> QMimeDatabasePrivate::allMimeTypes()
{
- return provider()->allMimeTypes();
+ QList<QMimeType> result;
+ const auto allProviders = providers();
+ for (QMimeProviderBase *provider : allProviders)
+ provider->addAllMimeTypes(result);
+ return result;
}
bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
{
- const QString resolvedParent = provider()->resolveAlias(parent);
- //Q_ASSERT(provider()->resolveAlias(mime) == mime);
+ const QString resolvedParent = resolveAlias(parent);
std::stack<QString, QStringList> toCheck;
toCheck.push(mime);
while (!toCheck.empty()) {
if (toCheck.top() == resolvedParent)
return true;
- const auto parents = provider()->parents(toCheck.top());
+ const QString mimeName = toCheck.top();
toCheck.pop();
- for (const QString &par : parents)
+ const auto parentList = parents(mimeName);
+ for (const QString &par : parentList)
toCheck.push(par);
}
return false;
diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h
index 93bdd24b6f..1c38f46115 100644
--- a/src/corelib/mimetypes/qmimedatabase_p.h
+++ b/src/corelib/mimetypes/qmimedatabase_p.h
@@ -59,8 +59,9 @@
#include "qmimetype_p.h"
#include "qmimeglobpattern_p.h"
-#include <QtCore/qmutex.h>
#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
@@ -84,7 +85,8 @@ public:
QList<QMimeType> allMimeTypes();
-
+ QString resolveAlias(const QString &nameOrAlias);
+ QStringList parents(const QString &mimeName);
QMimeType mimeTypeForName(const QString &nameOrAlias);
QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr);
QMimeType findByData(const QByteArray &data, int *priorityPtr);
@@ -95,15 +97,16 @@ public:
void loadMimeTypePrivate(QMimeTypePrivate &mimePrivate);
void loadGenericIcon(QMimeTypePrivate &mimePrivate);
void loadIcon(QMimeTypePrivate &mimePrivate);
- QStringList parents(const QString &mimeName);
+ QStringList mimeParents(const QString &mimeName);
QStringList listAliases(const QString &mimeName);
bool mimeInherits(const QString &mime, const QString &parent);
private:
- QMimeProviderBase *provider();
+ QVector<QMimeProviderBase *> providers();
bool shouldCheck();
+ void loadProviders();
- mutable QMimeProviderBase *m_provider;
+ mutable QVector<QMimeProviderBase *> m_providers;
QElapsedTimer m_lastCheck;
public:
diff --git a/src/corelib/mimetypes/qmimeglobpattern.cpp b/src/corelib/mimetypes/qmimeglobpattern.cpp
index a4d2b046fa..e7b2b879a1 100644
--- a/src/corelib/mimetypes/qmimeglobpattern.cpp
+++ b/src/corelib/mimetypes/qmimeglobpattern.cpp
@@ -206,10 +206,9 @@ void QMimeGlobPatternList::match(QMimeGlobMatchResult &result,
}
}
-QMimeGlobMatchResult QMimeAllGlobPatterns::matchingGlobs(const QString &fileName) const
+void QMimeAllGlobPatterns::matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result) const
{
// First try the high weight matches (>50), if any.
- QMimeGlobMatchResult result;
m_highWeightGlobs.match(result, fileName);
// Now use the "fast patterns" dict, for simple *.foo patterns with weight 50
@@ -230,8 +229,6 @@ QMimeGlobMatchResult QMimeAllGlobPatterns::matchingGlobs(const QString &fileName
// Finally, try the low weight matches (<=50)
m_lowWeightGlobs.match(result, fileName);
-
- return result;
}
void QMimeAllGlobPatterns::clear()
diff --git a/src/corelib/mimetypes/qmimeglobpattern_p.h b/src/corelib/mimetypes/qmimeglobpattern_p.h
index 21332e71bc..103729c4ff 100644
--- a/src/corelib/mimetypes/qmimeglobpattern_p.h
+++ b/src/corelib/mimetypes/qmimeglobpattern_p.h
@@ -152,7 +152,7 @@ public:
void addGlob(const QMimeGlobPattern &glob);
void removeMimeType(const QString &mimeType);
- QMimeGlobMatchResult matchingGlobs(const QString &fileName) const;
+ void matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result) const;
void clear();
PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain"
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index cd9a2768ee..ec0a6bf0ef 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -61,37 +61,18 @@ static void initResources()
QT_BEGIN_NAMESPACE
-static QString fallbackParent(const QString &mimeTypeName)
-{
- const QStringRef myGroup = mimeTypeName.leftRef(mimeTypeName.indexOf(QLatin1Char('/')));
- // All text/* types are subclasses of text/plain.
- if (myGroup == QLatin1String("text") && mimeTypeName != QLatin1String("text/plain"))
- return QLatin1String("text/plain");
- // All real-file mimetypes implicitly derive from application/octet-stream
- if (myGroup != QLatin1String("inode") &&
- // ignore non-file extensions
- myGroup != QLatin1String("all") && myGroup != QLatin1String("fonts") && myGroup != QLatin1String("print") && myGroup != QLatin1String("uri")
- && mimeTypeName != QLatin1String("application/octet-stream")) {
- return QLatin1String("application/octet-stream");
- }
- return QString();
-}
-
-QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db)
- : m_db(db)
+QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory)
+ : m_db(db), m_directory(directory)
{
}
-QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db)
- : QMimeProviderBase(db), m_mimetypeListLoaded(false)
+QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory)
+ : QMimeProviderBase(db, directory), m_mimetypeListLoaded(false)
{
+ ensureLoaded();
}
-#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
-#define QT_USE_MMAP
-#endif
-
struct QMimeBinaryProvider::CacheFile
{
CacheFile(const QString &fileName);
@@ -145,7 +126,6 @@ bool QMimeBinaryProvider::CacheFile::load()
bool QMimeBinaryProvider::CacheFile::reload()
{
- //qDebug() << "reload!" << file->fileName();
m_valid = false;
if (file.isOpen()) {
file.close();
@@ -154,18 +134,14 @@ bool QMimeBinaryProvider::CacheFile::reload()
return load();
}
-QMimeBinaryProvider::CacheFile *QMimeBinaryProvider::CacheFileList::findCacheFile(const QString &fileName) const
+QMimeBinaryProvider::~QMimeBinaryProvider()
{
- for (const_iterator it = begin(); it != end(); ++it) {
- if ((*it)->file.fileName() == fileName)
- return *it;
- }
- return 0;
+ delete m_cacheFile;
}
-QMimeBinaryProvider::~QMimeBinaryProvider()
+bool QMimeBinaryProvider::isValid()
{
- qDeleteAll(m_cacheFiles);
+ return m_cacheFile != nullptr;
}
// Position of the "list offsets" values, at the beginning of the mime.cache file
@@ -181,76 +157,33 @@ enum {
PosGenericIconsListOffset = 36
};
-bool QMimeBinaryProvider::isValid()
+bool QMimeBinaryProvider::checkCacheChanged()
{
-#if defined(QT_USE_MMAP)
- if (!qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE"))
- return false;
-
- Q_ASSERT(m_cacheFiles.isEmpty()); // this method is only ever called once
- ensureLoaded();
-
- if (m_cacheFiles.count() > 1)
+ QFileInfo fileInfo(m_cacheFile->file);
+ if (fileInfo.lastModified() > m_cacheFile->m_mtime) {
+ // Deletion can't happen by just running update-mime-database.
+ // But the user could use rm -rf :-)
+ m_cacheFile->reload(); // will mark itself as invalid on failure
return true;
- if (m_cacheFiles.isEmpty())
- return false;
-
- // We found exactly one file; is it the user-modified mimes, or a system file?
- const QString foundFile = m_cacheFiles.constFirst()->file.fileName();
- const QString localCacheFile = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/mime/mime.cache");
-
- return foundFile != localCacheFile;
-#else
- return false;
-#endif
-}
-
-bool QMimeBinaryProvider::CacheFileList::checkCacheChanged()
-{
- bool somethingChanged = false;
- for (CacheFile *cacheFile : qAsConst(*this)) {
- QFileInfo fileInfo(cacheFile->file);
- if (!fileInfo.exists() || fileInfo.lastModified() > cacheFile->m_mtime) {
- // Deletion can't happen by just running update-mime-database.
- // But the user could use rm -rf :-)
- cacheFile->reload(); // will mark itself as invalid on failure
- somethingChanged = true;
- }
}
- if (somethingChanged) {
- auto deleteIfNoLongerValid = [](CacheFile *cacheFile) -> bool {
- const bool invalid = !cacheFile->isValid();
- if (invalid)
- delete cacheFile;
- return invalid;
- };
- erase(std::remove_if(begin(), end(), deleteIfNoLongerValid), end());
- }
- return somethingChanged;
+ return false;
}
void QMimeBinaryProvider::ensureLoaded()
{
- // First iterate over existing known cache files and check for uptodate
- if (m_cacheFiles.checkCacheChanged())
- m_mimetypeListLoaded = false;
-
- // Then check if new cache files appeared
- const QStringList cacheFileNames = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/mime.cache"));
- if (cacheFileNames != m_cacheFileNames) {
- for (const QString &cacheFileName : cacheFileNames) {
- CacheFile *cacheFile = m_cacheFiles.findCacheFile(cacheFileName);
- if (!cacheFile) {
- //qDebug() << "new file:" << cacheFileName;
- cacheFile = new CacheFile(cacheFileName);
- if (cacheFile->isValid()) // verify version
- m_cacheFiles.append(cacheFile);
- else
- delete cacheFile;
- }
- }
- m_cacheFileNames = cacheFileNames;
+ if (!m_cacheFile) {
+ const QString cacheFileName = m_directory + QLatin1String("/mime.cache");
+ m_cacheFile = new CacheFile(cacheFileName);
m_mimetypeListLoaded = false;
+ } else {
+ if (checkCacheChanged())
+ m_mimetypeListLoaded = false;
+ else
+ return; // nothing to do
+ }
+ if (!m_cacheFile->isValid()) { // verify existence and version
+ delete m_cacheFile;
+ m_cacheFile = nullptr;
}
}
@@ -258,6 +191,7 @@ static QMimeType mimeTypeForNameUnchecked(const QString &name)
{
QMimeTypePrivate data;
data.name = name;
+ data.fromCache = true;
// The rest is retrieved on demand.
// comment and globPatterns: in loadMimeTypePrivate
// iconName: in loadIcon
@@ -274,27 +208,23 @@ QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name)
return mimeTypeForNameUnchecked(name);
}
-QMimeGlobMatchResult QMimeBinaryProvider::findByFileName(const QString &fileName)
+void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
{
- QMimeGlobMatchResult result;
if (fileName.isEmpty())
- return result;
+ return;
+ Q_ASSERT(m_cacheFile);
const QString lowerFileName = fileName.toLower();
- // TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
- for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- // Check literals (e.g. "Makefile")
- matchGlobList(result, cacheFile, cacheFile->getUint32(PosLiteralListOffset), fileName);
- // Check complex globs (e.g. "callgrind.out[0-9]*")
- matchGlobList(result, cacheFile, cacheFile->getUint32(PosGlobListOffset), fileName);
- // Check the very common *.txt cases with the suffix tree
- const int reverseSuffixTreeOffset = cacheFile->getUint32(PosReverseSuffixTreeOffset);
- const int numRoots = cacheFile->getUint32(reverseSuffixTreeOffset);
- const int firstRootOffset = cacheFile->getUint32(reverseSuffixTreeOffset + 4);
- matchSuffixTree(result, cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false);
- if (result.m_matchingMimeTypes.isEmpty())
- matchSuffixTree(result, cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
- }
- return result;
+ // Check literals (e.g. "Makefile")
+ matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), fileName);
+ // Check complex globs (e.g. "callgrind.out[0-9]*")
+ matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName);
+ // Check the very common *.txt cases with the suffix tree
+ const int reverseSuffixTreeOffset = m_cacheFile->getUint32(PosReverseSuffixTreeOffset);
+ const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
+ const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
+ matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, lowerFileName, lowerFileName.length() - 1, false);
+ if (result.m_matchingMimeTypes.isEmpty())
+ matchSuffixTree(result, m_cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
}
void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName)
@@ -392,120 +322,106 @@ bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFi
return false;
}
-QMimeType QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
-{
- for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const int magicListOffset = cacheFile->getUint32(PosMagicListOffset);
- const int numMatches = cacheFile->getUint32(magicListOffset);
- //const int maxExtent = cacheFile->getUint32(magicListOffset + 4);
- const int firstMatchOffset = cacheFile->getUint32(magicListOffset + 8);
-
- for (int i = 0; i < numMatches; ++i) {
- const int off = firstMatchOffset + i * 16;
- const int numMatchlets = cacheFile->getUint32(off + 8);
- const int firstMatchletOffset = cacheFile->getUint32(off + 12);
- if (matchMagicRule(cacheFile, numMatchlets, firstMatchletOffset, data)) {
- const int mimeTypeOffset = cacheFile->getUint32(off + 4);
- const char *mimeType = cacheFile->getCharStar(mimeTypeOffset);
- *accuracyPtr = cacheFile->getUint32(off);
- // Return the first match. We have no rules for conflicting magic data...
- // (mime.cache itself is sorted, but what about local overrides with a lower prio?)
- return mimeTypeForNameUnchecked(QLatin1String(mimeType));
- }
+void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate)
+{
+ const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset);
+ const int numMatches = m_cacheFile->getUint32(magicListOffset);
+ //const int maxExtent = cacheFile->getUint32(magicListOffset + 4);
+ const int firstMatchOffset = m_cacheFile->getUint32(magicListOffset + 8);
+
+ for (int i = 0; i < numMatches; ++i) {
+ const int off = firstMatchOffset + i * 16;
+ const int numMatchlets = m_cacheFile->getUint32(off + 8);
+ const int firstMatchletOffset = m_cacheFile->getUint32(off + 12);
+ if (matchMagicRule(m_cacheFile, numMatchlets, firstMatchletOffset, data)) {
+ const int mimeTypeOffset = m_cacheFile->getUint32(off + 4);
+ const char *mimeType = m_cacheFile->getCharStar(mimeTypeOffset);
+ *accuracyPtr = m_cacheFile->getUint32(off);
+ // Return the first match. We have no rules for conflicting magic data...
+ // (mime.cache itself is sorted, but what about local overrides with a lower prio?)
+ candidate = mimeTypeForNameUnchecked(QLatin1String(mimeType));
+ return;
}
}
- return QMimeType();
}
-QStringList QMimeBinaryProvider::parents(const QString &mime)
+void QMimeBinaryProvider::addParents(const QString &mime, QStringList &result)
{
const QByteArray mimeStr = mime.toLatin1();
- QStringList result;
- for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const int parentListOffset = cacheFile->getUint32(PosParentListOffset);
- const int numEntries = cacheFile->getUint32(parentListOffset);
-
- int begin = 0;
- int end = numEntries - 1;
- while (begin <= end) {
- const int medium = (begin + end) / 2;
- const int off = parentListOffset + 4 + 8 * medium;
- const int mimeOffset = cacheFile->getUint32(off);
- const char *aMime = cacheFile->getCharStar(mimeOffset);
- const int cmp = qstrcmp(aMime, mimeStr);
- if (cmp < 0) {
- begin = medium + 1;
- } else if (cmp > 0) {
- end = medium - 1;
- } else {
- const int parentsOffset = cacheFile->getUint32(off + 4);
- const int numParents = cacheFile->getUint32(parentsOffset);
- for (int i = 0; i < numParents; ++i) {
- const int parentOffset = cacheFile->getUint32(parentsOffset + 4 + 4 * i);
- const char *aParent = cacheFile->getCharStar(parentOffset);
- result.append(QString::fromLatin1(aParent));
- }
- break;
+ const int parentListOffset = m_cacheFile->getUint32(PosParentListOffset);
+ const int numEntries = m_cacheFile->getUint32(parentListOffset);
+
+ int begin = 0;
+ int end = numEntries - 1;
+ while (begin <= end) {
+ const int medium = (begin + end) / 2;
+ const int off = parentListOffset + 4 + 8 * medium;
+ const int mimeOffset = m_cacheFile->getUint32(off);
+ const char *aMime = m_cacheFile->getCharStar(mimeOffset);
+ const int cmp = qstrcmp(aMime, mimeStr);
+ if (cmp < 0) {
+ begin = medium + 1;
+ } else if (cmp > 0) {
+ end = medium - 1;
+ } else {
+ const int parentsOffset = m_cacheFile->getUint32(off + 4);
+ const int numParents = m_cacheFile->getUint32(parentsOffset);
+ for (int i = 0; i < numParents; ++i) {
+ const int parentOffset = m_cacheFile->getUint32(parentsOffset + 4 + 4 * i);
+ const char *aParent = m_cacheFile->getCharStar(parentOffset);
+ const QString strParent = QString::fromLatin1(aParent);
+ if (!result.contains(strParent))
+ result.append(strParent);
}
+ break;
}
}
- if (result.isEmpty()) {
- const QString parent = fallbackParent(mime);
- if (!parent.isEmpty())
- result.append(parent);
- }
- return result;
}
QString QMimeBinaryProvider::resolveAlias(const QString &name)
{
const QByteArray input = name.toLatin1();
- for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const int aliasListOffset = cacheFile->getUint32(PosAliasListOffset);
- const int numEntries = cacheFile->getUint32(aliasListOffset);
- int begin = 0;
- int end = numEntries - 1;
- while (begin <= end) {
- const int medium = (begin + end) / 2;
- const int off = aliasListOffset + 4 + 8 * medium;
- const int aliasOffset = cacheFile->getUint32(off);
- const char *alias = cacheFile->getCharStar(aliasOffset);
- const int cmp = qstrcmp(alias, input);
- if (cmp < 0) {
- begin = medium + 1;
- } else if (cmp > 0) {
- end = medium - 1;
- } else {
- const int mimeOffset = cacheFile->getUint32(off + 4);
- const char *mimeType = cacheFile->getCharStar(mimeOffset);
- return QLatin1String(mimeType);
- }
+ const int aliasListOffset = m_cacheFile->getUint32(PosAliasListOffset);
+ const int numEntries = m_cacheFile->getUint32(aliasListOffset);
+ int begin = 0;
+ int end = numEntries - 1;
+ while (begin <= end) {
+ const int medium = (begin + end) / 2;
+ const int off = aliasListOffset + 4 + 8 * medium;
+ const int aliasOffset = m_cacheFile->getUint32(off);
+ const char *alias = m_cacheFile->getCharStar(aliasOffset);
+ const int cmp = qstrcmp(alias, input);
+ if (cmp < 0) {
+ begin = medium + 1;
+ } else if (cmp > 0) {
+ end = medium - 1;
+ } else {
+ const int mimeOffset = m_cacheFile->getUint32(off + 4);
+ const char *mimeType = m_cacheFile->getCharStar(mimeOffset);
+ return QLatin1String(mimeType);
}
}
-
return name;
}
-QStringList QMimeBinaryProvider::listAliases(const QString &name)
+void QMimeBinaryProvider::addAliases(const QString &name, QStringList &result)
{
- QStringList result;
const QByteArray input = name.toLatin1();
- for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const int aliasListOffset = cacheFile->getUint32(PosAliasListOffset);
- const int numEntries = cacheFile->getUint32(aliasListOffset);
- for (int pos = 0; pos < numEntries; ++pos) {
- const int off = aliasListOffset + 4 + 8 * pos;
- const int mimeOffset = cacheFile->getUint32(off + 4);
- const char *mimeType = cacheFile->getCharStar(mimeOffset);
-
- if (input == mimeType) {
- const int aliasOffset = cacheFile->getUint32(off);
- const char *alias = cacheFile->getCharStar(aliasOffset);
- result.append(QString::fromLatin1(alias));
- }
+ const int aliasListOffset = m_cacheFile->getUint32(PosAliasListOffset);
+ const int numEntries = m_cacheFile->getUint32(aliasListOffset);
+ for (int pos = 0; pos < numEntries; ++pos) {
+ const int off = aliasListOffset + 4 + 8 * pos;
+ const int mimeOffset = m_cacheFile->getUint32(off + 4);
+ const char *mimeType = m_cacheFile->getCharStar(mimeOffset);
+
+ if (input == mimeType) {
+ const int aliasOffset = m_cacheFile->getUint32(off);
+ const char *alias = m_cacheFile->getCharStar(aliasOffset);
+ const QString strAlias = QString::fromLatin1(alias);
+ if (!result.contains(strAlias))
+ result.append(strAlias);
}
}
- return result;
}
void QMimeBinaryProvider::loadMimeTypeList()
@@ -515,31 +431,30 @@ void QMimeBinaryProvider::loadMimeTypeList()
m_mimetypeNames.clear();
// Unfortunately mime.cache doesn't have a full list of all mimetypes.
// So we have to parse the plain-text files called "types".
- const QStringList typesFilenames = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/types"));
- for (const QString &typeFilename : typesFilenames) {
- QFile file(typeFilename);
- if (file.open(QIODevice::ReadOnly)) {
- QTextStream stream(&file);
- stream.setCodec("ISO 8859-1");
- QString line;
- while (stream.readLineInto(&line))
- m_mimetypeNames.insert(line);
- }
+ QFile file(m_directory + QStringLiteral("/types"));
+ if (file.open(QIODevice::ReadOnly)) {
+ QTextStream stream(&file);
+ stream.setCodec("ISO 8859-1");
+ QString line;
+ while (stream.readLineInto(&line))
+ m_mimetypeNames.insert(line);
}
}
}
-QList<QMimeType> QMimeBinaryProvider::allMimeTypes()
+void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &result)
{
- QList<QMimeType> result;
loadMimeTypeList();
- result.reserve(m_mimetypeNames.count());
-
- for (QSet<QString>::const_iterator it = m_mimetypeNames.constBegin();
- it != m_mimetypeNames.constEnd(); ++it)
- result.append(mimeTypeForNameUnchecked(*it));
-
- return result;
+ if (result.isEmpty()) {
+ result.reserve(m_mimetypeNames.count());
+ for (const QString &name : m_mimetypeNames)
+ result.append(mimeTypeForNameUnchecked(name));
+ } else {
+ for (const QString &name : m_mimetypeNames)
+ if (std::find_if(result.constBegin(), result.constEnd(), [name](const QMimeType &mime) -> bool { return mime.name() == name; })
+ == result.constEnd())
+ result.append(mimeTypeForNameUnchecked(name));
+ }
}
void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
@@ -664,33 +579,28 @@ QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posList
void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
{
const QByteArray inputMime = data.name.toLatin1();
- for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const QLatin1String icon = iconForMime(cacheFile, PosIconsListOffset, inputMime);
- if (!icon.isEmpty()) {
- data.iconName = icon;
- return;
- }
+ const QLatin1String icon = iconForMime(m_cacheFile, PosIconsListOffset, inputMime);
+ if (!icon.isEmpty()) {
+ data.iconName = icon;
}
}
void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data)
{
const QByteArray inputMime = data.name.toLatin1();
- for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const QLatin1String icon = iconForMime(cacheFile, PosGenericIconsListOffset, inputMime);
- if (!icon.isEmpty()) {
- data.genericIconName = icon;
- return;
- }
+ const QLatin1String icon = iconForMime(m_cacheFile, PosGenericIconsListOffset, inputMime);
+ if (!icon.isEmpty()) {
+ data.genericIconName = icon;
}
}
////
-QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db)
- : QMimeProviderBase(db)
+QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory)
+ : QMimeProviderBase(db, directory)
{
initResources();
+ ensureLoaded();
}
QMimeXMLProvider::~QMimeXMLProvider()
@@ -699,6 +609,8 @@ QMimeXMLProvider::~QMimeXMLProvider()
bool QMimeXMLProvider::isValid()
{
+ // If you change this method, adjust the logic in QMimeDatabasePrivate::loadProviders,
+ // which assumes isValid==false is only possible in QMimeBinaryProvider.
return true;
}
@@ -707,50 +619,38 @@ QMimeType QMimeXMLProvider::mimeTypeForName(const QString &name)
return m_nameMimeTypeMap.value(name);
}
-QMimeGlobMatchResult QMimeXMLProvider::findByFileName(const QString &fileName)
+void QMimeXMLProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
{
- return m_mimeTypeGlobs.matchingGlobs(fileName);
+ m_mimeTypeGlobs.matchingGlobs(fileName, result);
}
-QMimeType QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
+void QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate)
{
- QString candidate;
-
+ QString candidateName;
+ bool foundOne = false;
for (const QMimeMagicRuleMatcher &matcher : qAsConst(m_magicMatchers)) {
if (matcher.matches(data)) {
const int priority = matcher.priority();
if (priority > *accuracyPtr) {
*accuracyPtr = priority;
- candidate = matcher.mimetype();
+ candidateName = matcher.mimetype();
+ foundOne = true;
}
}
}
- return mimeTypeForName(candidate);
+ if (foundOne)
+ candidate = mimeTypeForName(candidateName);
}
void QMimeXMLProvider::ensureLoaded()
{
- bool fdoXmlFound = false;
QStringList allFiles;
-
- const QStringList packageDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"), QStandardPaths::LocateDirectory);
- //qDebug() << "packageDirs=" << packageDirs;
- for (const QString &packageDir : packageDirs) {
- QDir dir(packageDir);
- const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
- //qDebug() << static_cast<const void *>(this) << packageDir << files;
- if (!fdoXmlFound)
- fdoXmlFound = files.contains(QLatin1String("freedesktop.org.xml"));
- QStringList::const_iterator endIt(files.constEnd());
- for (QStringList::const_iterator it(files.constBegin()); it != endIt; ++it) {
- allFiles.append(packageDir + QLatin1Char('/') + *it);
- }
- }
-
- if (!fdoXmlFound) {
- // We could instead install the file as part of installing Qt?
- allFiles.prepend(QLatin1String(":/qt-project.org/qmime/freedesktop.org.xml"));
- }
+ const QString packageDir = m_directory + QStringLiteral("/packages");
+ QDir dir(packageDir);
+ const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
+ allFiles.reserve(files.count());
+ for (const QString &xmlFile : files)
+ allFiles.append(packageDir + QLatin1Char('/') + xmlFile);
if (m_allFiles == allFiles)
return;
@@ -798,18 +698,16 @@ void QMimeXMLProvider::addGlobPattern(const QMimeGlobPattern &glob)
void QMimeXMLProvider::addMimeType(const QMimeType &mt)
{
+ Q_ASSERT(!mt.d.data()->fromCache);
m_nameMimeTypeMap.insert(mt.name(), mt);
}
-QStringList QMimeXMLProvider::parents(const QString &mime)
+void QMimeXMLProvider::addParents(const QString &mime, QStringList &result)
{
- QStringList result = m_parents.value(mime);
- if (result.isEmpty()) {
- const QString parent = fallbackParent(mime);
- if (!parent.isEmpty())
+ for (const QString &parent : m_parents.value(mime)) {
+ if (!result.contains(parent))
result.append(parent);
}
- return result;
}
void QMimeXMLProvider::addParent(const QString &child, const QString &parent)
@@ -817,10 +715,16 @@ void QMimeXMLProvider::addParent(const QString &child, const QString &parent)
m_parents[child].append(parent);
}
-QStringList QMimeXMLProvider::listAliases(const QString &name)
+void QMimeXMLProvider::addAliases(const QString &name, QStringList &result)
{
// Iterate through the whole hash. This method is rarely used.
- return m_aliases.keys(name);
+ for (auto it = m_aliases.constBegin(), end = m_aliases.constEnd() ; it != end ; ++it) {
+ if (it.value() == name) {
+ if (!result.contains(it.key()))
+ result.append(it.key());
+ }
+ }
+
}
QString QMimeXMLProvider::resolveAlias(const QString &name)
@@ -833,9 +737,18 @@ void QMimeXMLProvider::addAlias(const QString &alias, const QString &name)
m_aliases.insert(alias, name);
}
-QList<QMimeType> QMimeXMLProvider::allMimeTypes()
+void QMimeXMLProvider::addAllMimeTypes(QList<QMimeType> &result)
{
- return m_nameMimeTypeMap.values();
+ if (result.isEmpty()) { // fast path
+ result = m_nameMimeTypeMap.values();
+ } else {
+ for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd() ; it != end ; ++it) {
+ const QString newMime = it.key();
+ if (std::find_if(result.constBegin(), result.constEnd(), [newMime](const QMimeType &mime) -> bool { return mime.name() == newMime; })
+ == result.constEnd())
+ result.append(it.value());
+ }
+ }
}
void QMimeXMLProvider::addMagicMatcher(const QMimeMagicRuleMatcher &matcher)
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index 7344d8b453..b2be545cf8 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -67,23 +67,25 @@ class QMimeMagicRuleMatcher;
class QMimeProviderBase
{
public:
- QMimeProviderBase(QMimeDatabasePrivate *db);
+ QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory);
virtual ~QMimeProviderBase() {}
virtual bool isValid() = 0;
virtual QMimeType mimeTypeForName(const QString &name) = 0;
- virtual QMimeGlobMatchResult findByFileName(const QString &fileName) = 0;
- virtual QStringList parents(const QString &mime) = 0;
+ virtual void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) = 0;
+ virtual void addParents(const QString &mime, QStringList &result) = 0;
virtual QString resolveAlias(const QString &name) = 0;
- virtual QStringList listAliases(const QString &name) = 0;
- virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr) = 0;
- virtual QList<QMimeType> allMimeTypes() = 0;
- virtual void loadMimeTypePrivate(QMimeTypePrivate &) {}
+ virtual void addAliases(const QString &name, QStringList &result) = 0;
+ virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) = 0;
+ virtual void addAllMimeTypes(QList<QMimeType> &result) = 0;
virtual void loadIcon(QMimeTypePrivate &) {}
virtual void loadGenericIcon(QMimeTypePrivate &) {}
virtual void ensureLoaded() {}
+ QString directory() const { return m_directory; }
+
QMimeDatabasePrivate *m_db;
+ QString m_directory;
};
/*
@@ -92,18 +94,18 @@ public:
class QMimeBinaryProvider : public QMimeProviderBase
{
public:
- QMimeBinaryProvider(QMimeDatabasePrivate *db);
+ QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory);
virtual ~QMimeBinaryProvider();
virtual bool isValid() override;
virtual QMimeType mimeTypeForName(const QString &name) override;
- virtual QMimeGlobMatchResult findByFileName(const QString &fileName) override;
- virtual QStringList parents(const QString &mime) override;
+ void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override;
+ void addParents(const QString &mime, QStringList &result) override;
virtual QString resolveAlias(const QString &name) override;
- virtual QStringList listAliases(const QString &name) override;
- virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr) override;
- virtual QList<QMimeType> allMimeTypes() override;
- virtual void loadMimeTypePrivate(QMimeTypePrivate &) override;
+ void addAliases(const QString &name, QStringList &result) override;
+ void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override;
+ void addAllMimeTypes(QList<QMimeType> &result) override;
+ static void loadMimeTypePrivate(QMimeTypePrivate &);
virtual void loadIcon(QMimeTypePrivate &) override;
virtual void loadGenericIcon(QMimeTypePrivate &) override;
void ensureLoaded() override;
@@ -116,14 +118,9 @@ private:
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
QLatin1String iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
void loadMimeTypeList();
+ bool checkCacheChanged();
- class CacheFileList : public QList<CacheFile *>
- {
- public:
- CacheFile *findCacheFile(const QString &fileName) const;
- bool checkCacheChanged();
- };
- CacheFileList m_cacheFiles;
+ CacheFile *m_cacheFile = nullptr;
QStringList m_cacheFileNames;
QSet<QString> m_mimetypeNames;
bool m_mimetypeListLoaded;
@@ -135,17 +132,17 @@ private:
class QMimeXMLProvider : public QMimeProviderBase
{
public:
- QMimeXMLProvider(QMimeDatabasePrivate *db);
+ QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory);
~QMimeXMLProvider();
virtual bool isValid() override;
virtual QMimeType mimeTypeForName(const QString &name) override;
- virtual QMimeGlobMatchResult findByFileName(const QString &fileName) override;
- virtual QStringList parents(const QString &mime) override;
+ void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override;
+ void addParents(const QString &mime, QStringList &result) override;
virtual QString resolveAlias(const QString &name) override;
- virtual QStringList listAliases(const QString &name) override;
- virtual QMimeType findByMagic(const QByteArray &data, int *accuracyPtr) override;
- virtual QList<QMimeType> allMimeTypes() override;
+ void addAliases(const QString &name, QStringList &result) override;
+ void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override;
+ void addAllMimeTypes(QList<QMimeType> &result) override;
void ensureLoaded() override;
bool load(const QString &fileName, QString *errorMessage);
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 668b22e7cf..8f6237c1cb 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -57,7 +57,7 @@
QT_BEGIN_NAMESPACE
QMimeTypePrivate::QMimeTypePrivate()
- : loaded(false)
+ : loaded(false), fromCache(false)
{}
QMimeTypePrivate::QMimeTypePrivate(const QMimeType &other)
@@ -76,7 +76,6 @@ void QMimeTypePrivate::clear()
genericIconName.clear();
iconName.clear();
globPatterns.clear();
- loaded = false;
}
void QMimeTypePrivate::addGlobPattern(const QString &pattern)
@@ -368,12 +367,12 @@ QStringList QMimeType::globPatterns() const
*/
QStringList QMimeType::parentMimeTypes() const
{
- return QMimeDatabasePrivate::instance()->parents(d->name);
+ return QMimeDatabasePrivate::instance()->mimeParents(d->name);
}
static void collectParentMimeTypes(const QString &mime, QStringList &allParents)
{
- const QStringList parents = QMimeDatabasePrivate::instance()->parents(mime);
+ const QStringList parents = QMimeDatabasePrivate::instance()->mimeParents(mime);
for (const QString &parent : parents) {
// I would use QSet, but since order matters I better not
if (!allParents.contains(parent))
diff --git a/src/corelib/mimetypes/qmimetype_p.h b/src/corelib/mimetypes/qmimetype_p.h
index b0bfad2f65..aa38a1adf5 100644
--- a/src/corelib/mimetypes/qmimetype_p.h
+++ b/src/corelib/mimetypes/qmimetype_p.h
@@ -74,6 +74,7 @@ public:
void addGlobPattern(const QString &pattern);
bool loaded; // QSharedData leaves a 4 byte gap, so don't put 8 byte members first
+ bool fromCache; // true if this comes from the binary provider
QString name;
LocaleHash localeComments;
QString genericIconName;
@@ -94,6 +95,7 @@ QT_END_NAMESPACE
{ \
QMimeTypePrivate qMimeTypeData; \
qMimeTypeData.name = name; \
+ qMimeTypeData.loaded = true; \
qMimeTypeData.genericIconName = genericIconName; \
qMimeTypeData.iconName = iconName; \
qMimeTypeData.globPatterns = globPatterns; \
@@ -112,6 +114,7 @@ QT_END_NAMESPACE
) \
{ \
QMimeTypePrivate qMimeTypeData; \
+ qMimeTypeData.loaded = true; \
qMimeTypeData.name = std::move(name); \
qMimeTypeData.genericIconName = std::move(genericIconName); \
qMimeTypeData.iconName = std::move(iconName); \
diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp
index 5ecd339908..0a55560ab0 100644
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -201,6 +201,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
return false;
#else
QMimeTypePrivate data;
+ data.loaded = true;
int priority = 50;
QStack<QMimeMagicRule *> currentRules; // stack for the nesting of rules
QList<QMimeMagicRule> rules; // toplevel rules