QMimeDatabase: fix handling of glob-deleteall
Binary provider: It was not possible to remove the first glob in a local override, because the mainPattern handling would re-add the first glob back. XML provider: It didn't support glob-deleteall. Also, the order of the providers was wrong. We want to pick local overrides first, the internal DB has to go last in the list. Fixes: QTBUG-85436 Pick-to: 5.15 Change-Id: I9a4523f37cd962c730df9a6ed992bd01c075bf03 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
ad9108e2e9
commit
fc8f5afc87
@ -101,27 +101,13 @@ void QMimeDatabasePrivate::loadProviders()
|
||||
const auto fdoIterator = std::find_if(mimeDirs.constBegin(), mimeDirs.constEnd(), [](const QString &mimeDir) -> bool {
|
||||
return QFileInfo::exists(mimeDir + QStringLiteral("/packages/freedesktop.org.xml")); }
|
||||
);
|
||||
const bool needInternalDB = QMimeXMLProvider::InternalDatabaseAvailable && fdoIterator == mimeDirs.constEnd();
|
||||
//qDebug() << "mime dirs:" << mimeDirs;
|
||||
|
||||
Providers currentProviders;
|
||||
std::swap(m_providers, currentProviders);
|
||||
|
||||
if (QMimeXMLProvider::InternalDatabaseAvailable && fdoIterator == mimeDirs.constEnd()) {
|
||||
m_providers.reserve(mimeDirs.size() + 1);
|
||||
// Check if we already have a provider for the InternalDatabase
|
||||
const auto isInternal = [](const std::unique_ptr<QMimeProviderBase> &prov)
|
||||
{
|
||||
return prov && prov->isInternalDatabase();
|
||||
};
|
||||
const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), isInternal);
|
||||
if (it == currentProviders.end()) {
|
||||
m_providers.push_back(Providers::value_type(new QMimeXMLProvider(this, QMimeXMLProvider::InternalDatabase)));
|
||||
} else {
|
||||
m_providers.push_back(std::move(*it));
|
||||
}
|
||||
} else {
|
||||
m_providers.reserve(mimeDirs.size());
|
||||
}
|
||||
m_providers.reserve(mimeDirs.size() + (needInternalDB ? 1 : 0));
|
||||
|
||||
for (const QString &mimeDir : mimeDirs) {
|
||||
const QString cacheFile = mimeDir + QStringLiteral("/mime.cache");
|
||||
@ -158,6 +144,21 @@ void QMimeDatabasePrivate::loadProviders()
|
||||
m_providers.push_back(std::move(provider));
|
||||
}
|
||||
}
|
||||
// mimeDirs is sorted "most local first, most global last"
|
||||
// so the internal XML DB goes at the end
|
||||
if (needInternalDB) {
|
||||
// Check if we already have a provider for the InternalDatabase
|
||||
const auto isInternal = [](const std::unique_ptr<QMimeProviderBase> &prov)
|
||||
{
|
||||
return prov && prov->isInternalDatabase();
|
||||
};
|
||||
const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), isInternal);
|
||||
if (it == currentProviders.end()) {
|
||||
m_providers.push_back(Providers::value_type(new QMimeXMLProvider(this, QMimeXMLProvider::InternalDatabase)));
|
||||
} else {
|
||||
m_providers.push_back(std::move(*it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QMimeDatabasePrivate::Providers &QMimeDatabasePrivate::providers()
|
||||
@ -215,7 +216,6 @@ QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName)
|
||||
QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileName)
|
||||
{
|
||||
QMimeGlobMatchResult result;
|
||||
// TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
|
||||
for (const auto &provider : providers())
|
||||
provider->addFileNameMatches(fileName, result);
|
||||
return result;
|
||||
|
@ -542,6 +542,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
|
||||
data.iconName = xml.attributes().value(QLatin1String("name")).toString();
|
||||
} else if (tag == QLatin1String("glob-deleteall")) { // as written out by shared-mime-info >= 0.70
|
||||
data.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('*'))) {
|
||||
|
@ -63,6 +63,7 @@ static const char genericIconTagC[] = "generic-icon";
|
||||
static const char iconTagC[] = "icon";
|
||||
static const char nameAttributeC[] = "name";
|
||||
static const char globTagC[] = "glob";
|
||||
static const char globDeleteAllTagC[] = "glob-deleteall";
|
||||
static const char aliasTagC[] = "alias";
|
||||
static const char patternAttributeC[] = "pattern";
|
||||
static const char weightAttributeC[] = "weight";
|
||||
@ -123,6 +124,7 @@ QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState curren
|
||||
case ParseGenericIcon:
|
||||
case ParseIcon:
|
||||
case ParseGlobPattern:
|
||||
case ParseGlobDeleteAll:
|
||||
case ParseSubClass:
|
||||
case ParseAlias:
|
||||
case ParseOtherMimeTypeSubTag:
|
||||
@ -137,6 +139,8 @@ QMimeTypeParserBase::ParseState QMimeTypeParserBase::nextState(ParseState curren
|
||||
return ParseIcon;
|
||||
if (startElement == QLatin1String(globTagC))
|
||||
return ParseGlobPattern;
|
||||
if (startElement == QLatin1String(globDeleteAllTagC))
|
||||
return ParseGlobDeleteAll;
|
||||
if (startElement == QLatin1String(subClassTagC))
|
||||
return ParseSubClass;
|
||||
if (startElement == QLatin1String(aliasTagC))
|
||||
@ -242,6 +246,9 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
|
||||
data.addGlobPattern(pattern); // just for QMimeType::globPatterns()
|
||||
}
|
||||
break;
|
||||
case ParseGlobDeleteAll:
|
||||
data.globPatterns.clear();
|
||||
break;
|
||||
case ParseSubClass: {
|
||||
const QString inheritsFrom = atts.value(QLatin1String(mimeTypeAttributeC)).toString();
|
||||
if (!inheritsFrom.isEmpty())
|
||||
|
@ -90,6 +90,7 @@ private:
|
||||
ParseGenericIcon,
|
||||
ParseIcon,
|
||||
ParseGlobPattern,
|
||||
ParseGlobDeleteAll,
|
||||
ParseSubClass,
|
||||
ParseAlias,
|
||||
ParseMagic,
|
||||
|
@ -985,11 +985,10 @@ void tst_QMimeDatabase::installNewGlobalMimeType()
|
||||
QCOMPARE(db.mimeTypeForFile(qmlTestFile).name(),
|
||||
QString::fromLatin1("text/x-qml"));
|
||||
|
||||
// ensure we can access the empty glob list
|
||||
{
|
||||
QMimeType objcsrc = db.mimeTypeForName(QStringLiteral("text/x-objcsrc"));
|
||||
QVERIFY(objcsrc.isValid());
|
||||
qDebug() << objcsrc.globPatterns();
|
||||
QCOMPARE(objcsrc.globPatterns(), QStringList());
|
||||
}
|
||||
|
||||
const QString fooTestFile = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy.foo");
|
||||
@ -1066,6 +1065,12 @@ void tst_QMimeDatabase::installNewLocalMimeType()
|
||||
QCOMPARE(db.mimeTypeForName(QLatin1String("text/x-SuSE-ymu")).comment(), QString("URL of a YaST Meta Package"));
|
||||
checkHasMimeType("text/x-suse-ymp");
|
||||
|
||||
{ // QTBUG-85436
|
||||
QMimeType objcsrc = db.mimeTypeForName(QStringLiteral("text/x-objcsrc"));
|
||||
QVERIFY(objcsrc.isValid());
|
||||
QCOMPARE(objcsrc.globPatterns(), QStringList());
|
||||
}
|
||||
|
||||
// Test that a double-definition of a mimetype doesn't lead to sniffing ("conflicting globs").
|
||||
const QString qmlTestFile = QLatin1String(RESOURCE_PREFIX "test.qml");
|
||||
QVERIFY2(!qmlTestFile.isEmpty(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user