diff --git a/autotests/extractorcollectiontest.cpp b/autotests/extractorcollectiontest.cpp --- a/autotests/extractorcollectiontest.cpp +++ b/autotests/extractorcollectiontest.cpp @@ -68,6 +68,22 @@ QVERIFY(!xmlExtractors.contains(extractor)); } } + + void testBestMatching() + { + QCoreApplication::setLibraryPaths({QCoreApplication::applicationDirPath()}); + ExtractorCollection collection; + + auto textExtractors = collection.fetchExtractors("text/plain"); + auto xmlSubtypeExtractors = collection.fetchExtractors("application/x-kvtml"); + QVERIFY(!xmlSubtypeExtractors.isEmpty()); + + // Verify the generic "text/plain" extractor is also not used for + // types inherited from "application/xml" + for (auto extractor : textExtractors) { + QVERIFY(!xmlSubtypeExtractors.contains(extractor)); + } + } }; QTEST_GUILESS_MAIN(ExtractorCollectionTest) diff --git a/src/extractorcollection.h b/src/extractorcollection.h --- a/src/extractorcollection.h +++ b/src/extractorcollection.h @@ -48,8 +48,10 @@ * Fetch the extractors which can be used to extract * data for the respective file with the given mimetype. * - * If no match is found then all the plugins whose mimetype list - * starts with \p mimetype are returned. + * If no match is found then the best matching plugins + * are returned, determined by mimetype inheritance. + * + * \sa QMimeType::allAncestors */ QList fetchExtractors(const QString& mimetype) const; diff --git a/src/extractorcollection.cpp b/src/extractorcollection.cpp --- a/src/extractorcollection.cpp +++ b/src/extractorcollection.cpp @@ -148,17 +148,20 @@ QList ExtractorCollection::fetchExtractors(const QString& mimetype) const { QList plugins = d->m_extractors.values(mimetype); - if (plugins.isEmpty()) { - QMimeDatabase db; - auto type = db.mimeTypeForName(mimetype); - auto it = d->m_extractors.constBegin(); - for (; it != d->m_extractors.constEnd(); ++it) { - if (plugins.contains(it.value())) { - continue; - } - if (type.inherits(it.key())) { - plugins << it.value(); - } + if (!plugins.isEmpty()) { + return plugins; + } + + // try to find the best matching more generic extractor by mimetype inheritance + QMimeDatabase db; + auto type = db.mimeTypeForName(mimetype); + const QStringList ancestors = type.allAncestors(); + + for (auto ancestor : ancestors) { + QList plugins = d->m_extractors.values(ancestor); + if (!plugins.isEmpty()) { + qCDebug(KFILEMETADATA_LOG) << "Using inherited mimetype" << ancestor << "for" << mimetype; + return plugins; } }