Update mime database from Qt

qtbase/9547ef58c707a11d5affcbcfa553f3aca5334087
  QMimeDatabase: handle glob-deleteall tags

Change-Id: I8aebb6de340a51c978730b6ca0dba2ba9ce3460f
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
This commit is contained in:
Eike Ziller
2024-08-27 14:43:35 +02:00
parent e4431beb8c
commit 910471489a
5 changed files with 93 additions and 1 deletions

View File

@@ -194,6 +194,19 @@ void MimeDatabasePrivate::loadProviders()
}
}
// Handle mimetypes with glob-deleteall tags (from XML providers)
auto it = m_providers.begin();
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);
}
updateOverriddenMimeTypes(m_providers);
}

View File

@@ -51,6 +51,12 @@ using namespace Qt::StringLiterals;
namespace Utils {
static inline void appendIfNew(QStringList &list, const QString &str)
{
if (!list.contains(str))
list.push_back(str);
}
MimeProviderBase::MimeProviderBase(MimeDatabasePrivate *db, const QString &directory)
: m_db(db), m_directory(directory)
{
@@ -241,6 +247,17 @@ void MimeBinaryProvider::addFileNameMatches(const QString &fileName, MimeGlobMat
matchGlobList(result, m_cacheFile, m_cacheFile->getUint32(PosGlobListOffset), 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);
}
void MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result,
CacheFile *cacheFile,
int off,
@@ -261,8 +278,10 @@ void MimeBinaryProvider::matchGlobList(MimeGlobMatchResult &result,
if (m_overriddenMimeTypes.contains(QLatin1String(mimeType)))
continue;
//qDebug() << pattern << mimeType << weight << caseSensitive;
MimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive);
if (isMimeTypeGlobsExcluded(mimeType))
continue;
MimeGlobPattern glob(pattern, QString() /*unused*/, weight, qtCaseSensitive);
if (glob.matchFileName(fileName))
result.addMatch(QLatin1StringView(mimeType), weight, pattern);
}
@@ -308,6 +327,8 @@ bool MimeBinaryProvider::matchSuffixTree(MimeGlobMatchResult &result,
break;
const int mimeTypeOffset = cacheFile->getUint32(childOff + 4);
const char *mimeType = cacheFile->getCharStar(mimeTypeOffset);
if (isMimeTypeGlobsExcluded(mimeType))
continue;
if (m_overriddenMimeTypes.contains(QLatin1String(mimeType)))
continue;
const int flagsAndWeight = cacheFile->getUint32(childOff + 8);
@@ -760,6 +781,7 @@ void MimeXMLProvider::ensureLoaded()
m_parents.clear();
m_mimeTypeGlobs.clear();
m_magicMatchers.clear();
m_mimeTypesWithDeletedGlobs.clear();
//qDebug() << "Loading" << m_allFiles;
@@ -811,9 +833,31 @@ void MimeXMLProvider::addGlobPattern(const MimeGlobPattern &glob)
void MimeXMLProvider::addMimeType(const MimeType &mt)
{
Q_ASSERT(!mt.d.data()->fromCache);
QString name = mt.name();
if (mt.d->hasGlobDeleteAll)
appendIfNew(m_mimeTypesWithDeletedGlobs, 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->d->globPatterns.clear();
m_mimeTypeGlobs.removeMimeType(mt);
}
}
void MimeXMLProvider::addParents(const QString &mime, QStringList &result)
{
for (const QString &parent : m_parents.value(mime)) {

View File

@@ -45,6 +45,7 @@ public:
virtual void loadIcon(MimeTypePrivate &) {}
virtual void loadGenericIcon(MimeTypePrivate &) {}
virtual void ensureLoaded() {}
virtual void excludeMimeTypeGlobs(const QStringList &) {}
QString directory() const { return m_directory; }
@@ -59,6 +60,34 @@ 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 loadMimeTypePrivate()
is called, and clears the glob patterns associated with mimetypes that have this tag
- QMimeXMLProvider parses glob-deleteall from the 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;
// for Qt Creator
QSet<QString> m_overriddenMimeTypes;
};
@@ -84,6 +113,7 @@ public:
void loadIcon(MimeTypePrivate &) override;
void loadGenericIcon(MimeTypePrivate &) override;
void ensureLoaded() override;
void excludeMimeTypeGlobs(const QStringList &toExclude) override;
// added for Qt Creator
bool hasMimeTypeForName(const QString &name) override;
@@ -108,6 +138,7 @@ private:
qsizetype charPos,
bool caseSensitiveCheck);
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
bool isMimeTypeGlobsExcluded(const char *name);
QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
void loadMimeTypeList();
bool checkCacheChanged();
@@ -118,6 +149,7 @@ private:
bool m_mimetypeListLoaded;
struct MimeTypeExtra
{
// Both retrieved on demand in loadMimeTypePrivate
QHash<QString, QString> localeComments;
QStringList globPatterns;
};
@@ -157,6 +189,7 @@ public:
// Called by the mimetype xml parser
void addMimeType(const MimeType &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);

View File

@@ -35,6 +35,7 @@ public:
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
bool hasGlobDeleteAll = false; // true if the mimetype has a glob-deleteall tag
QString name;
LocaleHash localeComments;
QString genericIconName;

View File

@@ -213,6 +213,7 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
break;
case ParseGlobDeleteAll:
data.globPatterns.clear();
data.hasGlobDeleteAll = true;
break;
case ParseSubClass: {
const QString inheritsFrom = atts.value(QLatin1StringView(mimeTypeAttributeC)).toString();