kio: PreviewJobPrivate::startPreview() rewrite

mostly to make the MIME types check consistent by using KMimeType::is()
for the comparison (as done by KPreviewPropsPlugin::supports() for example)
and to filter the ThumbCreator service type (to avoid invalid KMimeType
checks)

fixed KFileMetaInfo regression for plugins that use globs aswell

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-11-26 01:07:12 +02:00
parent 27de045733
commit 2e6f3fba02
2 changed files with 70 additions and 49 deletions

View file

@ -36,24 +36,17 @@
static const KFileMetaInfoItem nullitem;
static KFileMetaInfoItem mutablenullitem;
static QStringList expandMimeTypes(const QStringList &mimetypes)
// NOTE: same as kdelibs/kio/kio/previewjob.cpp except the service string
static QStringList kMetaGlobMimeTypes(const QStringList &servicetypes)
{
static const QString kfimetadatapluginservice("KFileMetaData/Plugin");
QStringList result;
foreach (const QString &mime, mimetypes) {
if (mime.endsWith(QLatin1String("/*"))) {
const QString mimeglob = mime.mid(0, mime.size() - 2);
foreach (const KMimeType::Ptr &kmimetype, KMimeType::allMimeTypes()) {
// NOTE: it may be null during sycoca database update
if (kmimetype.isNull()) {
continue;
}
if (kmimetype->name().startsWith(mimeglob)) {
result.append(kmimetype->name());
}
}
} else {
result.append(mime);
foreach (const QString &servicetype, servicetypes) {
if (servicetype == kfimetadatapluginservice) {
continue;
}
result.append(servicetype);
}
// qDebug() << Q_FUNC_INFO << result;
return result;
@ -86,8 +79,20 @@ void KFileMetaInfoPrivate::init(const QString &filename, const KUrl &url, KFileM
const bool enable = pluginsgroup.readEntry(key, true);
if (enable) {
// qDebug() << Q_FUNC_INFO << filemimetype->name() << kfmdplugin->mimeTypes();
foreach (const QString &kfmdpluginmime, expandMimeTypes(kfmdplugin->mimeTypes())) {
if (filemimetype->is(kfmdpluginmime)) {
foreach (const QString &kfmdpluginmime, kMetaGlobMimeTypes(kfmdplugin->serviceTypes())) {
bool mimematches = false;
if (kfmdpluginmime.endsWith('*')) {
const QString kfmdpluginmimeglob = kfmdpluginmime.mid(0, kfmdpluginmime.size() - 1);
if (filemimetype && filemimetype->name().startsWith(kfmdpluginmimeglob)) {
mimematches = true;
}
}
if (!mimematches && filemimetype->is(kfmdpluginmime)) {
mimematches = true;
}
if (mimematches) {
KFileMetaDataPlugin *kfmdplugininstance = kfmdplugin->createInstance<KFileMetaDataPlugin>();
if (kfmdplugininstance) {
items.append(kfmdplugininstance->metaData(url, w));

View file

@ -69,6 +69,23 @@ struct KIO::PreviewItem
KService::Ptr plugin;
};
// NOTE: because KService::mimeTypes() validates the MIME types and some thumbnailers use globs
// (such as video/*) which are not valid, KService::serviceTypes() is used to get the unfiltered
// MIME types and then the service type is removed from the list
static QStringList kThumbGlobMimeTypes(const QStringList &servicetypes)
{
static const QString thumbcreatorservce("ThumbCreator");
QStringList result;
foreach (const QString &servicetype, servicetypes) {
if (servicetype == thumbcreatorservce) {
continue;
}
result.append(servicetype);
}
return result;
}
class KIO::PreviewJobPrivate: public KIO::JobPrivate
{
public:
@ -241,13 +258,16 @@ void PreviewJobPrivate::startPreview()
Q_Q(PreviewJob);
// Load the list of plugins to determine which mimetypes are supported
const KService::List plugins = KServiceTypeTrader::self()->query("ThumbCreator");
QMap<QString, KService::Ptr> mimeMap;
for (KService::List::ConstIterator it = plugins.constBegin(); it != plugins.constEnd(); ++it) {
if (enabledPlugins.contains((*it)->desktopEntryName())) {
const QStringList mimeTypes = (*it)->serviceTypes();
for (QStringList::ConstIterator mt = mimeTypes.constBegin(); mt != mimeTypes.constEnd(); ++mt) {
mimeMap.insert(*mt, *it);
// Map their MIME types
QHash<QString, KService::Ptr> mimesMap;
foreach (const KService::Ptr plugin, plugins) {
if (enabledPlugins.contains(plugin->desktopEntryName())) {
foreach (const QString &pluginmime, kThumbGlobMimeTypes(plugin->serviceTypes())) {
mimesMap.insert(pluginmime, plugin);
}
} else {
kDebug() << "Plugin is disabled" << plugin->desktopEntryName();
}
}
@ -256,45 +276,41 @@ void PreviewJobPrivate::startPreview()
foreach (const KFileItem &kit, initialItems) {
PreviewItem item;
item.item = kit;
const QString mimeType = item.item.mimetype();
KService::Ptr plugin(0);
const QString itemmime = item.item.mimetype();
KService::Ptr itemplugin(0);
if (!plugin) {
QMap<QString, KService::Ptr>::ConstIterator pluginIt = mimeMap.constFind(mimeType);
if (pluginIt == mimeMap.constEnd()) {
QString groupMimeType = mimeType;
groupMimeType.replace(QRegExp("/.*"), "/*");
pluginIt = mimeMap.constFind(groupMimeType);
if (pluginIt == mimeMap.constEnd()) {
// check mime type inheritance, resolve aliases
const KMimeType::Ptr mimeInfo = KMimeType::mimeType(mimeType);
if (mimeInfo) {
const QStringList parentMimeTypes = mimeInfo->allParentMimeTypes();
Q_FOREACH(const QString& parentMimeType, parentMimeTypes) {
pluginIt = mimeMap.constFind(parentMimeType);
if (pluginIt != mimeMap.constEnd())
break;
}
}
QHash<QString, KService::Ptr>::ConstIterator it = mimesMap.constBegin();
while (it != mimesMap.constEnd()) {
const QString pluginmime = it.key();
if (pluginmime.endsWith('*')) {
const QString globmime = pluginmime.mid(0, pluginmime.size() - 1);
if (itemmime.startsWith(globmime)) {
itemplugin = it.value();
kDebug() << "Glob match for" << itemmime << itemplugin->library();
break;
}
}
if (pluginIt != mimeMap.constEnd()) {
plugin = *pluginIt;
const KMimeType::Ptr mimeInfo = KMimeType::mimeType(pluginmime);
if (mimeInfo && mimeInfo->is(itemmime)) {
itemplugin = it.value();
kDebug() << "MIME match for" << itemmime << itemplugin->library();
break;
}
it++;
}
if (plugin) {
item.plugin = plugin;
if (itemplugin) {
item.plugin = itemplugin;
items.append(item);
if (!bNeedCache && bSave &&
(kit.url().protocol() != "file" ||
!kit.url().directory( KUrl::AppendTrailingSlash ).startsWith(thumbRoot)) &&
plugin->property("CacheThumbnail").toBool()) {
itemplugin->property("CacheThumbnail").toBool()) {
bNeedCache = true;
}
} else {
kDebug() << "No match for" << itemmime << enabledPlugins;
emit q->failed(kit);
}
}
@ -578,7 +594,7 @@ QStringList PreviewJob::supportedMimeTypes()
QStringList result;
const KService::List plugins = KServiceTypeTrader::self()->query("ThumbCreator");
for (KService::List::ConstIterator it = plugins.begin(); it != plugins.end(); ++it) {
result += (*it)->serviceTypes();
result += kThumbGlobMimeTypes((*it)->serviceTypes());
}
return result;
}