MimeDatabase: Prevent funny mixing of different mime type definitions

If multiple definitions for the same mime type are found, the mime XML
parser/provider would on the one hand replace the first MimeType instance
by the later one, but on the other hand keep all previously parsed glob
and magic matchers from the first definition.

The patch
- makes the XML parser ignore definitions of mime types that are already
defined
- parses custom types first, so custom types can override types from
freedesktop.org.xml

This fixes opening Cmake projects (CMakeLists.txt) in Qt Creator,
because freedesktop.org.xml defines these files to be x-cmake, but
we need them to be x-cmake-project.

Change-Id: Ia5598c2d0201f608aed6ae8c3268f0512d822f51
Reviewed-by: Daniel Teske <daniel.teske@theqtcompany.com>
This commit is contained in:
Eike Ziller
2015-02-18 15:16:57 +01:00
parent 839d226d70
commit d877f0983d
3 changed files with 32 additions and 18 deletions

View File

@@ -833,7 +833,8 @@ void MimeXMLProvider::ensureLoaded()
{
if (!m_loaded /*|| shouldCheck()*/) {
// bool fdoXmlFound = false;
QStringList allFiles;
// add custom mime types first, which overrides any default from freedesktop.org.xml
QStringList allFiles = m_additionalFiles;
// const QStringList packageDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"), QStandardPaths::LocateDirectory);
// //qDebug() << "packageDirs=" << packageDirs;
@@ -851,11 +852,9 @@ void MimeXMLProvider::ensureLoaded()
// if (!fdoXmlFound) {
// // We could instead install the file as part of installing Qt?
allFiles.prepend(QLatin1String(":/qt-project.org/qmime/freedesktop.org.xml"));
allFiles.append(QLatin1String(":/qt-project.org/qmime/freedesktop.org.xml"));
// }
allFiles.append(m_additionalFiles);
if (m_allFiles == allFiles)
return;
m_allFiles = allFiles;

View File

@@ -210,9 +210,12 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
QXmlStreamReader reader(dev);
ParseState ps = ParseBeginning;
QXmlStreamAttributes atts;
bool ignoreCurrentMimeType = false;
while (!reader.atEnd()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement:
if (ignoreCurrentMimeType)
continue;
ps = nextState(ps, reader.name());
atts = reader.attributes();
switch (ps) {
@@ -221,7 +224,10 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
if (name.isEmpty()) {
reader.raiseError(QString::fromLatin1("Missing '%1'-attribute").arg(QString::fromLatin1(mimeTypeAttributeC)));
} else {
data.name = name;
if (mimeTypeExists(name))
ignoreCurrentMimeType = true;
else
data.name = name;
}
}
break;
@@ -307,20 +313,25 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
{
const QStringRef elementName = reader.name();
if (elementName == QLatin1String(mimeTypeTagC)) {
if (!process(MimeType(data), errorMessage))
return false;
if (!ignoreCurrentMimeType) {
if (!process(MimeType(data), errorMessage))
return false;
}
ignoreCurrentMimeType = false;
data.clear();
} else if (elementName == QLatin1String(matchTagC)) {
// Closing a <match> tag, pop stack
currentRules.pop();
//qDebug() << " MATCH closed. Stack size is now" << currentRules.size();
} else if (elementName == QLatin1String(magicTagC)) {
//qDebug() << "MAGIC ended, we got" << rules.count() << "rules, with prio" << priority;
// Finished a <magic> sequence
MimeMagicRuleMatcher ruleMatcher(data.name, priority);
ruleMatcher.addRules(rules);
processMagicMatcher(ruleMatcher);
rules.clear();
} else if (!ignoreCurrentMimeType) {
if (elementName == QLatin1String(matchTagC)) {
// Closing a <match> tag, pop stack
currentRules.pop();
//qDebug() << " MATCH closed. Stack size is now" << currentRules.size();
} else if (elementName == QLatin1String(magicTagC)) {
//qDebug() << "MAGIC ended, we got" << rules.count() << "rules, with prio" << priority;
// Finished a <magic> sequence
MimeMagicRuleMatcher ruleMatcher(data.name, priority);
ruleMatcher.addRules(rules);
processMagicMatcher(ruleMatcher);
rules.clear();
}
}
break;
}

View File

@@ -67,6 +67,7 @@ public:
bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage);
protected:
virtual bool mimeTypeExists(const QString &mimeTypeName) = 0;
virtual bool process(const MimeType &t, QString *errorMessage) = 0;
virtual bool process(const MimeGlobPattern &t, QString *errorMessage) = 0;
virtual void processParent(const QString &child, const QString &parent) = 0;
@@ -100,6 +101,9 @@ public:
explicit MimeTypeParser(MimeXMLProvider &provider) : m_provider(provider) {}
protected:
inline bool mimeTypeExists(const QString &mimeTypeName)
{ return m_provider.mimeTypeForName(mimeTypeName).isValid(); }
inline bool process(const MimeType &t, QString *)
{ m_provider.addMimeType(t); return true; }