File indexing completed on 2024-05-05 16:09:04

0001 /*
0002     This file is part of the KFileMetaData project
0003     SPDX-FileCopyrightText: 2016 Varun Joshi <varunj.1011@gmail.com>
0004     SPDX-FileCopyrightText: 2016 Vishesh Handa <me@vhanda.in>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "writercollection.h"
0010 #include "writer_p.h"
0011 #include "writerplugin.h"
0012 #include "externalwriter.h"
0013 #include "kfilemetadata_debug.h"
0014 #include "config-kfilemetadata.h"
0015 
0016 #include <KPluginMetaData>
0017 #include <QCoreApplication>
0018 #include <QDir>
0019 #include <QMimeDatabase>
0020 #include <QPluginLoader>
0021 #include <vector>
0022 
0023 using namespace KFileMetaData;
0024 
0025 class KFileMetaData::WriterCollectionPrivate
0026 {
0027 public:
0028     QMultiHash<QString, Writer*> m_writers;
0029 
0030     std::vector<Writer> m_allWriters;
0031 
0032     void findWriters();
0033 };
0034 
0035 WriterCollection::WriterCollection()
0036     : d(new WriterCollectionPrivate)
0037 {
0038     d->findWriters();
0039 }
0040 
0041 WriterCollection::~WriterCollection() = default;
0042 
0043 void WriterCollectionPrivate::findWriters()
0044 {
0045     const auto internalPlugins = KPluginMetaData::findPlugins(QStringLiteral("kf" QT_STRINGIFY(QT_VERSION_MAJOR)) + QStringLiteral("/kfilemetadata/writers"), {}, KPluginMetaData::AllowEmptyMetaData);
0046 
0047     for (const KPluginMetaData &metaData : internalPlugins) {
0048         QPluginLoader loader(metaData.fileName());
0049         if (QObject *obj = loader.instance()) {
0050             if (WriterPlugin *plugin = qobject_cast<WriterPlugin *>(obj)) {
0051                 Writer writer;
0052                 writer.d->m_plugin = plugin;
0053                 writer.setAutoDeletePlugin(Writer::DoNotDeletePlugin);
0054 
0055                 m_allWriters.push_back(std::move(writer));
0056             } else {
0057                 qCDebug(KFILEMETADATA_LOG) << "Plugin could not be converted to a WriterPlugin";
0058                 qCDebug(KFILEMETADATA_LOG) << metaData.fileName();
0059             }
0060         } else {
0061             qCDebug(KFILEMETADATA_LOG) << "Plugin could not create instance" << metaData.fileName();
0062         }
0063     }
0064 
0065     QStringList externalPlugins;
0066     QStringList externalPluginPaths;
0067     QDir externalPluginDir(QStringLiteral(LIBEXEC_INSTALL_DIR) + QStringLiteral("/kfilemetadata/writers/externalwriters"));
0068     // For external plugins, we look into the directories. Those are executables and not C++ plugins.
0069     const QStringList externalPluginEntryList = externalPluginDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
0070     for (const QString& externalPlugin : externalPluginEntryList) {
0071         if (externalPlugins.contains(externalPlugin)) {
0072             continue;
0073         }
0074 
0075         externalPlugins << externalPlugin;
0076         externalPluginPaths << externalPluginDir.absoluteFilePath(externalPlugin);
0077     }
0078 
0079     for (const QString& externalPluginPath : std::as_const(externalPluginPaths)) {
0080         ExternalWriter *plugin = new ExternalWriter(externalPluginPath);
0081         Writer writer;
0082         writer.d->m_plugin = plugin;
0083         writer.setAutoDeletePlugin(Writer::AutoDeletePlugin);
0084 
0085         m_allWriters.push_back(std::move(writer));
0086     }
0087 
0088     for (Writer& writer : m_allWriters) {
0089         const QStringList lst = writer.mimetypes();
0090         for (const QString& type : lst) {
0091             m_writers.insert(type, &writer);
0092         }
0093     }
0094 }
0095 
0096 QList<Writer*> WriterCollection::fetchWriters(const QString& mimetype) const
0097 {
0098     QList<Writer*> plugins = d->m_writers.values(mimetype);
0099     if (!plugins.isEmpty()) {
0100         return plugins;
0101     }
0102 
0103     // try to find the best matching more generic writer by mimetype inheritance
0104     QMimeDatabase db;
0105     auto type = db.mimeTypeForName(mimetype);
0106     const QStringList ancestors = type.allAncestors();
0107 
0108     for (const auto &ancestor : ancestors) {
0109         if (ancestor == QLatin1String("application/octet-stream")) {
0110             continue;
0111         }
0112         QList<Writer*> plugins = d->m_writers.values(ancestor);
0113         if (!plugins.isEmpty()) {
0114             qCDebug(KFILEMETADATA_LOG) << "Using inherited mimetype" << ancestor <<  "for" << mimetype;
0115             return plugins;
0116         }
0117     }
0118 
0119     return plugins;
0120 }
0121 
0122 
0123