summaryrefslogtreecommitdiffstats
path: root/src/corelib/mimetypes/qmimeprovider.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/mimetypes/qmimeprovider.cpp')
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp521
1 files changed, 200 insertions, 321 deletions
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index ed7ebb2ef5..ec0a6bf0ef 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -61,46 +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)
{
}
-Q_CORE_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test
-bool QMimeProviderBase::shouldCheck()
-{
- if (m_lastCheck.isValid() && m_lastCheck.elapsed() < qmime_secondsBetweenChecks * 1000)
- return false;
- m_lastCheck.start();
- return true;
-}
-
-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);
@@ -154,7 +126,6 @@ bool QMimeBinaryProvider::CacheFile::load()
bool QMimeBinaryProvider::CacheFile::reload()
{
- //qDebug() << "reload!" << file->fileName();
m_valid = false;
if (file.isOpen()) {
file.close();
@@ -163,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
@@ -190,79 +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
- checkCache();
-
- 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::checkCache()
+void QMimeBinaryProvider::ensureLoaded()
{
- if (!shouldCheck())
- return;
-
- // 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;
}
}
@@ -270,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
@@ -279,7 +201,6 @@ static QMimeType mimeTypeForNameUnchecked(const QString &name)
QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name)
{
- checkCache();
if (!m_mimetypeListLoaded)
loadMimeTypeList();
if (!m_mimetypeNames.contains(name))
@@ -287,28 +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)
{
- checkCache();
- 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)
@@ -406,124 +322,106 @@ bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFi
return false;
}
-QMimeType QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
-{
- checkCache();
- 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)
{
- checkCache();
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)
{
- checkCache();
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)
{
- checkCache();
- 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()
@@ -533,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)
@@ -681,36 +578,29 @@ QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posList
void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
{
- checkCache();
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)
{
- checkCache();
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), m_loaded(false)
+QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory)
+ : QMimeProviderBase(db, directory)
{
initResources();
+ ensureLoaded();
}
QMimeXMLProvider::~QMimeXMLProvider()
@@ -719,81 +609,63 @@ 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;
}
QMimeType QMimeXMLProvider::mimeTypeForName(const QString &name)
{
- ensureLoaded();
-
return m_nameMimeTypeMap.value(name);
}
-QMimeGlobMatchResult QMimeXMLProvider::findByFileName(const QString &fileName)
+void QMimeXMLProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result)
{
- ensureLoaded();
-
- 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)
{
- ensureLoaded();
-
- 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()
{
- if (!m_loaded || shouldCheck()) {
- 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"));
- }
+ QStringList allFiles;
+ 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;
- m_allFiles = allFiles;
+ if (m_allFiles == allFiles)
+ return;
+ m_allFiles = allFiles;
- m_nameMimeTypeMap.clear();
- m_aliases.clear();
- m_parents.clear();
- m_mimeTypeGlobs.clear();
- m_magicMatchers.clear();
+ m_nameMimeTypeMap.clear();
+ m_aliases.clear();
+ m_parents.clear();
+ m_mimeTypeGlobs.clear();
+ m_magicMatchers.clear();
- //qDebug() << "Loading" << m_allFiles;
+ //qDebug() << "Loading" << m_allFiles;
- for (const QString &file : qAsConst(allFiles))
- load(file);
- }
+ for (const QString &file : qAsConst(allFiles))
+ load(file);
}
void QMimeXMLProvider::load(const QString &fileName)
@@ -805,8 +677,6 @@ void QMimeXMLProvider::load(const QString &fileName)
bool QMimeXMLProvider::load(const QString &fileName, QString *errorMessage)
{
- m_loaded = true;
-
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
if (errorMessage)
@@ -828,19 +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)
{
- ensureLoaded();
- 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)
@@ -848,16 +715,20 @@ 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)
{
- ensureLoaded();
// 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)
{
- ensureLoaded();
return m_aliases.value(name, name);
}
@@ -866,10 +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)
{
- ensureLoaded();
- 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)