8#include "typepluginloader_p.h"
11#include "itemserializer_p.h"
12#include "itemserializerplugin.h"
14#include "akonadicore_debug.h"
19#include <QMimeDatabase>
21#include <QRegularExpression>
27#include "pluginloader_p.h"
32static const char LEGACY_NAME[] =
"legacy";
33static const char DEFAULT_NAME[] =
"default";
34static const char _APPLICATION_OCTETSTREAM[] =
"application/octet-stream";
38Q_GLOBAL_STATIC(DefaultItemSerializerPlugin, s_defaultItemSerializerPlugin)
48 explicit PluginEntry(
const QString &identifier, QObject *plugin =
nullptr)
49 : mIdentifier(identifier)
52 qCDebug(AKONADICORE_LOG) <<
" PLUGIN : identifier" << identifier;
55 QObject *plugin()
const
61 QObject *
object = PluginLoader::self()->createForName(mIdentifier);
63 qCWarning(AKONADICORE_LOG) <<
"ItemSerializerPluginLoader: "
64 <<
"plugin" << mIdentifier <<
"is not valid!";
67 mPlugin = s_defaultItemSerializerPlugin;
71 if (!qobject_cast<ItemSerializerPlugin *>(mPlugin)) {
72 qCWarning(AKONADICORE_LOG) <<
"ItemSerializerPluginLoader: "
73 <<
"plugin" << mIdentifier <<
"doesn't provide interface ItemSerializerPlugin!";
76 mPlugin = s_defaultItemSerializerPlugin;
84 const char *pluginClassName()
const
86 return plugin()->metaObject()->className();
89 QString identifier()
const
94 bool operator<(
const PluginEntry &other)
const
96 return mIdentifier < other.mIdentifier;
99 bool operator<(
const QString &identifier)
const
101 return mIdentifier < identifier;
106 mutable QObject *mPlugin;
112 explicit MimeTypeEntry(
const QString &mimeType)
122 void add(
const QByteArray &class_,
const PluginEntry &entry)
124 m_pluginsByMetaTypeId.clear();
125 m_plugins.insert(class_, entry);
128 const PluginEntry *plugin(
const QByteArray &class_)
const
130 const QHash<QByteArray, PluginEntry>::const_iterator it = m_plugins.find(class_);
131 return it == m_plugins.end() ? nullptr : it.operator->();
134 const PluginEntry *defaultPlugin()
const
137 if (
const PluginEntry *pe = plugin(DEFAULT_NAME)) {
143 bool sawZero =
false;
144 for (QMap<
int, QHash<QByteArray, PluginEntry>::const_iterator>::const_iterator it = m_pluginsByMetaTypeId.constBegin(),
145 end = m_pluginsByMetaTypeId.constEnd();
150 }
else if (*it != m_plugins.end()) {
151 return it->operator->();
156 for (QHash<QByteArray, PluginEntry>::const_iterator it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it) {
157 if (it.key() == LEGACY_NAME) {
160 return it.operator->();
171 const PluginEntry *plugin(
int metaTypeId)
const
173 const QMap<int, QHash<QByteArray, PluginEntry>::const_iterator> &c_pluginsByMetaTypeId = m_pluginsByMetaTypeId;
174 QMap<int, QHash<QByteArray, PluginEntry>::const_iterator>::const_iterator it = c_pluginsByMetaTypeId.
find(metaTypeId);
175 if (it == c_pluginsByMetaTypeId.
end()) {
176 it = QMap<int, QHash<QByteArray, PluginEntry>::const_iterator>::const_iterator(
177 m_pluginsByMetaTypeId.insert(metaTypeId, m_plugins.find(metaTypeId ? QMetaType(metaTypeId).
name() : LEGACY_NAME)));
179 return *it == m_plugins.
end() ? nullptr : it->operator->();
182 const PluginEntry *plugin(
const QList<int> &metaTypeIds,
int &chosen)
const
184 bool sawZero =
false;
185 for (QList<int>::const_iterator it = metaTypeIds.
begin(), end = metaTypeIds.
end(); it != end; ++it) {
188 }
else if (
const PluginEntry *
const entry = plugin(*it)) {
202 QHash<QByteArray , PluginEntry> m_plugins;
203 mutable QMap<int, QHash<QByteArray, PluginEntry>::const_iterator> m_pluginsByMetaTypeId;
210 : mDefaultPlugin(PluginEntry(QStringLiteral(
"application/octet-stream@QByteArray"), s_defaultItemSerializerPlugin))
211 , mOverridePlugin(nullptr)
213 const PluginLoader *pl = PluginLoader::self();
215 qCWarning(AKONADICORE_LOG) <<
"Cannot instantiate plugin loader!";
218 const QStringList names = pl->names();
219 qCDebug(AKONADICORE_LOG) <<
"ItemSerializerPluginLoader: "
220 <<
"found" << names.
size() <<
"plugins.";
221 QMap<QString, MimeTypeEntry>
map;
223 QMimeDatabase mimeDb;
224 for (
const QString &name : names) {
225 QRegularExpressionMatch
match = rx.match(name);
226 if (
match.hasMatch()) {
230 const QByteArray classType =
match.captured(2).toLatin1();
231 QMap<QString, MimeTypeEntry>::iterator it =
map.find(mimeType);
232 if (it ==
map.end()) {
233 it =
map.insert(mimeType, MimeTypeEntry(mimeType));
235 it->add(classType, PluginEntry(name));
238 qCDebug(AKONADICORE_LOG) <<
"ItemSerializerPluginLoader: "
239 <<
"name" <<
name <<
"doesn't look like mimetype@classtype";
242 const QString APPLICATION_OCTETSTREAM = QLatin1StringView(_APPLICATION_OCTETSTREAM);
243 QMap<QString, MimeTypeEntry>::iterator it =
map.find(APPLICATION_OCTETSTREAM);
244 if (it ==
map.end()) {
245 it =
map.insert(APPLICATION_OCTETSTREAM, MimeTypeEntry(APPLICATION_OCTETSTREAM));
247 it->add(
"QByteArray", mDefaultPlugin);
248 it->add(LEGACY_NAME, mDefaultPlugin);
249 const int size =
map.size();
250 allMimeTypes.reserve(size);
251 std::copy(
map.begin(),
map.end(), std::back_inserter(allMimeTypes));
254 QObject *findBestMatch(
const QString &type,
const QList<int> &metaTypeId, TypePluginLoader::Options opt)
256 if (QObject *
const plugin = findBestMatch(type, metaTypeId)) {
258 if ((opt & TypePluginLoader::NoDefault) && plugin == mDefaultPlugin.plugin()) {
267 QObject *findBestMatch(
const QString &type,
const QList<int> &metaTypeIds)
269 if (mOverridePlugin) {
270 return mOverridePlugin;
272 if (QObject *
const plugin = cacheLookup(type, metaTypeIds)) {
277 QObject *
const plugin = findBestMatchImpl(type, metaTypeIds, chosen);
278 if (metaTypeIds.
empty()) {
280 cachedDefaultPlugins[
type] = plugin;
284 cachedPlugins[
type][chosen] = plugin;
289 void overrideDefaultPlugin(QObject *p)
296 void findSuitablePlugins(QMimeType mimeType, QSet<QMimeType> &checkedMimeTypes, QList<int> &matchingIndexes,
const QMimeDatabase &mimeDb)
const
299 if (checkedMimeTypes.
contains(mimeType)) {
303 checkedMimeTypes.
insert(mimeType);
306 for (
int i = 0, end = allMimeTypes.size(); i < end; ++i) {
308 if (!pluginMimeType.
isValid() || pluginMimeType != mimeType) {
312 matchingIndexes.
append(i);
315 auto parentTypes =
mimeType.parentMimeTypes();
318 for (
const auto &parent : parentTypes) {
320 findSuitablePlugins(parentType, checkedMimeTypes, matchingIndexes, mimeDb);
324 QObject *findBestMatchImpl(
const QString &type,
const QList<int> &metaTypeIds,
int &chosen)
const
326 const QMimeDatabase mimeDb;
329 qCWarning(AKONADICORE_LOG) <<
"Invalid mimetype requested:" <<
type;
330 return mDefaultPlugin.plugin();
333 QSet<QMimeType> checkedMimeTypes;
334 QList<int> matchingIndexes;
336 findSuitablePlugins(mimeType, checkedMimeTypes, matchingIndexes, mimeDb);
340 for (QList<int>::const_iterator it = matchingIndexes.
constBegin(), end = matchingIndexes.
constEnd(); it != end; ++it) {
343 const MimeTypeEntry &mt = allMimeTypes[*it];
344 if (metaTypeIds.
empty()) {
345 if (
const PluginEntry *
const entry = mt.defaultPlugin()) {
349 if (allMimeTypes[*it].
type() != QLatin1StringView(
"application/octet-stream")) {
350 return entry->plugin();
355 }
else if (
const PluginEntry *
const entry = mt.plugin(metaTypeIds, chosen)) {
357 return entry->plugin();
365 return mDefaultPlugin.plugin();
368 std::vector<MimeTypeEntry> allMimeTypes;
369 QHash<QString, QMap<int, QObject *>> cachedPlugins;
370 QHash<QString, QObject *> cachedDefaultPlugins;
373 QObject *cacheLookup(
const QString &mimeType,
const QList<int> &metaTypeIds)
const
375 if (metaTypeIds.
empty()) {
376 const QHash<QString, QObject *>::const_iterator hit = cachedDefaultPlugins.find(mimeType);
377 if (hit != cachedDefaultPlugins.end()) {
382 const QHash<QString, QMap<int, QObject *>>::const_iterator hit = cachedPlugins.find(mimeType);
383 if (hit == cachedPlugins.end()) {
386 bool sawZero =
false;
387 for (QList<int>::const_iterator it = metaTypeIds.
begin(), end = metaTypeIds.
end(); it != end; ++it) {
390 }
else if (QObject *
const o = hit->
value(*it)) {
395 return hit->
value(0);
401 PluginEntry mDefaultPlugin;
402 QObject *mOverridePlugin;
405Q_GLOBAL_STATIC(PluginRegistry, s_pluginRegistry)
407QObject *TypePluginLoader::objectForMimeTypeAndClass(
const QString &mimetype,
const QList<int> &metaTypeIds, Options opt)
409 return s_pluginRegistry->findBestMatch(mimetype, metaTypeIds, opt);
412QObject *TypePluginLoader::defaultObjectForMimeType(
const QString &mimetype)
414 return objectForMimeTypeAndClass(mimetype, QList<int>());
417ItemSerializerPlugin *TypePluginLoader::pluginForMimeTypeAndClass(
const QString &mimetype,
const QList<int> &metaTypeIds, Options opt)
419 return qobject_cast<ItemSerializerPlugin *>(objectForMimeTypeAndClass(mimetype, metaTypeIds, opt));
424 ItemSerializerPlugin *plugin = qobject_cast<ItemSerializerPlugin *>(defaultObjectForMimeType(mimetype));
429void TypePluginLoader::overridePluginLookup(QObject *p)
431 s_pluginRegistry->overrideDefaultPlugin(p);
The base class for item type serializer plugins.
Helper integration between Akonadi and Qt.
KCALUTILS_EXPORT QString mimeType()
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
QString name(StandardAction id)
T value(const Key &key) const const
void append(QList< T > &&value)
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype size() const const
iterator find(const Key &key)
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
bool isValid() const const
QString anchoredPattern(QStringView expression)
bool contains(const QSet< T > &other) const const
iterator insert(const T &value)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)