| 1 | /* |
|---|---|
| 2 | This file is part of the KFileMetaData project |
| 3 | SPDX-FileCopyrightText: 2016 Varun Joshi <varunj.1011@gmail.com> |
| 4 | SPDX-FileCopyrightText: 2016 Vishesh Handa <me@vhanda.in> |
| 5 | |
| 6 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
| 7 | */ |
| 8 | |
| 9 | #include "writercollection.h" |
| 10 | #include "writer_p.h" |
| 11 | #include "writerplugin.h" |
| 12 | #include "externalwriter.h" |
| 13 | #include "kfilemetadata_debug.h" |
| 14 | #include "config-kfilemetadata.h" |
| 15 | |
| 16 | #include <KPluginMetaData> |
| 17 | #include <QCoreApplication> |
| 18 | #include <QDir> |
| 19 | #include <QMimeDatabase> |
| 20 | #include <QPluginLoader> |
| 21 | #include <vector> |
| 22 | |
| 23 | using namespace KFileMetaData; |
| 24 | |
| 25 | class KFileMetaData::WriterCollectionPrivate |
| 26 | { |
| 27 | public: |
| 28 | QMultiHash<QString, Writer*> m_writers; |
| 29 | |
| 30 | std::vector<Writer> m_allWriters; |
| 31 | |
| 32 | void findWriters(); |
| 33 | }; |
| 34 | |
| 35 | WriterCollection::WriterCollection() |
| 36 | : d(new WriterCollectionPrivate) |
| 37 | { |
| 38 | d->findWriters(); |
| 39 | } |
| 40 | |
| 41 | WriterCollection::~WriterCollection() = default; |
| 42 | |
| 43 | void WriterCollectionPrivate::findWriters() |
| 44 | { |
| 45 | const auto internalPlugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/kfilemetadata/writers"), filter: {}, options: KPluginMetaData::AllowEmptyMetaData); |
| 46 | |
| 47 | for (const KPluginMetaData &metaData : internalPlugins) { |
| 48 | QPluginLoader loader(metaData.fileName()); |
| 49 | if (QObject *obj = loader.instance()) { |
| 50 | if (WriterPlugin *plugin = qobject_cast<WriterPlugin *>(object: obj)) { |
| 51 | Writer writer; |
| 52 | writer.d->m_plugin = plugin; |
| 53 | writer.setAutoDeletePlugin(Writer::DoNotDeletePlugin); |
| 54 | |
| 55 | m_allWriters.push_back(x: std::move(writer)); |
| 56 | } else { |
| 57 | qCDebug(KFILEMETADATA_LOG) << "Plugin could not be converted to a WriterPlugin"; |
| 58 | qCDebug(KFILEMETADATA_LOG) << metaData.fileName(); |
| 59 | } |
| 60 | } else { |
| 61 | qCDebug(KFILEMETADATA_LOG) << "Plugin could not create instance"<< metaData.fileName(); |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | QStringList externalPlugins; |
| 66 | QStringList externalPluginPaths; |
| 67 | QDir externalPluginDir(QStringLiteral(LIBEXEC_INSTALL_DIR) + QStringLiteral("/kfilemetadata/writers/externalwriters")); |
| 68 | // For external plugins, we look into the directories. Those are executables and not C++ plugins. |
| 69 | const QStringList externalPluginEntryList = externalPluginDir.entryList(filters: QDir::Dirs | QDir::NoDotAndDotDot); |
| 70 | for (const QString& externalPlugin : externalPluginEntryList) { |
| 71 | if (externalPlugins.contains(str: externalPlugin)) { |
| 72 | continue; |
| 73 | } |
| 74 | |
| 75 | externalPlugins << externalPlugin; |
| 76 | externalPluginPaths << externalPluginDir.absoluteFilePath(fileName: externalPlugin); |
| 77 | } |
| 78 | |
| 79 | for (const QString& externalPluginPath : std::as_const(t&: externalPluginPaths)) { |
| 80 | ExternalWriter *plugin = new ExternalWriter(externalPluginPath); |
| 81 | Writer writer; |
| 82 | writer.d->m_plugin = plugin; |
| 83 | writer.setAutoDeletePlugin(Writer::AutoDeletePlugin); |
| 84 | |
| 85 | m_allWriters.push_back(x: std::move(writer)); |
| 86 | } |
| 87 | |
| 88 | for (Writer& writer : m_allWriters) { |
| 89 | const QStringList lst = writer.mimetypes(); |
| 90 | for (const QString& type : lst) { |
| 91 | m_writers.insert(key: type, value: &writer); |
| 92 | } |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | QList<Writer*> WriterCollection::fetchWriters(const QString& mimetype) const |
| 97 | { |
| 98 | QList<Writer*> plugins = d->m_writers.values(key: mimetype); |
| 99 | if (!plugins.isEmpty()) { |
| 100 | return plugins; |
| 101 | } |
| 102 | |
| 103 | // try to find the best matching more generic writer by mimetype inheritance |
| 104 | QMimeDatabase db; |
| 105 | auto type = db.mimeTypeForName(nameOrAlias: mimetype); |
| 106 | const QStringList ancestors = type.allAncestors(); |
| 107 | |
| 108 | for (const auto &ancestor : ancestors) { |
| 109 | if (ancestor == QLatin1String("application/octet-stream")) { |
| 110 | continue; |
| 111 | } |
| 112 | QList<Writer*> plugins = d->m_writers.values(key: ancestor); |
| 113 | if (!plugins.isEmpty()) { |
| 114 | qCDebug(KFILEMETADATA_LOG) << "Using inherited mimetype"<< ancestor << "for"<< mimetype; |
| 115 | return plugins; |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | return plugins; |
| 120 | } |
| 121 | |
| 122 | |
| 123 | |
| 124 |
