summaryrefslogtreecommitdiffstats
path: root/src/corelib/mimetypes/qmimedatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/mimetypes/qmimedatabase.cpp')
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp165
1 files changed, 89 insertions, 76 deletions
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index 6d6b322229..d52ccacbe7 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -10,9 +10,9 @@
#include "qmimeprovider_p.h"
#include "qmimetype_p.h"
+#include <private/qduplicatetracker_p.h>
#include <private/qfilesystementry_p.h>
-#include <QtCore/QMap>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QStandardPaths>
@@ -74,7 +74,7 @@ static QStringList locateMimeDirectories()
return QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("mime"), QStandardPaths::LocateDirectory);
}
-#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
# define QT_USE_MMAP
#endif
@@ -142,6 +142,13 @@ void QMimeDatabasePrivate::loadProviders()
m_providers.push_back(std::move(*it));
}
}
+
+ auto it = m_providers.begin();
+ (*it)->setOverrideProvider(nullptr);
+ ++it;
+ const auto end = m_providers.end();
+ for (; it != end; ++it)
+ (*it)->setOverrideProvider((it - 1)->get());
}
const QMimeDatabasePrivate::Providers &QMimeDatabasePrivate::providers()
@@ -177,9 +184,8 @@ QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)
{
const QString mimeName = resolveAlias(nameOrAlias);
for (const auto &provider : providers()) {
- const QMimeType mime = provider->mimeTypeForName(mimeName);
- if (mime.isValid())
- return mime;
+ if (provider->knowsMimeType(mimeName))
+ return QMimeType(QMimeTypePrivate(mimeName));
}
return {};
}
@@ -204,54 +210,54 @@ QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileNam
return result;
}
-void QMimeDatabasePrivate::loadMimeTypePrivate(QMimeTypePrivate &mimePrivate)
+QMimeTypePrivate::LocaleHash QMimeDatabasePrivate::localeComments(const QString &name)
{
QMutexLocker locker(&mutex);
- if (mimePrivate.name.isEmpty())
- return; // invalid mimetype
- if (!mimePrivate.loaded) { // XML provider sets loaded=true, binary provider does this on demand
- Q_ASSERT(mimePrivate.fromCache);
- bool found = false;
- for (const auto &provider : providers()) {
- if (provider->loadMimeTypePrivate(mimePrivate)) {
- found = true;
- break;
- }
- }
- if (!found) {
- const QString file = mimePrivate.name + ".xml"_L1;
- qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.\n"
- "Either it was just removed, or the directory doesn't have executable permission..."
- << locateMimeDirectories();
- }
- mimePrivate.loaded = true;
+ for (const auto &provider : providers()) {
+ auto comments = provider->localeComments(name);
+ if (!comments.isEmpty())
+ return comments; // maybe we want to merge in comments from more global providers, in
+ // case of more translations?
}
+ return {};
}
-void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate)
+QStringList QMimeDatabasePrivate::globPatterns(const QString &name)
{
QMutexLocker locker(&mutex);
- if (mimePrivate.fromCache) {
- mimePrivate.genericIconName.clear();
- for (const auto &provider : providers()) {
- provider->loadGenericIcon(mimePrivate);
- if (!mimePrivate.genericIconName.isEmpty())
- break;
- }
+ QStringList patterns;
+ const auto &providerList = providers();
+ // reverse iteration because we start from most global, add up, clear if delete-all, and add up
+ // again.
+ for (auto rit = providerList.rbegin(); rit != providerList.rend(); ++rit) {
+ auto *provider = rit->get();
+ if (provider->hasGlobDeleteAll(name))
+ patterns.clear();
+ patterns += provider->globPatterns(name);
}
+ return patterns;
}
-void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate)
+QString QMimeDatabasePrivate::genericIcon(const QString &name)
{
QMutexLocker locker(&mutex);
- if (mimePrivate.fromCache) {
- mimePrivate.iconName.clear();
- for (const auto &provider : providers()) {
- provider->loadIcon(mimePrivate);
- if (!mimePrivate.iconName.isEmpty())
- break;
- }
+ for (const auto &provider : providers()) {
+ QString genericIconName = provider->genericIcon(name);
+ if (!genericIconName.isEmpty())
+ return genericIconName;
}
+ return {};
+}
+
+QString QMimeDatabasePrivate::icon(const QString &name)
+{
+ QMutexLocker locker(&mutex);
+ for (const auto &provider : providers()) {
+ QString iconName = provider->icon(name);
+ if (!iconName.isEmpty())
+ return iconName;
+ }
+ return {};
}
QString QMimeDatabasePrivate::fallbackParent(const QString &mimeTypeName) const
@@ -331,13 +337,14 @@ QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracy
return mimeTypeForName(QStringLiteral("application/x-zerosize"));
}
- *accuracyPtr = 0;
- QMimeType candidate;
+ QMimeMagicResult result;
for (const auto &provider : providers())
- provider->findByMagic(data, accuracyPtr, candidate);
+ provider->findByMagic(data, result);
- if (candidate.isValid())
- return candidate;
+ if (result.isValid()) {
+ *accuracyPtr = result.accuracy;
+ return QMimeType(QMimeTypePrivate(result.candidate));
+ }
if (isTextFile(data)) {
*accuracyPtr = 5;
@@ -357,7 +364,7 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
// Pass 1) Try to match on the file name
QMimeGlobMatchResult candidatesByName = findByFileName(fileName);
- if (candidatesByName.m_allMatchingMimeTypes.count() == 1) {
+ if (candidatesByName.m_allMatchingMimeTypes.size() == 1) {
const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
if (mime.isValid())
return mime;
@@ -386,7 +393,7 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) {
return candidateByData;
}
- for (const QString &m : qAsConst(candidatesByName.m_allMatchingMimeTypes)) {
+ for (const QString &m : std::as_const(candidatesByName.m_allMatchingMimeTypes)) {
if (inherits(m, sniffedMime)) {
// We have magic + pattern pointing to this, so it's a pretty good match
return mimeTypeForName(m);
@@ -399,7 +406,7 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
}
}
- if (candidatesByName.m_allMatchingMimeTypes.count() > 1) {
+ if (candidatesByName.m_allMatchingMimeTypes.size() > 1) {
candidatesByName.m_matchingMimeTypes.sort(); // make it deterministic
const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
if (mime.isValid())
@@ -444,31 +451,32 @@ QMimeType QMimeDatabasePrivate::mimeTypeForData(QIODevice *device)
}
QMimeType QMimeDatabasePrivate::mimeTypeForFile(const QString &fileName,
- [[maybe_unused]] const QFileInfo *fileInfo,
+ const QFileInfo &fileInfo,
QMimeDatabase::MatchMode mode)
{
+ if (false) {
#ifdef Q_OS_UNIX
- // Cannot access statBuf.st_mode from the filesystem engine, so we have to stat again.
- // In addition we want to follow symlinks.
- const QByteArray nativeFilePath = QFile::encodeName(fileName);
- QT_STATBUF statBuffer;
- if (QT_STAT(nativeFilePath.constData(), &statBuffer) == 0) {
- if (S_ISDIR(statBuffer.st_mode))
- return mimeTypeForName(directoryMimeType());
- if (S_ISCHR(statBuffer.st_mode))
- return mimeTypeForName(QStringLiteral("inode/chardevice"));
- if (S_ISBLK(statBuffer.st_mode))
- return mimeTypeForName(QStringLiteral("inode/blockdevice"));
- if (S_ISFIFO(statBuffer.st_mode))
- return mimeTypeForName(QStringLiteral("inode/fifo"));
- if (S_ISSOCK(statBuffer.st_mode))
- return mimeTypeForName(QStringLiteral("inode/socket"));
- }
-#else
- const bool isDirectory = fileInfo ? fileInfo->isDir() : QFileInfo(fileName).isDir();
- if (isDirectory)
- return mimeTypeForName(directoryMimeType());
+ } else if (fileInfo.isNativePath()) {
+ // If this is a local file, we'll want to do a stat() ourselves so we can
+ // detect additional inode types. In addition we want to follow symlinks.
+ const QByteArray nativeFilePath = QFile::encodeName(fileName);
+ QT_STATBUF statBuffer;
+ if (QT_STAT(nativeFilePath.constData(), &statBuffer) == 0) {
+ if (S_ISDIR(statBuffer.st_mode))
+ return mimeTypeForName(directoryMimeType());
+ if (S_ISCHR(statBuffer.st_mode))
+ return mimeTypeForName(QStringLiteral("inode/chardevice"));
+ if (S_ISBLK(statBuffer.st_mode))
+ return mimeTypeForName(QStringLiteral("inode/blockdevice"));
+ if (S_ISFIFO(statBuffer.st_mode))
+ return mimeTypeForName(QStringLiteral("inode/fifo"));
+ if (S_ISSOCK(statBuffer.st_mode))
+ return mimeTypeForName(QStringLiteral("inode/socket"));
+ }
#endif
+ } else if (fileInfo.isDir()) {
+ return mimeTypeForName(directoryMimeType());
+ }
switch (mode) {
case QMimeDatabase::MatchDefault:
@@ -495,6 +503,7 @@ QList<QMimeType> QMimeDatabasePrivate::allMimeTypes()
bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
{
const QString resolvedParent = resolveAlias(parent);
+ QDuplicateTracker<QString> seen;
std::stack<QString, QStringList> toCheck;
toCheck.push(mime);
while (!toCheck.empty()) {
@@ -503,8 +512,11 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
const QString mimeName = toCheck.top();
toCheck.pop();
const auto parentList = parents(mimeName);
- for (const QString &par : parentList)
- toCheck.push(resolveAlias(par));
+ for (const QString &par : parentList) {
+ const QString resolvedPar = resolveAlias(par);
+ if (!seen.hasSeen(resolvedPar))
+ toCheck.push(resolvedPar);
+ }
}
return false;
}
@@ -546,7 +558,7 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
\snippet code/src_corelib_mimetype_qmimedatabase.cpp 0
- \sa QMimeType, {MIME Type Browser Example}
+ \sa QMimeType, {MIME Type Browser}
*/
/*!
@@ -615,7 +627,7 @@ QMimeType QMimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mo
{
QMutexLocker locker(&d->mutex);
- return d->mimeTypeForFile(fileInfo.filePath(), &fileInfo, mode);
+ return d->mimeTypeForFile(fileInfo.filePath(), fileInfo, mode);
}
/*!
@@ -630,7 +642,8 @@ QMimeType QMimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode
if (mode == MatchExtension) {
return d->mimeTypeForFileExtension(fileName);
} else {
- return d->mimeTypeForFile(fileName, nullptr, mode);
+ QFileInfo fileInfo(fileName);
+ return d->mimeTypeForFile(fileName, fileInfo, mode);
}
}
@@ -652,7 +665,7 @@ QList<QMimeType> QMimeDatabase::mimeTypesForFileName(const QString &fileName) co
const QStringList matches = d->mimeTypeForFileName(fileName);
QList<QMimeType> mimes;
- mimes.reserve(matches.count());
+ mimes.reserve(matches.size());
for (const QString &mime : matches)
mimes.append(d->mimeTypeForName(mime));
return mimes;
@@ -666,7 +679,7 @@ QList<QMimeType> QMimeDatabase::mimeTypesForFileName(const QString &fileName) co
QString QMimeDatabase::suffixForFileName(const QString &fileName) const
{
QMutexLocker locker(&d->mutex);
- const int suffixLength = d->findByFileName(fileName).m_knownSuffixLength;
+ const qsizetype suffixLength = d->findByFileName(fileName).m_knownSuffixLength;
return fileName.right(suffixLength);
}