Changeset View
Changeset View
Standalone View
Standalone View
mimetreeparser/src/viewer/bodypartformatterfactory.cpp
- This file was moved from mimetreeparser/src/viewer/bodypartformatterbasefactory.cpp.
Show All 25 Lines | 1 | /* | |||
---|---|---|---|---|---|
26 | combinations including the two. You must obey the GNU General | 26 | combinations including the two. You must obey the GNU General | ||
27 | Public License in all respects for all of the code used other than | 27 | Public License in all respects for all of the code used other than | ||
28 | Qt. If you modify this file, you may extend this exception to | 28 | Qt. If you modify this file, you may extend this exception to | ||
29 | your version of the file, but you are not obligated to do so. If | 29 | your version of the file, but you are not obligated to do so. If | ||
30 | you do not wish to do so, delete this exception statement from | 30 | you do not wish to do so, delete this exception statement from | ||
31 | your version. | 31 | your version. | ||
32 | */ | 32 | */ | ||
33 | 33 | | |||
34 | #include "bodypartformatterbasefactory.h" | 34 | #include "bodypartformatterfactory.h" | ||
35 | #include "bodypartformatterbasefactory_p.h" | 35 | #include "bodypartformatterfactory_p.h" | ||
36 | #include "interfaces/bodypartformatter.h" | ||||
36 | #include "mimetreeparser_debug.h" | 37 | #include "mimetreeparser_debug.h" | ||
37 | 38 | | |||
39 | #include <KPluginLoader> | ||||
40 | | ||||
41 | #include <QJsonArray> | ||||
42 | #include <QJsonObject> | ||||
38 | #include <QMimeDatabase> | 43 | #include <QMimeDatabase> | ||
39 | #include <QMimeType> | 44 | #include <QMimeType> | ||
40 | 45 | | |||
41 | #include <assert.h> | 46 | #include <assert.h> | ||
42 | 47 | | |||
43 | using namespace MimeTreeParser; | 48 | using namespace MimeTreeParser; | ||
44 | 49 | | |||
45 | BodyPartFormatterBaseFactoryPrivate::BodyPartFormatterBaseFactoryPrivate(BodyPartFormatterBaseFactory *factory) | 50 | BodyPartFormatterFactoryPrivate::BodyPartFormatterFactoryPrivate(BodyPartFormatterFactory *factory) | ||
46 | : q(factory) | 51 | : q(factory) | ||
47 | { | 52 | { | ||
48 | } | 53 | } | ||
49 | 54 | | |||
50 | void BodyPartFormatterBaseFactoryPrivate::setup() | 55 | void BodyPartFormatterFactoryPrivate::setup() | ||
51 | { | 56 | { | ||
52 | if (registry.empty()) { | 57 | if (registry.empty()) { | ||
53 | messageviewer_create_builtin_bodypart_formatters(); | 58 | messageviewer_create_builtin_bodypart_formatters(); | ||
54 | q->loadPlugins(); | 59 | q->loadPlugins(); | ||
55 | } | 60 | } | ||
56 | assert(!registry.empty()); | 61 | assert(!registry.empty()); | ||
57 | } | 62 | } | ||
58 | 63 | | |||
59 | void BodyPartFormatterBaseFactoryPrivate::insert(const QString &mimeType, const Interface::BodyPartFormatter *formatter, int priority) | 64 | void BodyPartFormatterFactoryPrivate::insert(const QString &mimeType, const Interface::BodyPartFormatter *formatter, int priority) | ||
60 | { | 65 | { | ||
61 | if (mimeType.isEmpty() || !formatter) { | 66 | if (mimeType.isEmpty() || !formatter) { | ||
62 | return; | 67 | return; | ||
63 | } | 68 | } | ||
64 | 69 | | |||
65 | QMimeDatabase db; | 70 | QMimeDatabase db; | ||
66 | const auto mt = db.mimeTypeForName(mimeType); | 71 | const auto mt = db.mimeTypeForName(mimeType); | ||
67 | FormatterInfo info; | 72 | FormatterInfo info; | ||
68 | info.formatter = formatter; | 73 | info.formatter = formatter; | ||
69 | info.priority = priority; | 74 | info.priority = priority; | ||
70 | 75 | | |||
71 | auto &v = registry[mt.isValid() ? mt.name() : mimeType]; | 76 | auto &v = registry[mt.isValid() ? mt.name() : mimeType]; | ||
72 | v.push_back(info); | 77 | v.push_back(info); | ||
73 | std::stable_sort(v.begin(), v.end(), [](const FormatterInfo &lhs, const FormatterInfo &rhs) { | 78 | std::stable_sort(v.begin(), v.end(), [](const FormatterInfo &lhs, const FormatterInfo &rhs) { | ||
74 | return lhs.priority > rhs.priority; | 79 | return lhs.priority > rhs.priority; | ||
75 | }); | 80 | }); | ||
76 | } | 81 | } | ||
77 | 82 | | |||
78 | void BodyPartFormatterBaseFactoryPrivate::appendFormattersForType(const QString &mimeType, QVector<const Interface::BodyPartFormatter *> &formatters) | 83 | void BodyPartFormatterFactoryPrivate::appendFormattersForType(const QString &mimeType, QVector<const Interface::BodyPartFormatter *> &formatters) | ||
79 | { | 84 | { | ||
80 | const auto it = registry.constFind(mimeType); | 85 | const auto it = registry.constFind(mimeType); | ||
81 | if (it == registry.constEnd()) { | 86 | if (it == registry.constEnd()) { | ||
82 | return; | 87 | return; | ||
83 | } | 88 | } | ||
84 | for (const auto &f : it.value()) { | 89 | for (const auto &f : it.value()) { | ||
85 | formatters.push_back(f.formatter); | 90 | formatters.push_back(f.formatter); | ||
86 | } | 91 | } | ||
87 | } | 92 | } | ||
88 | 93 | | |||
89 | BodyPartFormatterBaseFactory::BodyPartFormatterBaseFactory() | 94 | BodyPartFormatterFactory::BodyPartFormatterFactory() | ||
90 | : d(new BodyPartFormatterBaseFactoryPrivate(this)) | 95 | : d(new BodyPartFormatterFactoryPrivate(this)) | ||
91 | { | 96 | { | ||
92 | } | 97 | } | ||
93 | 98 | | |||
94 | BodyPartFormatterBaseFactory::~BodyPartFormatterBaseFactory() | 99 | BodyPartFormatterFactory::~BodyPartFormatterFactory() | ||
95 | { | 100 | { | ||
96 | delete d; | 101 | delete d; | ||
97 | } | 102 | } | ||
98 | 103 | | |||
99 | void BodyPartFormatterBaseFactory::insert(const QString &mimeType, const Interface::BodyPartFormatter *formatter, int priority) | 104 | BodyPartFormatterFactory* BodyPartFormatterFactory::instance() | ||
105 | { | ||||
106 | static BodyPartFormatterFactory s_instance; | ||||
107 | return &s_instance; | ||||
108 | } | ||||
109 | | ||||
110 | void BodyPartFormatterFactory::insert(const QString &mimeType, const Interface::BodyPartFormatter *formatter, int priority) | ||||
100 | { | 111 | { | ||
101 | d->insert(mimeType.toLower(), formatter, priority); | 112 | d->insert(mimeType.toLower(), formatter, priority); | ||
102 | } | 113 | } | ||
103 | 114 | | |||
104 | QVector<const Interface::BodyPartFormatter *> BodyPartFormatterBaseFactory::formattersForType(const QString &mimeType) const | 115 | QVector<const Interface::BodyPartFormatter *> BodyPartFormatterFactory::formattersForType(const QString &mimeType) const | ||
105 | { | 116 | { | ||
106 | QVector<const Interface::BodyPartFormatter *> r; | 117 | QVector<const Interface::BodyPartFormatter *> r; | ||
107 | d->setup(); | 118 | d->setup(); | ||
108 | 119 | | |||
109 | QMimeDatabase db; | 120 | QMimeDatabase db; | ||
110 | std::vector<QString> processedTypes; | 121 | std::vector<QString> processedTypes; | ||
111 | processedTypes.push_back(mimeType.toLower()); | 122 | processedTypes.push_back(mimeType.toLower()); | ||
112 | 123 | | |||
Show All 24 Lines | 145 | if (mimeType.startsWith(QLatin1String("multipart/"))) { | |||
137 | } | 148 | } | ||
138 | } else { | 149 | } else { | ||
139 | d->appendFormattersForType(QStringLiteral("application/octet-stream"), r); | 150 | d->appendFormattersForType(QStringLiteral("application/octet-stream"), r); | ||
140 | } | 151 | } | ||
141 | assert(!r.empty()); | 152 | assert(!r.empty()); | ||
142 | return r; | 153 | return r; | ||
143 | } | 154 | } | ||
144 | 155 | | |||
145 | void BodyPartFormatterBaseFactory::loadPlugins() | 156 | void BodyPartFormatterFactory::loadPlugins() | ||
knauss: no the idea is that in mimetreeparser there is no plugin loader, this should be in… | |||||
The solution for that is adding a way to change the plugin search path (or add some other way of filtering the plugins by additional metadata), not to duplicate the entire plugin loading code. This becomes even more relevant once we add on-demand plugin loading, when this wont be a single function anymore. vkrause: The solution for that is adding a way to change the plugin search path (or add some other way… | |||||
146 | { | 157 | { | ||
147 | qCDebug(MIMETREEPARSER_LOG) << "plugin loading is not enabled in libmimetreeparser"; | 158 | KPluginLoader::forEachPlugin(QStringLiteral("messageviewer/bodypartformatter"), [this](const QString &path) { | ||
159 | QPluginLoader loader(path); | ||||
160 | const auto formatterData = loader.metaData().value(QLatin1String("MetaData")).toObject().value(QLatin1String("formatter")).toArray(); | ||||
161 | if (formatterData.isEmpty()) { | ||||
162 | qCWarning(MIMETREEPARSER_LOG) << "Plugin" << path << "has no meta data."; | ||||
163 | return; | ||||
164 | } | ||||
165 | | ||||
166 | auto plugin = qobject_cast<MimeTreeParser::Interface::BodyPartFormatterPlugin*>(loader.instance()); | ||||
167 | if (!plugin) { | ||||
168 | qCWarning(MIMETREEPARSER_LOG) << "BodyPartFormatterFactory: plugin" << path | ||||
169 | << "is not valid!"; | ||||
170 | return; | ||||
171 | } | ||||
172 | | ||||
173 | const MimeTreeParser::Interface::BodyPartFormatter *bfp = nullptr; | ||||
174 | for (int i = 0; (bfp = plugin->bodyPartFormatter(i)) && i < formatterData.size(); ++i) { | ||||
175 | const auto metaData = formatterData.at(i).toObject(); | ||||
176 | const auto mimetype = metaData.value(QLatin1String("mimetype")).toString(); | ||||
177 | if (mimetype.isEmpty()) { | ||||
178 | qCWarning(MIMETREEPARSER_LOG) << "BodyPartFormatterFactory: plugin" << path | ||||
179 | << "returned empty mimetype specification for index" | ||||
180 | << i; | ||||
181 | break; | ||||
182 | } | ||||
183 | // priority should always be higher than the built-in ones, otherwise what's the point? | ||||
184 | const auto priority = metaData.value(QLatin1String("priority")).toInt() + 100; | ||||
185 | qCDebug(MIMETREEPARSER_LOG) << "plugin for " << mimetype << priority; | ||||
186 | insert(mimetype, bfp, priority); | ||||
187 | } | ||||
188 | }); | ||||
148 | } | 189 | } |
no the idea is that in mimetreeparser there is no plugin loader, this should be in messageviewer. Because the plugins may be specific for a specific messageviewer, that's why the messageviewer needs to control this. For Kube as example the plugins would need different plugins, becuase tithey support a different set. That was the base idea of this BaseFactory to give full control ovr the plugins to the messageviewer.