diff options
Diffstat (limited to 'src/corelib/mimetypes/qmimeprovider.cpp')
-rw-r--r-- | src/corelib/mimetypes/qmimeprovider.cpp | 433 |
1 files changed, 228 insertions, 205 deletions
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 92be90658e..458cd46385 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> -** Copyright (C) 2019 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> +// Copyright (C) 2019 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qmimeprovider_p.h" @@ -55,7 +19,7 @@ #include <QtEndian> #if QT_CONFIG(mimetype_database) -# if defined(Q_CC_MSVC) +# if defined(Q_CC_MSVC_ONLY) # pragma section(".qtmimedatabase", read, shared) __declspec(allocate(".qtmimedatabase")) __declspec(align(4096)) # elif defined(Q_OS_DARWIN) @@ -84,17 +48,7 @@ __attribute__((section(".qtmimedatabase"), aligned(4096))) QT_BEGIN_NAMESPACE -QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory) - : m_db(db), m_directory(directory) -{ -} - - -QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory) - : QMimeProviderBase(db, directory), m_mimetypeListLoaded(false) -{ - ensureLoaded(); -} +using namespace Qt::StringLiterals; struct QMimeBinaryProvider::CacheFile { @@ -123,6 +77,43 @@ struct QMimeBinaryProvider::CacheFile bool m_valid; }; +static inline void appendIfNew(QStringList &list, const QString &str) +{ + if (!list.contains(str)) + list.push_back(str); +} + +QMimeProviderBase::QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory) + : m_db(db), m_directory(directory) +{ +} + +QMimeProviderBase *QMimeProviderBase::overrideProvider() const +{ + return m_overrideProvider; +} + +void QMimeProviderBase::setOverrideProvider(QMimeProviderBase *provider) +{ + m_overrideProvider = provider; +} + +bool QMimeProviderBase::isMimeTypeGlobsExcluded(const QString &name) const +{ + if (m_overrideProvider) { + if (m_overrideProvider->hasGlobDeleteAll(name)) + return true; + return m_overrideProvider->isMimeTypeGlobsExcluded(name); + } + return false; +} + +QMimeBinaryProvider::QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory) + : QMimeProviderBase(db, directory), m_mimetypeListLoaded(false) +{ + ensureLoaded(); +} + QMimeBinaryProvider::CacheFile::CacheFile(const QString &fileName) : file(fileName), m_valid(false) { @@ -143,7 +134,7 @@ bool QMimeBinaryProvider::CacheFile::load() const int minor = getUint16(2); m_valid = (major == 1 && minor >= 1 && minor <= 2); } - m_mtime = QFileInfo(file).lastModified(); + m_mtime = QFileInfo(file).lastModified(QTimeZone::UTC); return m_valid; } @@ -157,10 +148,7 @@ bool QMimeBinaryProvider::CacheFile::reload() return load(); } -QMimeBinaryProvider::~QMimeBinaryProvider() -{ - delete m_cacheFile; -} +QMimeBinaryProvider::~QMimeBinaryProvider() = default; bool QMimeBinaryProvider::isValid() { @@ -188,7 +176,7 @@ enum { bool QMimeBinaryProvider::checkCacheChanged() { QFileInfo fileInfo(m_cacheFile->file); - if (fileInfo.lastModified() > m_cacheFile->m_mtime) { + if (fileInfo.lastModified(QTimeZone::UTC) > 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 @@ -200,8 +188,8 @@ bool QMimeBinaryProvider::checkCacheChanged() void QMimeBinaryProvider::ensureLoaded() { if (!m_cacheFile) { - const QString cacheFileName = m_directory + QLatin1String("/mime.cache"); - m_cacheFile = new CacheFile(cacheFileName); + const QString cacheFileName = m_directory + "/mime.cache"_L1; + m_cacheFile = std::make_unique<CacheFile>(cacheFileName); m_mimetypeListLoaded = false; m_mimetypeExtra.clear(); } else { @@ -212,31 +200,15 @@ void QMimeBinaryProvider::ensureLoaded() return; // nothing to do } } - if (!m_cacheFile->isValid()) { // verify existence and version - delete m_cacheFile; - m_cacheFile = nullptr; - } -} - -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 - // genericIconName: in loadGenericIcon - return QMimeType(data); + if (!m_cacheFile->isValid()) // verify existence and version + m_cacheFile.reset(); } -QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name) +bool QMimeBinaryProvider::knowsMimeType(const QString &name) { if (!m_mimetypeListLoaded) loadMimeTypeList(); - if (!m_mimetypeNames.contains(name)) - return QMimeType(); // unknown mimetype - return mimeTypeForNameUnchecked(name); + return m_mimetypeNames.contains(name); } void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) @@ -244,25 +216,34 @@ void QMimeBinaryProvider::addFileNameMatches(const QString &fileName, QMimeGlobM if (fileName.isEmpty()) return; Q_ASSERT(m_cacheFile); - const QString lowerFileName = fileName.toLower(); + int numMatches = 0; // Check literals (e.g. "Makefile") - matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosLiteralListOffset), fileName); + numMatches = matchGlobList(result, m_cacheFile.get(), + m_cacheFile->getUint32(PosLiteralListOffset), fileName); // Check the very common *.txt cases with the suffix tree - if (result.m_matchingMimeTypes.isEmpty()) { + if (numMatches == 0) { + const QString lowerFileName = fileName.toLower(); 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); + if (matchSuffixTree(result, m_cacheFile.get(), numRoots, firstRootOffset, lowerFileName, + lowerFileName.size() - 1, false)) { + ++numMatches; + } else if (matchSuffixTree(result, m_cacheFile.get(), numRoots, firstRootOffset, fileName, + fileName.size() - 1, true)) { + ++numMatches; + } } // Check complex globs (e.g. "callgrind.out[0-9]*" or "README*") - if (result.m_matchingMimeTypes.isEmpty()) - matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), fileName); + if (numMatches == 0) + matchGlobList(result, m_cacheFile.get(), m_cacheFile->getUint32(PosGlobListOffset), + fileName); } -void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName) +int QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, + const QString &fileName) { + int numMatches = 0; const int numGlobs = cacheFile->getUint32(off); //qDebug() << "Loading" << numGlobs << "globs from" << cacheFile->file.fileName() << "at offset" << cacheFile->globListOffset; for (int i = 0; i < numGlobs; ++i) { @@ -272,19 +253,26 @@ void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile const int weight = flagsAndWeight & 0xff; const bool caseSensitive = flagsAndWeight & 0x100; const Qt::CaseSensitivity qtCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; - const QString pattern = QLatin1String(cacheFile->getCharStar(globOffset)); + const QString pattern = QLatin1StringView(cacheFile->getCharStar(globOffset)); - const char *mimeType = cacheFile->getCharStar(mimeTypeOffset); + const QLatin1StringView mimeType(cacheFile->getCharStar(mimeTypeOffset)); //qDebug() << pattern << mimeType << weight << caseSensitive; - QMimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive); + if (isMimeTypeGlobsExcluded(mimeType)) + continue; - // TODO: this could be done faster for literals where a simple == would do. - if (glob.matchFileName(fileName)) - result.addMatch(QLatin1String(mimeType), weight, pattern); + QMimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive); + if (glob.matchFileName(fileName)) { + result.addMatch(mimeType, weight, pattern); + ++numMatches; + } } + return numMatches; } -bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, QMimeBinaryProvider::CacheFile *cacheFile, int numEntries, int firstOffset, const QString &fileName, int charPos, bool caseSensitiveCheck) +bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, + QMimeBinaryProvider::CacheFile *cacheFile, int numEntries, + int firstOffset, const QString &fileName, + qsizetype charPos, bool caseSensitiveCheck) { QChar fileChar = fileName[charPos]; int min = 0; @@ -311,13 +299,16 @@ bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, QMimeBin if (mch != 0) break; const int mimeTypeOffset = cacheFile->getUint32(childOff + 4); - const char *mimeType = cacheFile->getCharStar(mimeTypeOffset); + const QLatin1StringView mimeType(cacheFile->getCharStar(mimeTypeOffset)); + if (isMimeTypeGlobsExcluded(mimeType)) + continue; const int flagsAndWeight = cacheFile->getUint32(childOff + 8); const int weight = flagsAndWeight & 0xff; const bool caseSensitive = flagsAndWeight & 0x100; if (caseSensitiveCheck || !caseSensitive) { - result.addMatch(QLatin1String(mimeType), weight, - QLatin1Char('*') + QStringView{fileName}.mid(charPos + 1), fileName.size() - charPos - 2); + result.addMatch(mimeType, weight, + u'*' + QStringView{ fileName }.mid(charPos + 1), + fileName.size() - charPos - 2); success = true; } } @@ -331,7 +322,7 @@ bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, QMimeBin bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data) { const char *dataPtr = data.constData(); - const int dataSize = data.size(); + const qsizetype dataSize = data.size(); for (int matchlet = 0; matchlet < numMatchlets; ++matchlet) { const int off = firstOffset + matchlet * 32; const int rangeStart = cacheFile->getUint32(off); @@ -356,7 +347,7 @@ bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::CacheFile *cacheFi return false; } -void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) +void QMimeBinaryProvider::findByMagic(const QByteArray &data, QMimeMagicResult &result) { const int magicListOffset = m_cacheFile->getUint32(PosMagicListOffset); const int numMatches = m_cacheFile->getUint32(magicListOffset); @@ -367,14 +358,16 @@ void QMimeBinaryProvider::findByMagic(const QByteArray &data, int *accuracyPtr, 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)) { + if (matchMagicRule(m_cacheFile.get(), 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; + const int accuracy = static_cast<int>(m_cacheFile->getUint32(off)); + if (accuracy > result.accuracy) { + result.accuracy = accuracy; + result.candidate = QString::fromLatin1(mimeType); + // Return the first match, mime.cache is sorted + return; + } } } } @@ -404,8 +397,7 @@ void QMimeBinaryProvider::addParents(const QString &mime, QStringList &result) 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); + appendIfNew(result, strParent); } break; } @@ -432,7 +424,7 @@ QString QMimeBinaryProvider::resolveAlias(const QString &name) } else { const int mimeOffset = m_cacheFile->getUint32(off + 4); const char *mimeType = m_cacheFile->getCharStar(mimeOffset); - return QLatin1String(mimeType); + return QLatin1StringView(mimeType); } } return QString(); @@ -452,8 +444,7 @@ void QMimeBinaryProvider::addAliases(const QString &name, QStringList &result) 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); + appendIfNew(result, strAlias); } } } @@ -465,13 +456,14 @@ 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". - QFile file(m_directory + QStringLiteral("/types")); + QFile file(m_directory + QStringView(u"/types")); if (file.open(QIODevice::ReadOnly)) { while (!file.atEnd()) { - QByteArray line = file.readLine(); - if (line.endsWith('\n')) - line.chop(1); - m_mimetypeNames.insert(QString::fromLatin1(line)); + const QByteArray line = file.readLine(); + auto lineView = QByteArrayView(line); + if (lineView.endsWith('\n')) + lineView.chop(1); + m_mimetypeNames.insert(QString::fromLatin1(lineView)); } } } @@ -481,80 +473,95 @@ void QMimeBinaryProvider::addAllMimeTypes(QList<QMimeType> &result) { loadMimeTypeList(); if (result.isEmpty()) { - result.reserve(m_mimetypeNames.count()); - for (const QString &name : qAsConst(m_mimetypeNames)) - result.append(mimeTypeForNameUnchecked(name)); + result.reserve(m_mimetypeNames.size()); + for (const QString &name : std::as_const(m_mimetypeNames)) + result.append(QMimeType(QMimeTypePrivate(name))); } else { - for (const QString &name : qAsConst(m_mimetypeNames)) + for (const QString &name : std::as_const(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)); + result.append(QMimeType(QMimeTypePrivate(name))); } } -bool QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) +QMimeTypePrivate::LocaleHash QMimeBinaryProvider::localeComments(const QString &name) { -#ifdef QT_NO_XMLSTREAMREADER - Q_UNUSED(data); - qWarning("Cannot load mime type since QXmlStreamReader is not available."); - return false; -#else - if (data.loaded) - return true; + MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name); + if (it != m_mimetypeExtra.cend()) + return it->second.localeComments; + return {}; +} + +bool QMimeBinaryProvider::hasGlobDeleteAll(const QString &name) +{ + MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name); + if (it != m_mimetypeExtra.cend()) + return it->second.hasGlobDeleteAll; + return {}; +} + +QStringList QMimeBinaryProvider::globPatterns(const QString &name) +{ + MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name); + if (it != m_mimetypeExtra.cend()) + return it->second.globPatterns; + return {}; +} - auto it = m_mimetypeExtra.constFind(data.name); - if (it == m_mimetypeExtra.constEnd()) { +QMimeBinaryProvider::MimeTypeExtraMap::const_iterator +QMimeBinaryProvider::loadMimeTypeExtra(const QString &mimeName) +{ +#if QT_CONFIG(xmlstreamreader) + auto it = m_mimetypeExtra.find(mimeName); + if (it == m_mimetypeExtra.cend()) { // load comment and globPatterns // shared-mime-info since 1.3 lowercases the xml files - QString mimeFile = m_directory + QLatin1Char('/') + data.name.toLower() + QLatin1String(".xml"); + QString mimeFile = m_directory + u'/' + mimeName.toLower() + ".xml"_L1; if (!QFile::exists(mimeFile)) - mimeFile = m_directory + QLatin1Char('/') + data.name + QLatin1String(".xml"); // pre-1.3 + mimeFile = m_directory + u'/' + mimeName + ".xml"_L1; // pre-1.3 QFile qfile(mimeFile); if (!qfile.open(QFile::ReadOnly)) - return false; + return m_mimetypeExtra.cend(); - auto insertIt = m_mimetypeExtra.insert(data.name, MimeTypeExtra{}); - it = insertIt; - MimeTypeExtra &extra = insertIt.value(); + it = m_mimetypeExtra.try_emplace(mimeName).first; + MimeTypeExtra &extra = it->second; QString mainPattern; QXmlStreamReader xml(&qfile); if (xml.readNextStartElement()) { - if (xml.name() != QLatin1String("mime-type")) { - return false; + if (xml.name() != "mime-type"_L1) { + return m_mimetypeExtra.cend(); } - const auto name = xml.attributes().value(QLatin1String("type")); + const auto name = xml.attributes().value("type"_L1); if (name.isEmpty()) - return false; - if (name.compare(data.name, Qt::CaseInsensitive)) - qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << data.name; + return m_mimetypeExtra.cend(); + if (name.compare(mimeName, Qt::CaseInsensitive)) + qWarning() << "Got name" << name << "in file" << mimeFile << "expected" << mimeName; while (xml.readNextStartElement()) { const auto tag = xml.name(); - if (tag == QLatin1String("comment")) { - QString lang = xml.attributes().value(QLatin1String("xml:lang")).toString(); + if (tag == "comment"_L1) { + QString lang = xml.attributes().value("xml:lang"_L1).toString(); const QString text = xml.readElementText(); if (lang.isEmpty()) { - lang = QLatin1String("default"); // no locale attribute provided, treat it as default. + lang = "default"_L1; // no locale attribute provided, treat it as default. } extra.localeComments.insert(lang, text); continue; // we called readElementText, so we're at the EndElement already. - } else if (tag == QLatin1String("glob-deleteall")) { // as written out by shared-mime-info >= 0.70 - extra.globPatterns.clear(); - mainPattern.clear(); - } else if (tag == QLatin1String("glob")) { // as written out by shared-mime-info >= 0.70 - const QString pattern = xml.attributes().value(QLatin1String("pattern")).toString(); - if (mainPattern.isEmpty() && pattern.startsWith(QLatin1Char('*'))) { + } else if (tag == "glob-deleteall"_L1) { // as written out by shared-mime-info >= 0.70 + extra.hasGlobDeleteAll = true; + } else if (tag == "glob"_L1) { // as written out by shared-mime-info >= 0.70 + const QString pattern = xml.attributes().value("pattern"_L1).toString(); + if (mainPattern.isEmpty() && pattern.startsWith(u'*')) { mainPattern = pattern; } - if (!extra.globPatterns.contains(pattern)) - extra.globPatterns.append(pattern); + appendIfNew(extra.globPatterns, pattern); } xml.skipCurrentElement(); } - Q_ASSERT(xml.name() == QLatin1String("mime-type")); + Q_ASSERT(xml.name() == "mime-type"_L1); } // Let's assume that shared-mime-info is at least version 0.70 @@ -566,15 +573,17 @@ bool QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) extra.globPatterns.prepend(mainPattern); } } - const MimeTypeExtra &e = it.value(); - data.localeComments = e.localeComments; - data.globPatterns = e.globPatterns; - return true; -#endif //QT_NO_XMLSTREAMREADER + return it; +#else + Q_UNUSED(mimeName); + qWarning("Cannot load mime type since QXmlStreamReader is not available."); + return m_mimetypeExtra.cend(); +#endif // feature xmlstreamreader } // Binary search in the icons or generic-icons list -QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime) +QLatin1StringView QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, + const QByteArray &inputMime) { const int iconsListOffset = cacheFile->getUint32(posListOffset); const int numIcons = cacheFile->getUint32(iconsListOffset); @@ -592,28 +601,22 @@ QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posList end = medium - 1; else { const int iconOffset = cacheFile->getUint32(off + 4); - return QLatin1String(cacheFile->getCharStar(iconOffset)); + return QLatin1StringView(cacheFile->getCharStar(iconOffset)); } } - return QLatin1String(); + return QLatin1StringView(); } -void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data) +QString QMimeBinaryProvider::icon(const QString &name) { - const QByteArray inputMime = data.name.toLatin1(); - const QLatin1String icon = iconForMime(m_cacheFile, PosIconsListOffset, inputMime); - if (!icon.isEmpty()) { - data.iconName = icon; - } + const QByteArray inputMime = name.toLatin1(); + return iconForMime(m_cacheFile.get(), PosIconsListOffset, inputMime); } -void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data) +QString QMimeBinaryProvider::genericIcon(const QString &name) { - const QByteArray inputMime = data.name.toLatin1(); - const QLatin1String icon = iconForMime(m_cacheFile, PosGenericIconsListOffset, inputMime); - if (!icon.isEmpty()) { - data.genericIconName = icon; - } + const QByteArray inputMime = name.toLatin1(); + return iconForMime(m_cacheFile.get(), PosGenericIconsListOffset, inputMime); } //// @@ -698,43 +701,39 @@ bool QMimeXMLProvider::isInternalDatabase() const #endif } -QMimeType QMimeXMLProvider::mimeTypeForName(const QString &name) +bool QMimeXMLProvider::knowsMimeType(const QString &name) { - return m_nameMimeTypeMap.value(name); + return m_nameMimeTypeMap.contains(name); } void QMimeXMLProvider::addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) { - m_mimeTypeGlobs.matchingGlobs(fileName, result); + auto filterFunc = [this](const QString &name) { return !isMimeTypeGlobsExcluded(name); }; + m_mimeTypeGlobs.matchingGlobs(fileName, result, filterFunc); } -void QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) +void QMimeXMLProvider::findByMagic(const QByteArray &data, QMimeMagicResult &result) { - QString candidateName; - bool foundOne = false; - for (const QMimeMagicRuleMatcher &matcher : qAsConst(m_magicMatchers)) { + for (const QMimeMagicRuleMatcher &matcher : std::as_const(m_magicMatchers)) { if (matcher.matches(data)) { const int priority = matcher.priority(); - if (priority > *accuracyPtr) { - *accuracyPtr = priority; - candidateName = matcher.mimetype(); - foundOne = true; + if (priority > result.accuracy) { + result.accuracy = priority; + result.candidate = matcher.mimetype(); } } } - if (foundOne) - candidate = mimeTypeForName(candidateName); } void QMimeXMLProvider::ensureLoaded() { QStringList allFiles; - const QString packageDir = m_directory + QStringLiteral("/packages"); + const QString packageDir = m_directory + QStringView(u"/packages"); QDir dir(packageDir); const QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot); - allFiles.reserve(files.count()); + allFiles.reserve(files.size()); for (const QString &xmlFile : files) - allFiles.append(packageDir + QLatin1Char('/') + xmlFile); + allFiles.append(packageDir + u'/' + xmlFile); if (m_allFiles == allFiles) return; @@ -748,10 +747,35 @@ void QMimeXMLProvider::ensureLoaded() //qDebug() << "Loading" << m_allFiles; - for (const QString &file : qAsConst(allFiles)) + for (const QString &file : std::as_const(allFiles)) load(file); } +QMimeTypePrivate::LocaleHash QMimeXMLProvider::localeComments(const QString &name) +{ + return m_nameMimeTypeMap.value(name).localeComments; +} + +bool QMimeXMLProvider::hasGlobDeleteAll(const QString &name) +{ + return m_nameMimeTypeMap.value(name).hasGlobDeleteAll; +} + +QStringList QMimeXMLProvider::globPatterns(const QString &name) +{ + return m_nameMimeTypeMap.value(name).globPatterns; +} + +QString QMimeXMLProvider::icon(const QString &name) +{ + return m_nameMimeTypeMap.value(name).iconName; +} + +QString QMimeXMLProvider::genericIcon(const QString &name) +{ + return m_nameMimeTypeMap.value(name).genericIconName; +} + void QMimeXMLProvider::load(const QString &fileName) { QString errorMessage; @@ -764,7 +788,7 @@ bool QMimeXMLProvider::load(const QString &fileName, QString *errorMessage) QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (errorMessage) - *errorMessage = QLatin1String("Cannot open ") + fileName + QLatin1String(": ") + file.errorString(); + *errorMessage = "Cannot open "_L1 + fileName + ": "_L1 + file.errorString(); return false; } @@ -793,10 +817,9 @@ void QMimeXMLProvider::addGlobPattern(const QMimeGlobPattern &glob) m_mimeTypeGlobs.addGlob(glob); } -void QMimeXMLProvider::addMimeType(const QMimeType &mt) +void QMimeXMLProvider::addMimeType(const QMimeTypeXMLData &mt) { - Q_ASSERT(!mt.d.data()->fromCache); - m_nameMimeTypeMap.insert(mt.name(), mt); + m_nameMimeTypeMap.insert(mt.name, mt); } void QMimeXMLProvider::addParents(const QString &mime, QStringList &result) @@ -815,13 +838,10 @@ void QMimeXMLProvider::addParent(const QString &child, const QString &parent) void QMimeXMLProvider::addAliases(const QString &name, QStringList &result) { // Iterate through the whole hash. This method is rarely used. - 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()); - } + for (const auto &[alias, mimeName] : std::as_const(m_aliases).asKeyValueRange()) { + if (mimeName == name) + appendIfNew(result, alias); } - } QString QMimeXMLProvider::resolveAlias(const QString &name) @@ -837,13 +857,16 @@ void QMimeXMLProvider::addAlias(const QString &alias, const QString &name) void QMimeXMLProvider::addAllMimeTypes(QList<QMimeType> &result) { if (result.isEmpty()) { // fast path - result = m_nameMimeTypeMap.values(); + for (auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd(); + it != end; ++it) { + result.append(QMimeType(QMimeTypePrivate(it.value().name))); + } } 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()); + result.append(QMimeType(QMimeTypePrivate(it.value().name))); } } } |