diff options
author | Roberto Raggi <roberto.raggi@nokia.com> | 2010-02-23 14:37:36 (GMT) |
---|---|---|
committer | Roberto Raggi <roberto.raggi@nokia.com> | 2010-02-23 14:37:36 (GMT) |
commit | ab8477a347b286f84c7747ca0ae39bbd139a5f01 (patch) | |
tree | af845c2a783e0e3684f46dd02978bf86c937ccdb /src/declarative | |
parent | 742befdd5077b27de79ca5ee6f9182540d0d5863 (diff) | |
parent | 5b99df32ea16775923f7060d8b0c7ee6f9c635d8 (diff) | |
download | Qt-ab8477a347b286f84c7747ca0ae39bbd139a5f01.zip Qt-ab8477a347b286f84c7747ca0ae39bbd139a5f01.tar.gz Qt-ab8477a347b286f84c7747ca0ae39bbd139a5f01.tar.bz2 |
Merge branch 'qtruntime'
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/qml/qml.pri | 10 | ||||
-rw-r--r-- | src/declarative/qml/qmldirparser.cpp | 220 | ||||
-rw-r--r-- | src/declarative/qml/qmldirparser_p.h | 125 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 256 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 10 | ||||
-rw-r--r-- | src/declarative/qml/qmlextensioninterface.h | 66 | ||||
-rw-r--r-- | src/declarative/qml/qmlextensionplugin.cpp | 87 | ||||
-rw-r--r-- | src/declarative/qml/qmlextensionplugin.h (renamed from src/declarative/qml/qmlmoduleplugin.h) | 36 | ||||
-rw-r--r-- | src/declarative/qml/qmlmoduleplugin.cpp | 111 | ||||
-rw-r--r-- | src/declarative/util/qmlview.cpp | 94 | ||||
-rw-r--r-- | src/declarative/util/qmlview.h | 3 |
12 files changed, 774 insertions, 245 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 diff --git a/src/declarative/util/qmlview.cpp b/src/declarative/util/qmlview.cpp index 05c6460..9e95b66 100644 --- a/src/declarative/util/qmlview.cpp +++ b/src/declarative/util/qmlview.cpp @@ -425,52 +425,58 @@ void QmlView::continueExecute() return; } - if (obj) { - if (QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(obj)) { - - d->scene.addItem(item); - - QPerformanceLog::displayData(); - QPerformanceLog::clear(); - d->root = item; - d->qmlRoot = item; - connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged())); - connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged())); - if (d->initialSize.height() <= 0 && d->qmlRoot->width() > 0) - d->initialSize.setWidth(d->qmlRoot->width()); - if (d->initialSize.height() <= 0 && d->qmlRoot->height() > 0) - d->initialSize.setHeight(d->qmlRoot->height()); - resize(d->initialSize); - - if (d->resizeMode == SizeRootObjectToView) { - d->qmlRoot->setWidth(width()); - d->qmlRoot->setHeight(height()); - } else { - QSize sz(d->qmlRoot->width(),d->qmlRoot->height()); - emit sceneResized(sz); - resize(sz); - } - updateGeometry(); - } else if (QGraphicsObject *item = qobject_cast<QGraphicsObject *>(obj)) { - d->scene.addItem(item); - qWarning() << "QmlView::resizeMode is not honored for components of type QGraphicsObject"; - } else if (QWidget *wid = qobject_cast<QWidget *>(obj)) { - window()->setAttribute(Qt::WA_OpaquePaintEvent, false); - window()->setAttribute(Qt::WA_NoSystemBackground, false); - if (!layout()) { - setLayout(new QVBoxLayout); - layout()->setContentsMargins(0, 0, 0, 0); - } else if (layout()->count()) { - // Hide the QGraphicsView in GV mode. - QLayoutItem *item = layout()->itemAt(0); - if (item->widget()) - item->widget()->hide(); - } - layout()->addWidget(wid); - emit sceneResized(wid->size()); + setRootObject(obj); + emit statusChanged(status()); +} + + +/*! + \internal +*/ +void QmlView::setRootObject(QObject *obj) +{ + if (QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(obj)) { + d->scene.addItem(item); + + QPerformanceLog::displayData(); + QPerformanceLog::clear(); + d->root = item; + d->qmlRoot = item; + connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged())); + connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged())); + if (d->initialSize.height() <= 0 && d->qmlRoot->width() > 0) + d->initialSize.setWidth(d->qmlRoot->width()); + if (d->initialSize.height() <= 0 && d->qmlRoot->height() > 0) + d->initialSize.setHeight(d->qmlRoot->height()); + resize(d->initialSize); + + if (d->resizeMode == SizeRootObjectToView) { + d->qmlRoot->setWidth(width()); + d->qmlRoot->setHeight(height()); + } else { + QSize sz(d->qmlRoot->width(),d->qmlRoot->height()); + emit sceneResized(sz); + resize(sz); } + updateGeometry(); + } else if (QGraphicsObject *item = qobject_cast<QGraphicsObject *>(obj)) { + d->scene.addItem(item); + qWarning() << "QmlView::resizeMode is not honored for components of type QGraphicsObject"; + } else if (QWidget *wid = qobject_cast<QWidget *>(obj)) { + window()->setAttribute(Qt::WA_OpaquePaintEvent, false); + window()->setAttribute(Qt::WA_NoSystemBackground, false); + if (!layout()) { + setLayout(new QVBoxLayout); + layout()->setContentsMargins(0, 0, 0, 0); + } else if (layout()->count()) { + // Hide the QGraphicsView in GV mode. + QLayoutItem *item = layout()->itemAt(0); + if (item->widget()) + item->widget()->hide(); + } + layout()->addWidget(wid); + emit sceneResized(wid->size()); } - emit statusChanged(status()); } /*! diff --git a/src/declarative/util/qmlview.h b/src/declarative/util/qmlview.h index 5f72781..26be18f 100644 --- a/src/declarative/util/qmlview.h +++ b/src/declarative/util/qmlview.h @@ -100,7 +100,8 @@ private Q_SLOTS: protected: virtual void resizeEvent(QResizeEvent *); virtual void paintEvent(QPaintEvent *event); - void timerEvent(QTimerEvent*); + virtual void timerEvent(QTimerEvent*); + virtual void setRootObject(QObject *obj); friend class QmlViewPrivate; QmlViewPrivate *d; |