summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2010-02-23 14:37:36 (GMT)
committerRoberto Raggi <roberto.raggi@nokia.com>2010-02-23 14:37:36 (GMT)
commitab8477a347b286f84c7747ca0ae39bbd139a5f01 (patch)
treeaf845c2a783e0e3684f46dd02978bf86c937ccdb /src/declarative/qml
parent742befdd5077b27de79ca5ee6f9182540d0d5863 (diff)
parent5b99df32ea16775923f7060d8b0c7ee6f9c635d8 (diff)
downloadQt-ab8477a347b286f84c7747ca0ae39bbd139a5f01.zip
Qt-ab8477a347b286f84c7747ca0ae39bbd139a5f01.tar.gz
Qt-ab8477a347b286f84c7747ca0ae39bbd139a5f01.tar.bz2
Merge branch 'qtruntime'
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/qml.pri10
-rw-r--r--src/declarative/qml/qmldirparser.cpp220
-rw-r--r--src/declarative/qml/qmldirparser_p.h125
-rw-r--r--src/declarative/qml/qmlengine.cpp256
-rw-r--r--src/declarative/qml/qmlengine.h1
-rw-r--r--src/declarative/qml/qmlengine_p.h10
-rw-r--r--src/declarative/qml/qmlextensioninterface.h66
-rw-r--r--src/declarative/qml/qmlextensionplugin.cpp87
-rw-r--r--src/declarative/qml/qmlextensionplugin.h (renamed from src/declarative/qml/qmlmoduleplugin.h)36
-rw-r--r--src/declarative/qml/qmlmoduleplugin.cpp111
10 files changed, 722 insertions, 200 deletions
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index f09a944..1e4e234 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -7,7 +7,6 @@ SOURCES += \
$$PWD/qmlexpression.cpp \
$$PWD/qmlbinding.cpp \
$$PWD/qmlmetaproperty.cpp \
- $$PWD/qmlmoduleplugin.cpp \
$$PWD/qmlcomponent.cpp \
$$PWD/qmlcontext.cpp \
$$PWD/qmlcustomparser.cpp \
@@ -52,6 +51,8 @@ SOURCES += \
$$PWD/qmlworkerscript.cpp \
$$PWD/qmlimageprovider.cpp \
$$PWD/qmlnetworkaccessmanagerfactory.cpp \
+ $$PWD/qmldirparser.cpp \
+ $$PWD/qmlextensionplugin.cpp \
$$PWD/qmllist.cpp
HEADERS += \
@@ -63,7 +64,6 @@ HEADERS += \
$$PWD/qmlbinding_p.h \
$$PWD/qmlbinding_p_p.h \
$$PWD/qmlmetaproperty.h \
- $$PWD/qmlmoduleplugin.h \
$$PWD/qmlcomponent.h \
$$PWD/qmlcomponent_p.h \
$$PWD/qmlcustomparser_p.h \
@@ -122,7 +122,11 @@ HEADERS += \
$$PWD/qmlscriptclass_p.h \
$$PWD/qmlguard_p.h \
$$PWD/qmlimageprovider.h \
- $$PWD/qmlnetworkaccessmanagerfactory.h
+ $$PWD/qmlnetworkaccessmanagerfactory.h \
+ $$PWD/qmldirparser_p.h \
+ $$PWD/qmlextensioninterface.h \
+ $$PWD/qmlextensionplugin.h
+
QT += sql
include(parser/parser.pri)
include(rewriter/rewriter.pri)
diff --git a/src/declarative/qml/qmldirparser.cpp b/src/declarative/qml/qmldirparser.cpp
new file mode 100644
index 0000000..60beb72
--- /dev/null
+++ b/src/declarative/qml/qmldirparser.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmldirparser_p.h"
+#include "qmlerror.h"
+
+#include <QtCore/QTextStream>
+#include <QtCore/QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+QmlDirParser::QmlDirParser()
+ : _isParsed(false)
+{
+}
+
+QmlDirParser::~QmlDirParser()
+{
+}
+
+QUrl QmlDirParser::url() const
+{
+ return _url;
+}
+
+void QmlDirParser::setUrl(const QUrl &url)
+{
+ _url = url;
+}
+
+QString QmlDirParser::source() const
+{
+ return _source;
+}
+
+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();
+
+ QTextStream stream(&_source);
+ int lineNumber = 0;
+
+ forever {
+ ++lineNumber;
+
+ const QString line = stream.readLine();
+ if (line.isNull())
+ break;
+
+ QString sections[3];
+ int sectionCount = 0;
+
+ int index = 0;
+ const int length = line.length();
+
+ while (index != length) {
+ const QChar ch = line.at(index);
+
+ if (ch.isSpace()) {
+ do { ++index; }
+ while (index != length && line.at(index).isSpace());
+
+ } else if (ch == QLatin1Char('#')) {
+ // recognized a comment
+ break;
+
+ } else {
+ const int start = index;
+
+ do { ++index; }
+ while (index != length && !line.at(index).isSpace());
+
+ const QString lexeme = line.mid(start, index - start);
+
+ if (sectionCount >= 3) {
+ reportError(lineNumber, start, QLatin1String("unexpected token"));
+
+ } else {
+ sections[sectionCount++] = lexeme;
+ }
+ }
+ }
+
+ if (sectionCount == 0) {
+ continue; // no sections, no party.
+
+ } else if (sections[0] == QLatin1String("plugin")) {
+ if (sectionCount < 2) {
+ reportError(lineNumber, -1,
+ QString::fromUtf8("plugin directive requires 2 arguments, but %1 were provided").arg(sectionCount + 1));
+
+ continue;
+ }
+
+ const Plugin entry(sections[1], sections[2]);
+
+ _plugins.append(entry);
+
+ } else if (sectionCount == 3) {
+ const QString &version = sections[1];
+ const int dotIndex = version.indexOf(QLatin1Char('.'));
+
+ if (dotIndex == -1) {
+ qWarning() << "expected '.'"; // ### use reportError
+
+ } else if (version.indexOf(QLatin1Char('.'), dotIndex + 1) != -1) {
+ qWarning() << "unexpected '.'"; // ### use reportError
+
+ } else {
+ bool validVersionNumber = false;
+ const int majorVersion = version.left(dotIndex).toInt(&validVersionNumber);
+
+ if (validVersionNumber) {
+ const int minorVersion = version.mid(dotIndex + 1).toInt(&validVersionNumber);
+
+ if (validVersionNumber) {
+ const Component entry(sections[0], sections[2], majorVersion, minorVersion);
+
+ _components.append(entry);
+ }
+ }
+ }
+ } else {
+ // ### use reportError
+ qWarning() << "a component declaration requires 3 arguments, but" << (sectionCount + 1) << "were provided";
+ }
+ }
+
+ return hasError();
+}
+
+void QmlDirParser::reportError(int line, int column, const QString &description)
+{
+ QmlError error;
+ error.setUrl(_url);
+ error.setLine(line);
+ error.setColumn(column);
+ error.setDescription(description);
+ _errors.append(error);
+}
+
+bool QmlDirParser::hasError() const
+{
+ if (! _errors.isEmpty())
+ return true;
+
+ return false;
+}
+
+QList<QmlError> QmlDirParser::errors() const
+{
+ return _errors;
+}
+
+QList<QmlDirParser::Plugin> QmlDirParser::plugins() const
+{
+ return _plugins;
+}
+
+QList<QmlDirParser::Component> QmlDirParser::components() const
+{
+ return _components;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmldirparser_p.h b/src/declarative/qml/qmldirparser_p.h
new file mode 100644
index 0000000..c58c03f
--- /dev/null
+++ b/src/declarative/qml/qmldirparser_p.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLDIRPARSER_P_H
+#define QMLDIRPARSER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QUrl>
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QmlError;
+
+class QmlDirParser
+{
+ Q_DISABLE_COPY(QmlDirParser)
+
+public:
+ QmlDirParser();
+ ~QmlDirParser();
+
+ QUrl url() const;
+ void setUrl(const QUrl &url);
+
+ QString source() const;
+ void setSource(const QString &source);
+
+ bool isParsed() const;
+ bool parse();
+
+ bool hasError() const;
+ QList<QmlError> errors() const;
+
+ struct Plugin
+ {
+ Plugin() {}
+
+ Plugin(const QString &name, const QString &path)
+ : name(name), path(path) {}
+
+ QString name;
+ QString path;
+ };
+
+ struct Component
+ {
+ Component()
+ : majorVersion(0), minorVersion(0) {}
+
+ Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion)
+ : typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) {}
+
+ QString typeName;
+ QString fileName;
+ int majorVersion;
+ int minorVersion;
+ };
+
+ QList<Component> components() const;
+ QList<Plugin> plugins() const;
+
+private:
+ void reportError(int line, int column, const QString &message);
+
+private:
+ QList<QmlError> _errors;
+ QUrl _url;
+ QString _source;
+ QList<Component> _components;
+ QList<Plugin> _plugins;
+ unsigned _isParsed: 1;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLDIRPARSER_P_H
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 2460f52..c7e1e16 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -50,7 +50,6 @@
#include "qmlexpression.h"
#include "qmlcomponent.h"
#include "qmlmetaproperty_p.h"
-#include "qmlmoduleplugin.h"
#include "qmlbinding_p_p.h"
#include "qmlvme_p.h"
#include "qmlenginedebug_p.h"
@@ -66,6 +65,8 @@
#include "qmlscriptclass_p.h"
#include "qmlnetworkaccessmanagerfactory.h"
#include "qmlimageprovider.h"
+#include "qmldirparser_p.h"
+#include "qmlextensioninterface.h"
#include "qmllist_p.h"
#include <qfxperf_p_p.h>
@@ -82,6 +83,7 @@
#include <QDebug>
#include <QMetaObject>
#include <QStack>
+#include <QPluginLoader>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qthreadstorage.h>
#include <QtCore/qthread.h>
@@ -94,7 +96,6 @@
#include <QGraphicsObject>
#include <QtCore/qcryptographichash.h>
-#include <private/qfactoryloader_p.h>
#include <private/qobject_p.h>
#include <private/qscriptdeclarativeclass_p.h>
@@ -156,6 +157,21 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
}
globalClass = new QmlGlobalScriptClass(&scriptEngine);
fileImportPath.append(QLibraryInfo::location(QLibraryInfo::DataPath)+QDir::separator()+QLatin1String("qml"));
+
+ // env import paths
+ QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
+ if (!envImportPath.isEmpty()) {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ QLatin1Char pathSep(';');
+#else
+ QLatin1Char pathSep(':');
+#endif
+ foreach (const QString &path, QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts)) {
+ QString canonicalPath = QDir(path).canonicalPath();
+ if (!canonicalPath.isEmpty() && !environmentImportPath.contains(canonicalPath))
+ environmentImportPath.append(canonicalPath);
+ }
+ }
}
QUrl QmlScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url)
@@ -1235,7 +1251,6 @@ struct QmlEnginePrivate::ImportedNamespace {
QList<int> majversions;
QList<int> minversions;
QList<bool> isLibrary;
- QList<bool> isBuiltin; // Types provided by C++ code (including plugins)
QList<QString> qmlDirContent;
bool find(const QByteArray& type, int *vmajor, int *vminor, QmlType** type_return, QUrl* url_return) const
@@ -1244,23 +1259,23 @@ struct QmlEnginePrivate::ImportedNamespace {
int vmaj = majversions.at(i);
int vmin = minversions.at(i);
- if (isBuiltin.at(i)) {
- QByteArray qt = uris.at(i).toUtf8();
- qt += '/';
- qt += type;
- if (qmlImportTrace())
- qDebug() << "Look in" << qt;
- QmlType *t = QmlMetaType::qmlType(qt,vmaj,vmin);
+ QByteArray qt = uris.at(i).toUtf8();
+ qt += '/';
+ qt += type;
+
+ if (qmlImportTrace())
+ qDebug() << "Look in" << qt;
+ QmlType *t = QmlMetaType::qmlType(qt,vmaj,vmin);
+ if (t) {
if (vmajor) *vmajor = vmaj;
if (vminor) *vminor = vmin;
- if (t) {
- if (qmlImportTrace())
- qDebug() << "Found" << qt;
- if (type_return)
- *type_return = t;
- return true;
- }
+ if (qmlImportTrace())
+ qDebug() << "Found" << qt;
+ if (type_return)
+ *type_return = t;
+ return true;
}
+
QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml"));
QString qmldircontent = qmlDirContent.at(i);
if (vmaj>=0 || !qmldircontent.isEmpty()) {
@@ -1271,27 +1286,25 @@ struct QmlEnginePrivate::ImportedNamespace {
qmldircontent = QString::fromUtf8(qmldir.readAll());
}
}
- QString typespace = QString::fromUtf8(type)+QLatin1Char(' ');
- QStringList lines = qmldircontent.split(QLatin1Char('\n'));
- foreach (QString line, lines) {
- if (line.isEmpty() || line.at(0) == QLatin1Char('#'))
- continue;
- if (line.startsWith(typespace)) {
- int space1 = line.indexOf(QLatin1Char(' '));
- int space2 = space1 >=0 ? line.indexOf(QLatin1Char(' '),space1+1) : -1;
- QString mapversions = line.mid(space1+1,space2<0?line.length()-space1-1:space2-space1-1);
- int dot = mapversions.indexOf(QLatin1Char('.'));
- int mapvmaj = mapversions.left(dot).toInt();
- if (mapvmaj<=vmaj) {
- if (mapvmaj<vmaj || vmin >= mapversions.mid(dot+1).toInt()) {
- QStringRef mapfile = space2<0 ? QStringRef() : line.midRef(space2+1,line.length()-space2-1);
- if (url_return)
- *url_return = url.resolved(QUrl(mapfile.toString()));
- return true;
- }
+
+ const QString typeName = QString::fromUtf8(type);
+
+ QmlDirParser qmldirParser;
+ qmldirParser.setUrl(url);
+ qmldirParser.setSource(qmldircontent);
+ qmldirParser.parse();
+
+ foreach (const QmlDirParser::Component &c, qmldirParser.components()) { // ### TODO: cache the components
+ if (c.majorVersion < vmaj || (c.majorVersion == vmaj && vmin >= c.minorVersion)) {
+ if (c.typeName == typeName) {
+ if (url_return)
+ *url_return = url.resolved(QUrl(c.fileName));
+
+ return true;
}
}
}
+
} else {
// XXX search non-files too! (eg. zip files, see QT-524)
QFileInfo f(toLocalFileOrQrc(url));
@@ -1306,9 +1319,6 @@ struct QmlEnginePrivate::ImportedNamespace {
}
};
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QmlModuleFactoryInterface_iid, QLatin1String("/qmlmodules")))
-
class QmlImportsPrivate {
public:
QmlImportsPrivate() : ref(1)
@@ -1321,7 +1331,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()) {
@@ -1332,39 +1344,63 @@ public:
set.insert(prefix,(s=new QmlEnginePrivate::ImportedNamespace));
}
QString url = uri;
- bool isbuiltin = false;
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;
+
+ // user import paths
+ QStringList paths;
+
+ // base..
+ paths += QFileInfo(base.toLocalFile()).path();
+ paths += importPath;
+ paths += QmlEnginePrivate::get(engine)->environmentImportPath;
+
+ 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()) {
+ QString resolvedFilePath = QmlEnginePrivate::get(engine)->resolvePlugin(dir + QDir::separator() + plugin.path,
+ plugin.name);
+
+ if (!resolvedFilePath.isEmpty())
+ engine->importExtension(resolvedFilePath, uri);
+ }
+ }
+
break;
}
}
- if (!found) {
- // XXX assume it is a built-in type qualifier
- isbuiltin = true;
- }
- QFactoryLoader *l = loader();
- QmlModuleFactoryInterface *factory =
- qobject_cast<QmlModuleFactoryInterface*>(l->instance(uri));
- if (factory) {
- factory->defineModuleOnce(uri);
- isbuiltin = true;
- }
+
} else {
url = base.resolved(QUrl(url)).toString();
}
+
s->uris.prepend(uri);
s->urls.prepend(url);
s->majversions.prepend(vmaj);
s->minversions.prepend(vmin);
s->isLibrary.prepend(importType == QmlScriptParser::Import::Library);
- s->isBuiltin.prepend(isbuiltin);
s->qmlDirContent.prepend(qmldircontent);
return true;
}
@@ -1387,10 +1423,11 @@ public:
if (s) {
if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return))
return true;
- if (s->urls.count() == 1 && !s->isBuiltin[0] && !s->isLibrary[0] && url_return) {
+ if (s->urls.count() == 1 && !s->isLibrary[0] && url_return) {
*url_return = QUrl(s->urls[0]+QLatin1Char('/')).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml")));
return true;
}
+
}
if (url_return) {
*url_return = base.resolved(QUrl(QString::fromUtf8(type + ".qml")));
@@ -1451,9 +1488,6 @@ static QmlTypeNameCache *cacheForNamespace(QmlEngine *engine, const QmlEnginePri
QList<QmlType *> types = QmlMetaType::qmlTypes();
for (int ii = 0; ii < set.uris.count(); ++ii) {
- if (!set.isBuiltin.at(ii))
- continue;
-
QByteArray base = set.uris.at(ii).toUtf8() + '/';
int major = set.majversions.at(ii);
int minor = set.minversions.at(ii);
@@ -1552,6 +1586,24 @@ void QmlEngine::addImportPath(const QString& path)
}
/*!
+ Imports the given \a extension into this QmlEngine. Returns
+ true if the extension was successfully imported.
+
+ \sa QmlExtensionInterface
+*/
+bool QmlEngine::importExtension(const QString &fileName, const QString &uri)
+{
+ QPluginLoader loader(fileName);
+
+ if (QmlExtensionInterface *iface = qobject_cast<QmlExtensionInterface *>(loader.instance())) {
+ iface->initialize(this, uri.toUtf8().constData());
+ return true;
+ }
+
+ return false;
+}
+
+/*!
\property QmlEngine::offlineStoragePath
\brief the directory for storing offline user data
@@ -1580,6 +1632,87 @@ QString QmlEngine::offlineStoragePath() const
return d->scriptEngine.offlineStoragePath;
}
+/*!
+ \internal
+
+ Returns the result of the merge of \a baseName with \a dir, \a suffixes, and \a prefix.
+ */
+QString QmlEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName,
+ const QStringList &suffixes,
+ const QString &prefix)
+{
+ foreach (const QString &suffix, suffixes) {
+ QString pluginFileName = prefix;
+
+ pluginFileName += baseName;
+ pluginFileName += QLatin1Char('.');
+ pluginFileName += suffix;
+
+ QFileInfo fileInfo(dir, pluginFileName);
+
+ if (fileInfo.exists())
+ return fileInfo.absoluteFilePath();
+ }
+
+ return QString();
+}
+
+/*!
+ \internal
+
+ Returns the result of the merge of \a baseName with \a dir and the platform suffix.
+
+ \table
+ \header \i Platform \i Valid suffixes
+ \row \i Windows \i \c .dll
+ \row \i Unix/Linux \i \c .so
+ \row \i AIX \i \c .a
+ \row \i HP-UX \i \c .sl, \c .so (HP-UXi)
+ \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so
+ \row \i Symbian \i \c .dll
+ \endtable
+
+ Version number on unix are ignored.
+*/
+QString QmlEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName)
+{
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ return resolvePlugin(dir, baseName, QStringList(QLatin1String("dll")));
+#elif defined(Q_OS_SYMBIAN)
+ return resolvePlugin(dir, baseName, QStringList() << QLatin1String("dll") << QLatin1String("qtplugin"));
+#else
+
+# if defined(Q_OS_DARWIN)
+
+ return resolvePlugin(dir, baseName, QStringList() << QLatin1String("dylib") << QLatin1String("so") << QLatin1String("bundle"),
+ QLatin1String("lib"));
+# else // Generic Unix
+ QStringList validSuffixList;
+
+# if defined(Q_OS_HPUX)
+/*
+ See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
+ "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
+ the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
+ */
+ validSuffixList << QLatin1String("sl");
+# if defined __ia64
+ validSuffixList << QLatin1String("so");
+# endif
+# elif defined(Q_OS_AIX)
+ validSuffixList << QLatin1String("a") << QLatin1String("so");
+# elif defined(Q_OS_UNIX)
+ validSuffixList << QLatin1String("so");
+# endif
+
+ // Examples of valid library names:
+ // libfoo.so
+
+ return resolvePlugin(dir, baseName, validSuffixList, QLatin1String("lib"));
+# endif
+
+#endif
+}
/*!
\internal
@@ -1597,7 +1730,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 64d0b9d..dd2012a 100644
--- a/src/declarative/qml/qmlengine.h
+++ b/src/declarative/qml/qmlengine.h
@@ -78,6 +78,7 @@ public:
void clearComponentCache();
void addImportPath(const QString& dir);
+ 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..85c5fbe 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -104,6 +104,7 @@ class QmlCleanup;
class QmlDelayedError;
class QmlWorkerScriptEngine;
class QmlGlobalScriptClass;
+class QDir;
class QmlScriptEngine : public QScriptEngine
{
@@ -263,6 +264,15 @@ public:
QmlImportsPrivate *d;
};
+
+ QStringList environmentImportPath;
+
+ QString resolvePlugin(const QDir &dir, const QString &baseName,
+ const QStringList &suffixes,
+ const QString &prefix = QString());
+ QString resolvePlugin(const QDir &dir, const QString &baseName);
+
+
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
new file mode 100644
index 0000000..b993e82
--- /dev/null
+++ b/src/declarative/qml/qmlextensioninterface.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLEXTENSIONINTERFACE_H
+#define QMLEXTENSIONINTERFACE_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlEngine;
+
+struct Q_DECLARATIVE_EXPORT QmlExtensionInterface
+{
+ virtual void initialize(QmlEngine *engine, const char *uri) = 0;
+};
+
+Q_DECLARE_INTERFACE(QmlExtensionInterface, "com.trolltech.Qt.QmlExtensionInterface/1.0")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLEXTENSIONINTERFACE_H
diff --git a/src/declarative/qml/qmlextensionplugin.cpp b/src/declarative/qml/qmlextensionplugin.cpp
new file mode 100644
index 0000000..c1195d2
--- /dev/null
+++ b/src/declarative/qml/qmlextensionplugin.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlextensionplugin.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \since 4.7
+ \class QmlExtensionPlugin
+ \brief The QmlExtensionPlugin class provides an abstract base for custom QML extension plugins.
+
+ \ingroup plugins
+
+ QmlExtensionPlugin is a plugin interface that makes it
+ possible to offer extensions that can be loaded dynamically into
+ applications using the QmlEngine class.
+
+ Writing a QML extension plugin is achieved by subclassing this
+ base class, reimplementing the pure virtual initialize()
+ function, and exporting the class using the Q_EXPORT_PLUGIN2()
+ macro. See \l {How to Create Qt Plugins} for details.
+
+ \sa QmlEngine::importExtension()
+*/
+
+/*!
+ \fn void QmlExtensionPlugin::initialize(QmlEngine *engine)
+
+ Initializes the extension specified in the given \a engine.
+*/
+
+/*!
+ Constructs a QML extension plugin with the given \a parent.
+
+ Note that this constructor is invoked automatically by the
+ Q_EXPORT_PLUGIN2() macro, so there is no need for calling it
+ explicitly.
+*/
+QmlExtensionPlugin::QmlExtensionPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QmlExtensionPlugin::~QmlExtensionPlugin()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmoduleplugin.h b/src/declarative/qml/qmlextensionplugin.h
index b28f1ad..8cc64ad 100644
--- a/src/declarative/qml/qmlmoduleplugin.h
+++ b/src/declarative/qml/qmlextensionplugin.h
@@ -39,14 +39,12 @@
**
****************************************************************************/
-#ifndef QMLMODULEPLUGIN_H
-#define QMLMODULEPLUGIN_H
+#ifndef QMLEXTENSIONPLUGIN_H
+#define QMLEXTENSIONPLUGIN_H
#include <QtCore/qplugin.h>
-#include <QtCore/qfactoryinterface.h>
-#include <QtCore/qlist.h>
-#include <QtCore/qset.h>
-#include <QtCore/qbytearray.h>
+
+#include "qmlextensioninterface.h"
QT_BEGIN_HEADER
@@ -54,33 +52,21 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-struct Q_DECLARATIVE_EXPORT QmlModuleFactoryInterface : public QFactoryInterface
-{
- virtual void defineModuleOnce(const QString& uri) = 0;
-};
-
-#define QmlModuleFactoryInterface_iid "com.nokia.Qt.QmlModuleFactoryInterface"
+class QmlEngine;
-Q_DECLARE_INTERFACE(QmlModuleFactoryInterface, QmlModuleFactoryInterface_iid)
-
-
-class Q_DECLARATIVE_EXPORT QmlModulePlugin : public QObject, public QmlModuleFactoryInterface
+class Q_DECLARATIVE_EXPORT QmlExtensionPlugin : public QObject, public QmlExtensionInterface
{
Q_OBJECT
- Q_INTERFACES(QmlModuleFactoryInterface:QFactoryInterface)
+ Q_INTERFACES(QmlExtensionInterface)
public:
- explicit QmlModulePlugin(QObject *parent = 0);
- ~QmlModulePlugin();
-
- virtual void defineModule(const QString& uri) = 0;
+ explicit QmlExtensionPlugin(QObject *parent = 0);
+ ~QmlExtensionPlugin();
-private:
- void defineModuleOnce(const QString& uri);
- QSet<QString> defined;
+ virtual void initialize(QmlEngine *engine, const char *uri) = 0;
};
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QMLMODULEPLUGIN_H
+#endif // QMLEXTENSIONPLUGIN_H
diff --git a/src/declarative/qml/qmlmoduleplugin.cpp b/src/declarative/qml/qmlmoduleplugin.cpp
deleted file mode 100644
index 8019805..0000000
--- a/src/declarative/qml/qmlmoduleplugin.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmlmoduleplugin.h"
-#include "qstringlist.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QmlModulePlugin
- \brief The QmlModulePlugin class provides an abstract base for custom QML module plugins.
- \reentrant
- \ingroup plugins
-
- The QML module plugin is a simple plugin interface that makes it
- easy to add custom QML modules that can be loaded dynamically
- into applications.
-
- Writing a QML module plugin is achieved by subclassing this base
- class, reimplementing the pure virtual function keys(), and
- exporting the class with the Q_EXPORT_PLUGIN2() macro. See \l{How
- to Create Qt Plugins} for details.
-
- The strings returned by keys() should be the list of URIs of modules
- that the plugin registers.
-
- The plugin should register QML types with qmlRegisterType() when the
- defineModule() method is called.
-
- See the example in \c{examples/declarative/plugins}.
-*/
-
-/*!
- Constructs a QML module plugin with the given \a parent. This is
- invoked automatically by the Q_EXPORT_PLUGIN2() macro.
-*/
-QmlModulePlugin::QmlModulePlugin(QObject *parent)
- : QObject(parent)
-{
-}
-
-/*!
- Destroys the QML module plugin.
-
- You never have to call this explicitly. Qt destroys a plugin
- automatically when it is no longer used.
-*/
-QmlModulePlugin::~QmlModulePlugin()
-{
-}
-
-/*!
- \fn void QmlModulePlugin::defineModule(const QString& uri)
-
- Subclasses must override this function to register types
- of the module \a uri, which will be one of the strings returned by keys().
-
- The plugin registers QML types with qmlRegisterType():
-
- \code
- qmlRegisterType<MyClass>("com.nokia.MyModule", 1, 0, "MyType", "MyClass");
- \endcode
-*/
-
-void QmlModulePlugin::defineModuleOnce(const QString& uri)
-{
- if (!defined.contains(uri)) {
- defined += uri;
- defineModule(uri);
- }
-}
-
-QT_END_NAMESPACE