diff options
Diffstat (limited to 'src/corelib/plugin/qfactoryloader.cpp')
-rw-r--r-- | src/corelib/plugin/qfactoryloader.cpp | 157 |
1 files changed, 127 insertions, 30 deletions
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index fe5aea0e8a..ce988fa2ff 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -51,6 +51,10 @@ #include "qpluginloader.h" #include "private/qobject_p.h" #include "private/qcoreapplication_p.h" +#include "qjsondocument.h" +#include "qjsonvalue.h" +#include "qjsonobject.h" +#include "qjsonarray.h" QT_BEGIN_NAMESPACE @@ -137,29 +141,44 @@ void QFactoryLoader::update() continue; } QStringList keys; - if (!library->loadPlugin()) { - if (qt_debug_component()) { - qDebug() << library->errorString; - qDebug() << " could not load"; + if (library->compatPlugin) { + qWarning() << "Compat plugin, need to load for accessing meta data"; + if (!library->loadPlugin()) { + if (qt_debug_component()) { + qDebug() << library->errorString; + qDebug() << " could not load"; + } + library->release(); + continue; } - library->release(); - continue; - } - if (!library->inst) - library->inst = library->instance(); - QObject *instance = library->inst.data(); - if (!instance) { - library->release(); - // ignore plugins that have a valid signature but cannot be loaded. - continue; + if (!library->inst) + library->inst = library->instance(); + QObject *instance = library->inst.data(); + if (!instance) { + library->release(); + // ignore plugins that have a valid signature but cannot be loaded. + continue; + } + QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance); + if (instance && factory && instance->qt_metacast(d->iid)) + keys = factory->keys(); + } else { + QString iid = library->metaData.value(QLatin1String("IID")).toString(); + if (iid == QLatin1String(d->iid.constData(), d->iid.size())) { + QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject(); + QJsonArray k = object.value(QLatin1String("Keys")).toArray(); + for (int i = 0; i < k.size(); ++i) { + QString s = k.at(i).toString(); + keys += s; + } + } + if (qt_debug_component()) + qDebug() << "Got keys from plugin meta data" << keys; } - QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance); - if (instance && factory && instance->qt_metacast(d->iid)) - keys = factory->keys(); - if (keys.isEmpty()) - library->unload(); + if (keys.isEmpty()) { + library->unload(); library->release(); continue; } @@ -173,7 +192,12 @@ void QFactoryLoader::update() if (!d->cs) key = key.toLower(); QLibraryPrivate *previous = d->keyMap.value(key); - if (!previous || (previous->qt_version > QT_VERSION && library->qt_version <= QT_VERSION)) { + int prev_qt_version = 0; + if (previous) { + prev_qt_version = (int)previous->metaData.value(QLatin1String("version")).toDouble(); + } + int qt_version = (int)library->metaData.value(QLatin1String("version")).toDouble(); + if (!previous || (prev_qt_version > QT_VERSION && qt_version <= QT_VERSION)) { d->keyMap[key] = library; d->keyList += keys.at(k); } @@ -200,23 +224,76 @@ QStringList QFactoryLoader::keys() const Q_D(const QFactoryLoader); QMutexLocker locker(&d->mutex); QStringList keys = d->keyList; - QObjectList instances = QPluginLoader::staticInstances(); - for (int i = 0; i < instances.count(); ++i) - if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i))) - if (instances.at(i)->qt_metacast(d->iid)) - keys += factory->keys(); + QVector<QStaticPlugin> staticPlugins = QLibraryPrivate::staticPlugins(); + for (int i = 0; i < staticPlugins.count(); ++i) { + if (staticPlugins.at(i).metaData) { + const char *rawMetaData = staticPlugins.at(i).metaData(); + QJsonObject object = QLibraryPrivate::fromRawMetaData(rawMetaData).object(); + if (object.value(QLatin1String("IID")) != QLatin1String(d->iid.constData(), d->iid.size())) + continue; + + QJsonObject meta = object.value(QLatin1String("MetaData")).toObject(); + QJsonArray a = meta.value(QLatin1String("Keys")).toArray(); + for (int i = 0; i < a.size(); ++i) { + QString s = a.at(i).toString(); + if (!s.isEmpty()) + keys += s; + } + } else { + // compat plugin + QObject *instance = staticPlugins.at(i).instance(); + QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance); + if (instance && factory && instance->qt_metacast(d->iid)) + keys = factory->keys(); + } + } return keys; } +QList<QJsonObject> QFactoryLoader::metaData() const +{ + Q_D(const QFactoryLoader); + QMutexLocker locker(&d->mutex); + QList<QJsonObject> metaData; + for (int i = 0; i < d->libraryList.size(); ++i) + metaData.append(d->libraryList.at(i)->metaData); + + QVector<QStaticPlugin> staticPlugins = QLibraryPrivate::staticPlugins(); + for (int i = 0; i < staticPlugins.count(); ++i) { + if (staticPlugins.at(i).metaData) { + const char *rawMetaData = staticPlugins.at(i).metaData(); + QJsonObject object = QLibraryPrivate::fromRawMetaData(rawMetaData).object(); + if (object.value(QLatin1String("IID")) != QLatin1String(d->iid.constData(), d->iid.size())) + continue; + + QJsonObject meta = object.value(QLatin1String("MetaData")).toObject(); + metaData.append(meta); + } else { + // compat plugins + QObject *instance = staticPlugins.at(i).instance(); + QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance); + if (instance && factory && instance->qt_metacast(d->iid)) { + QJsonObject meta; + QJsonArray a = QJsonArray::fromStringList(factory->keys()); + meta.insert(QLatin1String("Keys"), a); + metaData.append(meta); + } + } + } + return metaData; +} + QObject *QFactoryLoader::instance(const QString &key) const { Q_D(const QFactoryLoader); QMutexLocker locker(&d->mutex); - QObjectList instances = QPluginLoader::staticInstances(); - for (int i = 0; i < instances.count(); ++i) - if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i))) - if (instances.at(i)->qt_metacast(d->iid) && factory->keys().contains(key, Qt::CaseInsensitive)) - return instances.at(i); + QVector<QStaticPlugin> staticPlugins = QLibraryPrivate::staticPlugins(); + for (int i = 0; i < staticPlugins.count(); ++i) { + QObject *instance = staticPlugins.at(i).instance(); + if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance)) + if (instance->qt_metacast(d->iid) && factory->keys().contains(key, Qt::CaseInsensitive)) + return instance; + } QString lowered = d->cs ? key : key.toLower(); if (QLibraryPrivate* library = d->keyMap.value(lowered)) { @@ -234,6 +311,26 @@ QObject *QFactoryLoader::instance(const QString &key) const return 0; } +QObject *QFactoryLoader::instance(int index) const +{ + Q_D(const QFactoryLoader); + if (index < 0 || index >= d->libraryList.size()) + return 0; + + QLibraryPrivate *library = d->libraryList.at(index); + if (library->instance || library->loadPlugin()) { + if (!library->inst) + library->inst = library->instance(); + QObject *obj = library->inst.data(); + if (obj) { + if (!obj->parent()) + obj->moveToThread(QCoreApplicationPrivate::mainThread()); + return obj; + } + } + return 0; +} + #if defined(Q_OS_UNIX) && !defined (Q_OS_MAC) QLibraryPrivate *QFactoryLoader::library(const QString &key) const { |