diff options
author | Richard Moe Gustavsen <richard.gustavsen@digia.com> | 2014-03-11 12:51:15 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-13 10:21:42 +0100 |
commit | 6e1851de9595d7e7abe9acdc8c473e792d24c4c2 (patch) | |
tree | 9c5e4d2b6b36208b52e2bf7219c870d1c156fcee | |
parent | b244fc002d4fb97abb8647ed07f6e927cf3de789 (diff) |
Static plugins: support loading static plugins from several engines
When loading dynamic plugins, we register them as loaded so that
we don't try to register their types several times if using several
engines. The same was not done for static plugins. This patch
will ensure that we follow the same logic also for static
plugins.
Task-number: QTBUG-36532
Change-Id: Icc1e089ae5d682c38b2d36bf4808f1c753c122a4
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 64 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport_p.h | 8 |
3 files changed, 58 insertions, 16 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 72de9845c8..d927a8c628 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1983,7 +1983,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths) bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors) { Q_D(QQmlEngine); - return d->importDatabase.importPlugin(filePath, uri, QString(), errors); + return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), errors); } /*! diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 97f82a2e8d..cae8365598 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -191,7 +191,7 @@ void qmlClearEnginePlugins() QMutexLocker lock(&plugins->mutex); foreach (RegisteredPlugin plugin, plugins->values()) { QPluginLoader* loader = plugin.loader; - if (!loader->unload()) + if (loader && !loader->unload()) qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString())); delete loader; } @@ -911,7 +911,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name); if (!resolvedFilePath.isEmpty()) { dynamicPluginsFound++; - if (!database->importPlugin(resolvedFilePath, uri, typeNamespace, errors)) { + if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, errors)) { if (errors) { // XXX TODO: should we leave the import plugin error alone? // Here, we pop it off the top and coalesce it into this error's message. @@ -947,7 +947,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath, if (versionUri == metaTagUri.toString()) { staticPluginsFound++; QObject *instance = pair.first.instance(); - if (!database->importPlugin(instance, basePath, uri, typeNamespace, true, errors)) { + if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, errors)) { if (errors) { QQmlError poppedError = errors->takeFirst(); QQmlError error; @@ -1820,12 +1820,11 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths) /*! \internal */ -bool QQmlImportDatabase::importPlugin(QObject *instance, const QString &basePath, - const QString &uri, const QString &typeNamespace, - bool initEngine, QList<QQmlError> *errors) +bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &basePath, + const QString &uri, const QString &typeNamespace, QList<QQmlError> *errors) { if (qmlImportTrace()) - qDebug().nospace() << "QQmlImportDatabase::importPluginInstance: " << uri << " from " << basePath; + qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath; QQmlTypesExtensionInterface *iface = qobject_cast<QQmlTypesExtensionInterface *>(instance); if (!iface) { @@ -1894,20 +1893,61 @@ bool QQmlImportDatabase::importPlugin(QObject *instance, const QString &basePath return false; } - if (initEngine) { + return true; +} + +/*! + \internal +*/ +bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &basePath, + const QString &uri, const QString &typeNamespace, QList<QQmlError> *errors) +{ +#ifndef QT_NO_LIBRARY + // Dynamic plugins are differentiated by their filepath. For static plugins we + // don't have that information so we use their address as key instead. + QString uniquePluginID = QString().sprintf("%p", instance); + StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes(); + QMutexLocker lock(&plugins->mutex); + + // Plugin types are global across all engines and should only be + // registered once. But each engine still needs to be initialized. + bool typesRegistered = plugins->contains(uniquePluginID); + bool engineInitialized = initializedPlugins.contains(uniquePluginID); + + if (typesRegistered) { + Q_ASSERT_X(plugins->value(uniquePluginID).uri == uri, + "QQmlImportDatabase::importStaticPlugin", + "Internal error: Static plugin imported previously with different uri"); + } else { + RegisteredPlugin plugin; + plugin.uri = uri; + plugin.loader = 0; + plugins->insert(uniquePluginID, plugin); + + if (!registerPluginTypes(instance, basePath, uri, typeNamespace, errors)) + return false; + } + + if (!engineInitialized) { + initializedPlugins.insert(uniquePluginID); + if (QQmlExtensionInterface *eiface = qobject_cast<QQmlExtensionInterface *>(instance)) { QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); - ep->typeLoader.initializeEngine(eiface, moduleId); + ep->typeLoader.initializeEngine(eiface, uri.toUtf8().constData()); } } return true; +#else + return false; +#endif } /*! \internal */ -bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &uri, const QString &typeNamespace, QList<QQmlError> *errors) +bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QString &uri, + const QString &typeNamespace, QList<QQmlError> *errors) { #ifndef QT_NO_LIBRARY QFileInfo fileInfo(filePath); @@ -1920,7 +1960,7 @@ bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &ur if (typesRegistered) { Q_ASSERT_X(plugins->value(absoluteFilePath).uri == uri, - "QQmlImportDatabase::importPlugin", + "QQmlImportDatabase::importDynamicPlugin", "Internal error: Plugin imported previously with different uri"); } @@ -1961,7 +2001,7 @@ bool QQmlImportDatabase::importPlugin(const QString &filePath, const QString &ur plugins->insert(absoluteFilePath, plugin); // Continue with shared code path for dynamic and static plugins: - if (!importPlugin(instance, fileInfo.absolutePath(), uri, typeNamespace, false, errors)) + if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, errors)) return false; } diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index f19f5d4f34..b19e777852 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -151,7 +151,7 @@ public: QQmlImportDatabase(QQmlEngine *); ~QQmlImportDatabase(); - bool importPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, QList<QQmlError> *errors); + bool importDynamicPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, QList<QQmlError> *errors); QStringList importPathList(PathType type = LocalOrRemote) const; void setImportPathList(const QStringList &paths); @@ -170,8 +170,10 @@ private: QString resolvePlugin(QQmlTypeLoader *typeLoader, const QString &qmldirPath, const QString &qmldirPluginPath, const QString &baseName); - bool importPlugin(QObject *instance, const QString &basePath, const QString &uri, - const QString &typeNamespace, bool initEngine, QList<QQmlError> *errors); + bool importStaticPlugin(QObject *instance, const QString &basePath, const QString &uri, + const QString &typeNamespace, QList<QQmlError> *errors); + bool registerPluginTypes(QObject *instance, const QString &basePath, + const QString &uri, const QString &typeNamespace, QList<QQmlError> *errors); struct QmldirCache { int versionMajor; |