diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2012-02-06 23:36:17 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-15 17:27:37 +0100 |
commit | 7184456f9a26a9c07a689c15b415ddf82eb000b7 (patch) | |
tree | 076d42ad3fd6f08a1cbef21ee6811a3fa951850b /src/corelib/plugin/qfactoryloader.cpp | |
parent | 556dd0228aca07dfe8443fd99e9f2ead4e13ab22 (diff) |
Implement new plugin mechanism
moc can now embed meta information about the plugin
inside the plugin itself. This information can
be queried by Qt without having to load the plugin.
Source compatibility with the old plugin loading
mechanism is still there, but will be removed before
Qt 5.0.
Change-Id: I03e4196ddfed07d0fe94acca40d5de8a6ce7f920
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
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 { |