From 5b98fcf7f9e031c177a175066fcc46b0cd0939bf Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 24 Feb 2015 12:13:05 +0100 Subject: [PATCH] Mime types: Fix opening files with mime types with multiple inheritance It was opening e.g. ruby files in the binary editor because the ruby mime type inherits from application/x-executable (which inherits from application/octet-stream) as well as text/plain, and it was searching depth-first. Task-number: QTCREATORBUG-13996 Change-Id: I1980d7ed04fabf111f8fb76df657225ae9ebe552 Reviewed-by: Orgad Shaneh --- .../editormanager/editormanager.cpp | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 39b24cb0582..fd27a5f253d 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -2195,36 +2195,42 @@ IEditor *EditorManager::activateEditorForDocument(IDocument *document, OpenEdito * or IExternalEditor), find the one best matching the mimetype passed in. * Recurse over the parent classes of the mimetype to find them. */ template -static void mimeTypeFactoryRecursion(const Utils::MimeType &mimeType, +static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType, const QList &allFactories, bool firstMatchOnly, QList *list) { - typedef typename QList::const_iterator EditorFactoryLikeListConstIterator; - // Loop factories to find type - const EditorFactoryLikeListConstIterator fcend = allFactories.constEnd(); - for (EditorFactoryLikeListConstIterator fit = allFactories.constBegin(); fit != fcend; ++fit) { - // Exclude duplicates when recursing over xml or C++ -> C -> text. - EditorFactoryLike *factory = *fit; - if (!list->contains(factory)) { - foreach (const QString &mt, factory->mimeTypes()) { - if (mimeType.matchesName(mt)) { - list->push_back(*fit); - if (firstMatchOnly) - return; + Utils::MimeDatabase mdb; + QSet matches; + // search breadth-first through parent hierarchy, e.g. for hierarchy + // * application/x-ruby + // * application/x-executable + // * application/octet-stream + // * text/plain + QList queue; + queue.append(mimeType); + while (!queue.isEmpty()) { + Utils::MimeType mt = queue.takeFirst(); + // check for matching factories + foreach (EditorFactoryLike *factory, allFactories) { + if (!matches.contains(factory)) { + foreach (const QString &mimeName, factory->mimeTypes()) { + if (mt.matchesName(mimeName)) { + list->append(factory); + if (firstMatchOnly) + return; + matches.insert(factory); + } } } } - } - // Any parent mime type classes? -> recurse - QStringList parentNames = mimeType.parentMimeTypes(); - if (parentNames.empty()) - return; - Utils::MimeDatabase mdb; - foreach (const QString &parentName, parentNames) { - const Utils::MimeType parent = mdb.mimeTypeForName(parentName); - if (parent.isValid()) - mimeTypeFactoryRecursion(parent, allFactories, firstMatchOnly, list); + // add parent mime types + QStringList parentNames = mt.parentMimeTypes(); + foreach (const QString &parentName, parentNames) { + const Utils::MimeType parent = mdb.mimeTypeForName(parentName); + if (parent.isValid()) + queue.append(parent); + } } } @@ -2233,7 +2239,7 @@ EditorManager::EditorFactoryList { EditorFactoryList rc; const EditorFactoryList allFactories = ExtensionSystem::PluginManager::getObjects(); - mimeTypeFactoryRecursion(mimeType, allFactories, bestMatchOnly, &rc); + mimeTypeFactoryLookup(mimeType, allFactories, bestMatchOnly, &rc); if (debugEditorManager) qDebug() << Q_FUNC_INFO << mimeType.name() << " returns " << rc; return rc; @@ -2244,7 +2250,7 @@ EditorManager::ExternalEditorList { ExternalEditorList rc; const ExternalEditorList allEditors = ExtensionSystem::PluginManager::getObjects(); - mimeTypeFactoryRecursion(mimeType, allEditors, bestMatchOnly, &rc); + mimeTypeFactoryLookup(mimeType, allEditors, bestMatchOnly, &rc); if (debugEditorManager) qDebug() << Q_FUNC_INFO << mimeType.name() << " returns " << rc; return rc;