diff options
author | Roberto Raggi <roberto.raggi@nokia.com> | 2010-02-22 14:54:36 (GMT) |
---|---|---|
committer | Roberto Raggi <roberto.raggi@nokia.com> | 2010-02-22 17:12:13 (GMT) |
commit | 20fc9f2e264f34dd8580949ddbe5511b78ab0ac4 (patch) | |
tree | 3d407e6bbb3d6ce150a840b2cd27dec3fdc2a92b /src/declarative/qml | |
parent | cdeb85498e4cbd37022ba2bf4dc594db2326d0a4 (diff) | |
download | Qt-20fc9f2e264f34dd8580949ddbe5511b78ab0ac4.zip Qt-20fc9f2e264f34dd8580949ddbe5511b78ab0ac4.tar.gz Qt-20fc9f2e264f34dd8580949ddbe5511b78ab0ac4.tar.bz2 |
Load QML extensions.
This allows projects which use the QtDeclarative module to register QML
types and functions through C++ extensions.
Reviewed-by: mae
Diffstat (limited to 'src/declarative/qml')
-rw-r--r-- | src/declarative/qml/qmldirparser.cpp | 11 | ||||
-rw-r--r-- | src/declarative/qml/qmldirparser_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 67 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlextensioninterface.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlextensionplugin.h | 2 |
7 files changed, 62 insertions, 25 deletions
diff --git a/src/declarative/qml/qmldirparser.cpp b/src/declarative/qml/qmldirparser.cpp index c7de233..60beb72 100644 --- a/src/declarative/qml/qmldirparser.cpp +++ b/src/declarative/qml/qmldirparser.cpp @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE QmlDirParser::QmlDirParser() + : _isParsed(false) { } @@ -72,11 +73,21 @@ QString QmlDirParser::source() const void QmlDirParser::setSource(const QString &source) { + _isParsed = false; _source = source; } +bool QmlDirParser::isParsed() const +{ + return _isParsed; +} + bool QmlDirParser::parse() { + if (_isParsed) + return true; + + _isParsed = true; _errors.clear(); _plugins.clear(); _components.clear(); diff --git a/src/declarative/qml/qmldirparser_p.h b/src/declarative/qml/qmldirparser_p.h index ff8b0f8..c58c03f 100644 --- a/src/declarative/qml/qmldirparser_p.h +++ b/src/declarative/qml/qmldirparser_p.h @@ -74,6 +74,7 @@ public: QString source() const; void setSource(const QString &source); + bool isParsed() const; bool parse(); bool hasError() const; @@ -116,6 +117,7 @@ private: QString _source; QList<Component> _components; QList<Plugin> _plugins; + unsigned _isParsed: 1; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index ce2a693..d47db9b 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -97,7 +97,6 @@ #include <QGraphicsObject> #include <QtCore/qcryptographichash.h> -#include <private/qfactoryloader_p.h> #include <private/qobject_p.h> #include <private/qscriptdeclarativeclass_p.h> @@ -1249,12 +1248,13 @@ struct QmlEnginePrivate::ImportedNamespace { QByteArray qt = uris.at(i).toUtf8(); qt += '/'; qt += type; + if (qmlImportTrace()) qDebug() << "Look in" << qt; QmlType *t = QmlMetaType::qmlType(qt,vmaj,vmin); - if (vmajor) *vmajor = vmaj; - if (vminor) *vminor = vmin; if (t) { + if (vmajor) *vmajor = vmaj; + if (vminor) *vminor = vmin; if (qmlImportTrace()) qDebug() << "Found" << qt; if (type_return) @@ -1273,7 +1273,7 @@ struct QmlEnginePrivate::ImportedNamespace { } } - const QString typespace = QString::fromUtf8(type); + const QString typeName = QString::fromUtf8(type); QmlDirParser qmldirParser; qmldirParser.setUrl(url); @@ -1282,7 +1282,7 @@ struct QmlEnginePrivate::ImportedNamespace { foreach (const QmlDirParser::Component &c, qmldirParser.components()) { // ### TODO: cache the components if (c.majorVersion < vmaj || (c.majorVersion == vmaj && vmin >= c.minorVersion)) { - if (c.typeName == typespace) { + if (c.typeName == typeName) { if (url_return) *url_return = url.resolved(QUrl(c.fileName)); @@ -1290,6 +1290,7 @@ struct QmlEnginePrivate::ImportedNamespace { } } } + } else { // XXX search non-files too! (eg. zip files, see QT-524) QFileInfo f(toLocalFileOrQrc(url)); @@ -1304,9 +1305,6 @@ struct QmlEnginePrivate::ImportedNamespace { } }; -Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, - (QmlModuleFactoryInterface_iid, QLatin1String("/qmlmodules"))) - class QmlImportsPrivate { public: QmlImportsPrivate() : ref(1) @@ -1319,7 +1317,9 @@ public: delete s; } - bool add(const QUrl& base, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType, const QStringList& importPath) + QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded; + + bool add(const QUrl& base, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType, const QStringList& importPath, QmlEngine *engine) { QmlEnginePrivate::ImportedNamespace *s; if (prefix.isEmpty()) { @@ -1331,26 +1331,48 @@ public: } QString url = uri; if (importType == QmlScriptParser::Import::Library) { - url.replace(QLatin1Char('.'),QLatin1Char('/')); + url.replace(QLatin1Char('.'), QLatin1Char('/')); bool found = false; - foreach (QString p, importPath) { - QString dir = p+QLatin1Char('/')+url; + QString content; + QString dir; + QStringList paths = importPath; + paths.prepend(QFileInfo(base.toLocalFile()).path()); + foreach (const QString &p, paths) { + dir = p+QLatin1Char('/')+url; QFileInfo fi(dir+QLatin1String("/qmldir")); + const QString absoluteFilePath = fi.absoluteFilePath(); + if (fi.isFile()) { - url = QUrl::fromLocalFile(fi.absolutePath()).toString(); found = true; + + url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + + QFile file(absoluteFilePath); + if (file.open(QFile::ReadOnly)) + content = QString::fromUtf8(file.readAll()); + + if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) { + qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath); + + QmlDirParser qmldirParser; + qmldirParser.setSource(content); + qmldirParser.parse(); + + foreach (const QmlDirParser::Plugin &plugin, qmldirParser.plugins()) { + const QFileInfo pluginFileInfo(dir + QDir::separator() + plugin.path, plugin.name); + const QString pluginFilePath = pluginFileInfo.absoluteFilePath(); + engine->importExtension(pluginFilePath, uri); + } + } + break; } } - QFactoryLoader *l = loader(); - QmlModuleFactoryInterface *factory = - qobject_cast<QmlModuleFactoryInterface*>(l->instance(uri)); - if (factory) { - factory->defineModuleOnce(uri); - } + } else { url = base.resolved(QUrl(url)).toString(); } + s->uris.prepend(uri); s->urls.prepend(url); s->majversions.prepend(vmaj); @@ -1546,12 +1568,12 @@ void QmlEngine::addImportPath(const QString& path) \sa QmlExtensionInterface */ -bool QmlEngine::importExtension(const QString &fileName) +bool QmlEngine::importExtension(const QString &fileName, const QString &uri) { QPluginLoader loader(fileName); if (QmlExtensionInterface *iface = qobject_cast<QmlExtensionInterface *>(loader.instance())) { - iface->initialize(this); + iface->initialize(this, uri); return true; } @@ -1604,7 +1626,8 @@ QString QmlEngine::offlineStoragePath() const */ bool QmlEnginePrivate::addToImport(Imports* imports, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const { - bool ok = imports->d->add(imports->d->base,qmldircontent,uri,prefix,vmaj,vmin,importType,fileImportPath); + QmlEngine *engine = QmlEnginePrivate::get(const_cast<QmlEnginePrivate *>(this)); + bool ok = imports->d->add(imports->d->base,qmldircontent,uri,prefix,vmaj,vmin,importType,fileImportPath, engine); if (qmlImportTrace()) qDebug() << "QmlEngine::addToImport(" << imports << uri << prefix << vmaj << '.' << vmin << (importType==QmlScriptParser::Import::Library? "Library" : "File") << ": " << ok; return ok; diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h index 13a67b0..dd2012a 100644 --- a/src/declarative/qml/qmlengine.h +++ b/src/declarative/qml/qmlengine.h @@ -78,7 +78,7 @@ public: void clearComponentCache(); void addImportPath(const QString& dir); - bool importExtension(const QString &fileName); + bool importExtension(const QString &fileName, const QString &uri); void setNetworkAccessManagerFactory(QmlNetworkAccessManagerFactory *); QmlNetworkAccessManagerFactory *networkAccessManagerFactory() const; diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 3fe7991..d916286 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -263,6 +263,7 @@ public: QmlImportsPrivate *d; }; + bool addToImport(Imports*, const QString& qmlDirContent,const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const; bool resolveType(const Imports&, const QByteArray& type, QmlType** type_return, QUrl* url_return, diff --git a/src/declarative/qml/qmlextensioninterface.h b/src/declarative/qml/qmlextensioninterface.h index d37a5bc..cbdd34c 100644 --- a/src/declarative/qml/qmlextensioninterface.h +++ b/src/declarative/qml/qmlextensioninterface.h @@ -54,7 +54,7 @@ class QmlEngine; struct Q_DECLARATIVE_EXPORT QmlExtensionInterface { - virtual void initialize(QmlEngine *engine) = 0; + virtual void initialize(QmlEngine *engine, const QString &uri) = 0; }; Q_DECLARE_INTERFACE(QmlExtensionInterface, "com.trolltech.Qt.QmlExtensionInterface/1.0") diff --git a/src/declarative/qml/qmlextensionplugin.h b/src/declarative/qml/qmlextensionplugin.h index eda7d0c..82553e7 100644 --- a/src/declarative/qml/qmlextensionplugin.h +++ b/src/declarative/qml/qmlextensionplugin.h @@ -62,7 +62,7 @@ public: explicit QmlExtensionPlugin(QObject *parent = 0); ~QmlExtensionPlugin(); - virtual void initialize(QmlEngine *engine) = 0; + virtual void initialize(QmlEngine *engine, const QString &uri) = 0; }; QT_END_NAMESPACE |