From f39ef79210b6f4d5df72c52c2f1502e7dda5ff5a Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 29 Aug 2024 15:37:10 +0200 Subject: [PATCH] Update mime database from Qt qtbase/1f0bc1ade316547d01100dcca4f3f7187485f917 QMimeDatabase: fix glob-deleteall support for the binary providers And integrate Qt Creator's own override mechanism into the introduced filter function. Change-Id: I7c75a9830e263273af7ea3bfe35fc728e8421862 Reviewed-by: Jarek Kobus --- src/libs/utils/mimetypes2/mimedatabase.cpp | 14 ++-- src/libs/utils/mimetypes2/mimeglobpattern.cpp | 21 +++--- src/libs/utils/mimetypes2/mimeglobpattern_p.h | 12 ++-- src/libs/utils/mimetypes2/mimeprovider.cpp | 66 ++++++++----------- src/libs/utils/mimetypes2/mimeprovider_p.h | 35 ++-------- 5 files changed, 53 insertions(+), 95 deletions(-) diff --git a/src/libs/utils/mimetypes2/mimedatabase.cpp b/src/libs/utils/mimetypes2/mimedatabase.cpp index b7a8459af89..7451889dab7 100644 --- a/src/libs/utils/mimetypes2/mimedatabase.cpp +++ b/src/libs/utils/mimetypes2/mimedatabase.cpp @@ -196,18 +196,12 @@ void MimeDatabasePrivate::loadProviders() } } - // Handle mimetypes with glob-deleteall tags (from XML providers) auto it = m_providers.begin(); + (*it)->setOverrideProvider(nullptr); + ++it; const auto end = m_providers.end(); - for (;it != end; ++it) { - const QStringList &list = (*it)->m_mimeTypesWithDeletedGlobs; - if (list.isEmpty()) - continue; - // Each Provider affects Providers with lower precedence - auto nextIt = it + 1; - for (; nextIt != end; ++nextIt) - (*nextIt)->excludeMimeTypeGlobs(list); - } + for (; it != end; ++it) + (*it)->setOverrideProvider((it - 1)->get()); updateOverriddenMimeTypes(m_providers); } diff --git a/src/libs/utils/mimetypes2/mimeglobpattern.cpp b/src/libs/utils/mimetypes2/mimeglobpattern.cpp index 8d4af993103..11466934398 100644 --- a/src/libs/utils/mimetypes2/mimeglobpattern.cpp +++ b/src/libs/utils/mimetypes2/mimeglobpattern.cpp @@ -221,14 +221,11 @@ void MimeAllGlobPatterns::removeMimeType(const QString &mimeType) m_lowWeightGlobs.removeMimeType(mimeType); } -void MimeGlobPatternList::match(MimeGlobMatchResult &result, - const QString &fileName, - const QSet &ignoreMimeTypes) const +void MimeGlobPatternList::match(MimeGlobMatchResult &result, const QString &fileName, + const AddMatchFilterFunc &filterFunc) const { for (const MimeGlobPattern &glob : *this) { - if (ignoreMimeTypes.contains(glob.mimeType())) - continue; - if (glob.matchFileName(fileName)) { + if (glob.matchFileName(fileName) && filterFunc(glob.mimeType())) { const QString pattern = glob.pattern(); const qsizetype suffixLen = isSimplePattern(pattern) ? pattern.size() - strlen("*.") : 0; result.addMatch(glob.mimeType(), glob.weight(), pattern, suffixLen); @@ -236,12 +233,11 @@ void MimeGlobPatternList::match(MimeGlobMatchResult &result, } } -void MimeAllGlobPatterns::matchingGlobs(const QString &fileName, - MimeGlobMatchResult &result, - const QSet &ignoreMimeTypes) const +void MimeAllGlobPatterns::matchingGlobs(const QString &fileName, MimeGlobMatchResult &result, + const AddMatchFilterFunc &filterFunc) const { // First try the high weight matches (>50), if any. - m_highWeightGlobs.match(result, fileName, ignoreMimeTypes); + m_highWeightGlobs.match(result, fileName, filterFunc); // Now use the "fast patterns" dict, for simple *.foo patterns with weight 50 // (which is most of them, so this optimization is definitely worth it) @@ -254,15 +250,16 @@ void MimeAllGlobPatterns::matchingGlobs(const QString &fileName, const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension); const QString simplePattern = "*."_L1 + simpleExtension; for (const QString &mime : matchingMimeTypes) { - if (!ignoreMimeTypes.contains(mime)) + if (filterFunc(mime)) { result.addMatch(mime, 50, simplePattern, simpleExtension.size()); + } } // Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway, // at least those with weight 50. } // Finally, try the low weight matches (<=50) - m_lowWeightGlobs.match(result, fileName, ignoreMimeTypes); + m_lowWeightGlobs.match(result, fileName, filterFunc); } void MimeAllGlobPatterns::clear() diff --git a/src/libs/utils/mimetypes2/mimeglobpattern_p.h b/src/libs/utils/mimetypes2/mimeglobpattern_p.h index f57a2801822..1f86e40104c 100644 --- a/src/libs/utils/mimetypes2/mimeglobpattern_p.h +++ b/src/libs/utils/mimetypes2/mimeglobpattern_p.h @@ -81,6 +81,8 @@ private: PatternType m_patternType; }; +using AddMatchFilterFunc = std::function; + class MimeGlobPatternList : public QList { public: @@ -105,9 +107,8 @@ public: erase(std::remove_if(begin(), end(), isMimeTypeEqual), end()); } - void match(MimeGlobMatchResult &result, - const QString &fileName, - const QSet &ignoreMimeTypes) const; + void match(MimeGlobMatchResult &result, const QString &fileName, + const AddMatchFilterFunc &filterFunc) const; }; /*! @@ -124,9 +125,8 @@ public: void addGlob(const MimeGlobPattern &glob); void removeMimeType(const QString &mimeType); - void matchingGlobs(const QString &fileName, - MimeGlobMatchResult &result, - const QSet &ignoreMimeTypes) const; + void matchingGlobs(const QString &fileName, MimeGlobMatchResult &result, + const AddMatchFilterFunc &filterFunc) const; void clear(); PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain" diff --git a/src/libs/utils/mimetypes2/mimeprovider.cpp b/src/libs/utils/mimetypes2/mimeprovider.cpp index effbc2c5042..efcd44f1a62 100644 --- a/src/libs/utils/mimetypes2/mimeprovider.cpp +++ b/src/libs/utils/mimetypes2/mimeprovider.cpp @@ -62,6 +62,25 @@ MimeProviderBase::MimeProviderBase(MimeDatabasePrivate *db, const QString &direc { } +MimeProviderBase *MimeProviderBase::overrideProvider() const +{ + return m_overrideProvider; +} + +void MimeProviderBase::setOverrideProvider(MimeProviderBase *provider) +{ + m_overrideProvider = provider; +} + +bool MimeProviderBase::isMimeTypeGlobsExcluded(const QString &name) const +{ + if (m_overrideProvider) { + if (m_overrideProvider->hasGlobDeleteAll(name)) + return true; + return m_overrideProvider->isMimeTypeGlobsExcluded(name); + } + return false; +} MimeBinaryProvider::MimeBinaryProvider(MimeDatabasePrivate *db, const QString &directory) : MimeProviderBase(db, directory), m_mimetypeListLoaded(false) @@ -223,17 +242,6 @@ void MimeBinaryProvider::addFileNameMatches(const QString &fileName, MimeGlobMat fileName); } -bool MimeBinaryProvider::isMimeTypeGlobsExcluded(const char *mimeTypeName) -{ - return m_mimeTypesWithExcludedGlobs.contains(QLatin1StringView(mimeTypeName)); -} - -void MimeBinaryProvider::excludeMimeTypeGlobs(const QStringList &toExclude) -{ - for (const auto &mt : toExclude) - appendIfNew(m_mimeTypesWithExcludedGlobs, mt); -} - int MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName) { @@ -249,7 +257,7 @@ int MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, CacheFile *ca const Qt::CaseSensitivity qtCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; const QString pattern = QLatin1StringView(cacheFile->getCharStar(globOffset)); - const char *mimeType = cacheFile->getCharStar(mimeTypeOffset); + const QLatin1StringView mimeType(cacheFile->getCharStar(mimeTypeOffset)); if (m_overriddenMimeTypes.contains(QLatin1String(mimeType))) continue; //qDebug() << pattern << mimeType << weight << caseSensitive; @@ -258,7 +266,7 @@ int MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result, CacheFile *ca MimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive); if (glob.matchFileName(fileName)) { - result.addMatch(QLatin1StringView(mimeType), weight, pattern); + result.addMatch(mimeType, weight, pattern); ++numMatches; } } @@ -304,7 +312,7 @@ bool MimeBinaryProvider::matchSuffixTree(MimeGlobMatchResult &result, 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; if (m_overriddenMimeTypes.contains(QLatin1String(mimeType))) @@ -313,8 +321,8 @@ bool MimeBinaryProvider::matchSuffixTree(MimeGlobMatchResult &result, const int weight = flagsAndWeight & 0xff; const bool caseSensitive = flagsAndWeight & 0x100; if (caseSensitiveCheck || !caseSensitive) { - result.addMatch(QLatin1StringView(mimeType), weight, - u'*' + QStringView{fileName}.mid(charPos + 1), + result.addMatch(mimeType, weight, + u'*' + QStringView{ fileName }.mid(charPos + 1), fileName.size() - charPos - 2); success = true; } @@ -733,7 +741,10 @@ bool MimeXMLProvider::knowsMimeType(const QString &name) void MimeXMLProvider::addFileNameMatches(const QString &fileName, MimeGlobMatchResult &result) { - m_mimeTypeGlobs.matchingGlobs(fileName, result, m_overriddenMimeTypes); + auto filterFunc = [this](const QString &name) { + return !isMimeTypeGlobsExcluded(name) && !m_overriddenMimeTypes.contains(name); + }; + m_mimeTypeGlobs.matchingGlobs(fileName, result, filterFunc); } void MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr, QString *candidate) @@ -770,7 +781,6 @@ void MimeXMLProvider::ensureLoaded() m_parents.clear(); m_mimeTypeGlobs.clear(); m_magicMatchers.clear(); - m_mimeTypesWithDeletedGlobs.clear(); //qDebug() << "Loading" << m_allFiles; @@ -846,29 +856,9 @@ void MimeXMLProvider::addGlobPattern(const MimeGlobPattern &glob) void MimeXMLProvider::addMimeType(const MimeTypeXMLData &mt) { - if (mt.hasGlobDeleteAll) - appendIfNew(m_mimeTypesWithDeletedGlobs, mt.name); m_nameMimeTypeMap.insert(mt.name, mt); } -/* - \a toExclude is a list of mime type names that should have the the glob patterns - associated with them cleared (because there are mime types with the same names - in a higher precedence Provider that have glob-deleteall tags). - - This method is called from QMimeDatabasePrivate::loadProviders() to exclude mime - type glob patterns in lower precedence Providers. -*/ -void MimeXMLProvider::excludeMimeTypeGlobs(const QStringList &toExclude) -{ - for (const auto &mt : toExclude) { - auto it = m_nameMimeTypeMap.find(mt); - if (it != m_nameMimeTypeMap.end()) - it->globPatterns.clear(); - m_mimeTypeGlobs.removeMimeType(mt); - } -} - void MimeXMLProvider::addParents(const QString &mime, QStringList &result) { for (const QString &parent : m_parents.value(mime)) { diff --git a/src/libs/utils/mimetypes2/mimeprovider_p.h b/src/libs/utils/mimetypes2/mimeprovider_p.h index 33ffd67725c..b96034a4dc4 100644 --- a/src/libs/utils/mimetypes2/mimeprovider_p.h +++ b/src/libs/utils/mimetypes2/mimeprovider_p.h @@ -26,6 +26,7 @@ namespace Utils { class MimeMagicRuleMatcher; class MimeTypeXMLData; +class MimeProviderBase; class MimeProviderBase { @@ -50,10 +51,13 @@ public: virtual QString icon(const QString &name) = 0; virtual QString genericIcon(const QString &name) = 0; virtual void ensureLoaded() { } - virtual void excludeMimeTypeGlobs(const QStringList &) { } QString directory() const { return m_directory; } + MimeProviderBase *overrideProvider() const; + void setOverrideProvider(MimeProviderBase *provider); + bool isMimeTypeGlobsExcluded(const QString &name) const; + // added for Qt Creator virtual bool hasMimeTypeForName(const QString &name) = 0; virtual QStringList allMimeTypeNames() = 0; @@ -66,31 +70,7 @@ public: MimeDatabasePrivate *m_db; QString m_directory; - /* - MimeTypes with "glob-deleteall" tags are handled differently by each provider - sub-class: - - QMimeBinaryProvider parses glob-deleteall tags lazily, i.e. only when hasGlobDeleteAll() - is called, and clears the glob patterns associated with mimetypes that have this tag - - QMimeXMLProvider parses glob-deleteall from the start, i.e. when a XML file is - parsed with QMimeTypeParser - - The two lists below are used to let both provider types (XML and Binary) communicate - about mimetypes with glob-deleteall. - */ - /* - List of mimetypes in _this_ Provider that have a "glob-deleteall" tag, - glob patterns for those mimetypes should be ignored in all _other_ lower - precedence Providers. - */ - QStringList m_mimeTypesWithDeletedGlobs; - - /* - List of mimetypes with glob patterns that are "overwritten" in _this_ Provider, - by a "glob-deleteall" tag in a mimetype definition in a _higher precedence_ - Provider. With QMimeBinaryProvider, we can't change the data in the binary mmap'ed - file, hence the need for this list. - */ - QStringList m_mimeTypesWithExcludedGlobs; + MimeProviderBase *m_overrideProvider = nullptr; // more "local" than this one // for Qt Creator QSet m_overriddenMimeTypes; @@ -120,7 +100,6 @@ public: QString icon(const QString &name) override; QString genericIcon(const QString &name) override; void ensureLoaded() override; - void excludeMimeTypeGlobs(const QStringList &toExclude) override; // added for Qt Creator bool hasMimeTypeForName(const QString &name) override; @@ -142,7 +121,6 @@ private: const QString &fileName, qsizetype charPos, bool caseSensitiveCheck); - bool isMimeTypeGlobsExcluded(const char *name); bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data); QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime); @@ -203,7 +181,6 @@ public: // Called by the mimetype xml parser void addMimeType(const MimeTypeXMLData &mt); - void excludeMimeTypeGlobs(const QStringList &toExclude) override; void addGlobPattern(const MimeGlobPattern &glob); void addParent(const QString &child, const QString &parent); void addAlias(const QString &alias, const QString &name);