summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2010-02-22 14:54:36 (GMT)
committerRoberto Raggi <roberto.raggi@nokia.com>2010-02-22 17:12:13 (GMT)
commit20fc9f2e264f34dd8580949ddbe5511b78ab0ac4 (patch)
tree3d407e6bbb3d6ce150a840b2cd27dec3fdc2a92b
parentcdeb85498e4cbd37022ba2bf4dc594db2326d0a4 (diff)
downloadQt-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
-rw-r--r--src/declarative/qml/qmldirparser.cpp11
-rw-r--r--src/declarative/qml/qmldirparser_p.h2
-rw-r--r--src/declarative/qml/qmlengine.cpp67
-rw-r--r--src/declarative/qml/qmlengine.h2
-rw-r--r--src/declarative/qml/qmlengine_p.h1
-rw-r--r--src/declarative/qml/qmlextensioninterface.h2
-rw-r--r--src/declarative/qml/qmlextensionplugin.h2
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