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)