diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-04-10 08:58:00 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-04-10 08:58:00 (GMT) |
commit | 9a05223ea9a6ee0dbaac256607be201ea08e6fb6 (patch) | |
tree | 54e5407758a18954bdaf64146b8d3ad8532b9297 /src/declarative/qml/qdeclarativeengine.cpp | |
parent | ac27c8ad39a9646a9e509ba7a58f75eeae10bb6e (diff) | |
parent | bfc6a32c2a203766a6debdf19a265a4f0e198403 (diff) | |
download | Qt-9a05223ea9a6ee0dbaac256607be201ea08e6fb6.zip Qt-9a05223ea9a6ee0dbaac256607be201ea08e6fb6.tar.gz Qt-9a05223ea9a6ee0dbaac256607be201ea08e6fb6.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/qt-qml: (119 commits)
Add Mac OS X bundle description for qml runtime
Cleanup
Disallow writes to read-only value type properties
Allow undefined to be assigned to QVariant properties
Add a Qt.isQtObject() method
Fix crash in QML library imports
Remove QT_VERSION checks in QML
List properties aren't read-only
Small doc fix.
Make sure WorkerScript thread is stopped on deletion. This also fixes
Release ListModel's worker agent on deletion.
Doc fixes
Fix example
Example code style improvements
Enable other wrapping modes.
TextEdit::wrap changed to TextEdit::wrapMode enumeration
Remove use of obsolete "Script" element.
unwarn
Replace "var" with "variant" in tests
Fix test after deletion of GraphicsObjectContainer.
...
Diffstat (limited to 'src/declarative/qml/qdeclarativeengine.cpp')
-rw-r--r-- | src/declarative/qml/qdeclarativeengine.cpp | 261 |
1 files changed, 195 insertions, 66 deletions
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 52a1f45..e459d0f 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -61,7 +61,6 @@ #include "private/qdeclarativeglobal_p.h" #include "private/qdeclarativeworkerscript_p.h" #include "private/qdeclarativecomponent_p.h" -#include "private/qdeclarativescriptclass_p.h" #include "qdeclarativenetworkaccessmanagerfactory.h" #include "qdeclarativeimageprovider.h" #include "private/qdeclarativedirparser_p.h" @@ -183,11 +182,11 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) fileImportPath.append(canonicalPath); } } -#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); if (!builtinPath.isEmpty()) fileImportPath += builtinPath; -#endif + + filePluginPath += QLatin1String("."); } @@ -226,6 +225,7 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr // XXX used to add Qt.Sound class. //types + qtObject.setProperty(QLatin1String("isQtObject"), newFunction(QDeclarativeEnginePrivate::isQtObject, 1)); qtObject.setProperty(QLatin1String("rgba"), newFunction(QDeclarativeEnginePrivate::rgba, 4)); qtObject.setProperty(QLatin1String("hsla"), newFunction(QDeclarativeEnginePrivate::hsla, 4)); qtObject.setProperty(QLatin1String("rect"), newFunction(QDeclarativeEnginePrivate::rect, 4)); @@ -346,6 +346,17 @@ Q_GLOBAL_STATIC(QDeclarativeEngineDebugServer, qmlEngineDebugServer); typedef QMap<QString, QString> StringStringMap; Q_GLOBAL_STATIC(StringStringMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri + +void QDeclarativeDeclarativeData::destroyed(QDeclarativeData *d, QObject *o) +{ + static_cast<QDeclarativeDeclarativeData *>(d)->destroyed(o); +} + +void QDeclarativeDeclarativeData::parentChanged(QDeclarativeData *d, QObject *o, QObject *p) +{ + static_cast<QDeclarativeDeclarativeData *>(d)->parentChanged(o, p); +} + void QDeclarativeEnginePrivate::init() { Q_Q(QDeclarativeEngine); @@ -353,6 +364,8 @@ void QDeclarativeEnginePrivate::init() qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString"); qRegisterMetaType<QScriptValue>("QScriptValue"); + QDeclarativeDeclarativeData::init(); + contextClass = new QDeclarativeContextScriptClass(q); objectClass = new QDeclarativeObjectScriptClass(q); valueTypeClass = new QDeclarativeValueTypeScriptClass(q); @@ -396,7 +409,7 @@ QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine \code QDeclarativeEngine engine; QDeclarativeComponent component(&engine); - component.setData("import Qt 4.6\nText { text: \"Hello world!\" }", QUrl()); + component.setData("import Qt 4.7\nText { text: \"Hello world!\" }", QUrl()); QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create()); //add item to view, etc @@ -848,15 +861,16 @@ void QDeclarativeDeclarativeData::destroyed(QObject *object) if (ownContext) context->destroy(); + if (scriptValue) + delete scriptValue; + if (ownMemory) delete this; - else - this->~QDeclarativeDeclarativeData(); } void QDeclarativeDeclarativeData::parentChanged(QObject *, QObject *parent) { - if (!parent && scriptValue.isValid()) scriptValue = QScriptValue(); + if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; } } bool QDeclarativeDeclarativeData::hasBindingBit(int bit) const @@ -1014,6 +1028,14 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar); } +QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScriptEngine *engine) +{ + if (ctxt->argumentCount() == 0) + return QScriptValue(engine, false); + + return QScriptValue(engine, 0 != ctxt->argument(0).toQObject()); +} + QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 3) @@ -1310,7 +1332,6 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine return qScriptValueFromValue(engine, qVariantFromValue(finalColor)); } - QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) { if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) { @@ -1321,6 +1342,14 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } else { return scriptEngine.nullValue(); } + } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) { + const QList<QObject *> &list = *(QList<QObject *>*)val.constData(); + QScriptValue rv = scriptEngine.newArray(list.count()); + for (int ii = 0; ii < list.count(); ++ii) { + QObject *object = list.at(ii); + rv.setProperty(ii, objectClass->newQObject(object)); + } + return rv; } bool objOk; @@ -1332,35 +1361,29 @@ QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &v } } -QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val) +QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint) { QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); if (dc == objectClass) return QVariant::fromValue(objectClass->toQObject(val)); + else if (dc == valueTypeClass) + return valueTypeClass->toVariant(val); else if (dc == contextClass) return QVariant(); - QScriptDeclarativeClass *sc = QScriptDeclarativeClass::scriptClass(val); - if (!sc) { - return val.toVariant(); - } else if (sc == valueTypeClass) { - return valueTypeClass->toVariant(val); - } else { - return QVariant(); + // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted + if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) { + QList<QObject *> list; + int length = val.property(QLatin1String("length")).toInt32(); + for (int ii = 0; ii < length; ++ii) { + QScriptValue arrayItem = val.property(ii); + QObject *d = arrayItem.toQObject(); + list << d; + } + return QVariant::fromValue(list); } -} -QDeclarativeScriptClass::QDeclarativeScriptClass(QScriptEngine *engine) -: QScriptDeclarativeClass(engine) -{ -} - -QVariant QDeclarativeScriptClass::toVariant(QDeclarativeEngine *engine, const QScriptValue &val) -{ - QDeclarativeEnginePrivate *ep = - static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine)); - - return ep->scriptValueToVariant(val); + return val.toVariant(); } // XXX this beyonds in QUrl::toLocalFile() @@ -1463,13 +1486,17 @@ public: QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded; - QDeclarativeDirComponents importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeEngine *engine) { + QDeclarativeDirComponents importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeEngine *engine, QString *errorString) { QFile file(absoluteFilePath); QString filecontent; if (file.open(QFile::ReadOnly)) { filecontent = QString::fromUtf8(file.readAll()); if (qmlImportTrace()) qDebug() << "QDeclarativeEngine::add: loaded" << absoluteFilePath; + } else { + if (errorString) + *errorString = QDeclarativeEngine::tr("module \"%1\" definition \"%2\" not readable").arg(uri).arg(absoluteFilePath); + return QDeclarativeDirComponents(); } QDir dir = QFileInfo(file).dir(); @@ -1483,19 +1510,21 @@ public: foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) { - QDir pluginDir = dir.absoluteFilePath(plugin.path); - - // hack for resources, should probably go away - if (absoluteFilePath.startsWith(QLatin1Char(':'))) - pluginDir = QDir(QCoreApplication::applicationDirPath()); - QString resolvedFilePath = QDeclarativeEnginePrivate::get(engine) - ->resolvePlugin(pluginDir, + ->resolvePlugin(dir, plugin.path, plugin.name); if (!resolvedFilePath.isEmpty()) { - engine->importExtension(resolvedFilePath, uri); + if (!engine->importPlugin(resolvedFilePath, uri)) { + if (errorString) + *errorString = QDeclarativeEngine::tr("plugin \"%1\" cannot be loaded for module \"%2\"").arg(resolvedFilePath).arg(uri); + return QDeclarativeDirComponents(); + } + } else { + if (errorString) + *errorString = QDeclarativeEngine::tr("module \"%1\" plugin \"%2\" not found").arg(uri).arg(plugin.name); + return QDeclarativeDirComponents(); } } } @@ -1560,7 +1589,9 @@ public: url = QUrl::fromLocalFile(fi.absolutePath()).toString(); uri = resolvedUri(dir, engine); - qmldircomponents = importExtension(absoluteFilePath, uri, engine); + qmldircomponents = importExtension(absoluteFilePath, uri, engine, errorString); + if (qmldircomponents.isEmpty()) // error (or empty) + return false; break; } } @@ -1591,12 +1622,14 @@ public: return false; // local import dirs must exist } uri = resolvedUri(toLocalFileOrQrc(base.resolved(QUrl(uri))), engine); - qmldircomponents = importExtension(localFileOrQrc, - uri, - engine); - if (uri.endsWith(QLatin1Char('/'))) uri.chop(1); + if (QFile::exists(localFileOrQrc)) { + qmldircomponents = importExtension(localFileOrQrc, + uri,engine,errorString); + if (qmldircomponents.isEmpty()) // error (or empty) + return false; + } } else { if (prefix.isEmpty()) { // directory must at least exist for valid import @@ -1619,6 +1652,18 @@ public: url.chop(1); } + if (vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) { + QList<QDeclarativeDirParser::Component>::ConstIterator it = qmldircomponents.begin(); + for (; it != qmldircomponents.end(); ++it) { + if (it->majorVersion > vmaj || (it->majorVersion == vmaj && it->minorVersion >= vmin)) + break; + } + if (it == qmldircomponents.end()) { + *errorString = QDeclarativeEngine::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); + return false; + } + } + s->uris.prepend(uri); s->urls.prepend(url); s->majversions.prepend(vmaj); @@ -1778,8 +1823,8 @@ QUrl QDeclarativeEnginePrivate::Imports::baseUrl() const } /*! - Adds \a path as a directory where installed QML components are - defined in a URL-based directory structure. + Adds \a path as a directory where the engine searches for + installed modules in a URL-based directory structure. The newly added \a path will be first in the importPathList(). @@ -1802,7 +1847,7 @@ void QDeclarativeEngine::addImportPath(const QString& path) /*! Returns the list of directories where the engine searches for - installed modules. + installed modules in a URL-based directory structure. For example, if \c /opt/MyApp/lib/imports is in the path, then QML that imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look @@ -1823,7 +1868,7 @@ QStringList QDeclarativeEngine::importPathList() const /*! Sets the list of directories where the engine searches for - installed modules. + installed modules in a URL-based directory structure. By default, the list contains the paths specified in the \c QML_IMPORT_PATH environment variable, then the builtin \c ImportsPath from QLibraryInfo. @@ -1836,15 +1881,73 @@ void QDeclarativeEngine::setImportPathList(const QStringList &paths) d->fileImportPath = paths; } + +/*! + Adds \a path as a directory where the engine searches for + native plugins for imported modules (referenced in the \c qmldir file). + + By default, the list contains only \c ., i.e. the engine searches + in the directory of the \c qmldir file itself. + + The newly added \a path will be first in the pluginPathList(). + + \sa setPluginPathList() +*/ +void QDeclarativeEngine::addPluginPath(const QString& path) +{ + if (qmlImportTrace()) + qDebug() << "QDeclarativeEngine::addPluginPath" << path; + Q_D(QDeclarativeEngine); + QUrl url = QUrl(path); + if (url.isRelative() || url.scheme() == QString::fromLocal8Bit("file")) { + QDir dir = QDir(path); + d->filePluginPath.prepend(dir.canonicalPath()); + } else { + d->filePluginPath.prepend(path); + } +} + + +/*! + Returns the list of directories where the engine searches for + native plugins for imported modules (referenced in the \c qmldir file). + + By default, the list contains only \c ., i.e. the engine searches + in the directory of the \c qmldir file itself. + + \sa addPluginPath() setPluginPathList() +*/ +QStringList QDeclarativeEngine::pluginPathList() const +{ + Q_D(const QDeclarativeEngine); + return d->filePluginPath; +} + +/*! + Sets the list of directories where the engine searches for + native plugins for imported modules (referenced in the \c qmldir file). + + By default, the list contains only \c ., i.e. the engine searches + in the directory of the \c qmldir file itself. + + \sa pluginPathList() addPluginPath() + */ +void QDeclarativeEngine::setPluginPathList(const QStringList &paths) +{ + Q_D(QDeclarativeEngine); + d->filePluginPath = paths; +} + + /*! - Imports the extension named \a fileName from the \a uri provided. - Returns true if the extension was successfully imported. + Imports the plugin named \a filePath with the \a uri provided. + Returns true if the plugin was successfully imported; otherwise returns false. */ -bool QDeclarativeEngine::importExtension(const QString &fileName, const QString &uri) +bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri) { if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::importExtension" << uri << "from" << fileName; - QFileInfo fileInfo(fileName); + qDebug() << "QDeclarativeEngine::importPlugin" << uri << "from" << filePath; + QFileInfo fileInfo(filePath); const QString absoluteFilePath = fileInfo.absoluteFilePath(); QDeclarativeEnginePrivate *d = QDeclarativeEnginePrivate::get(this); @@ -1917,27 +2020,53 @@ QString QDeclarativeEngine::offlineStoragePath() const /*! \internal - Returns the result of the merge of \a baseName with \a dir, \a suffixes, and \a prefix. + Returns the result of the merge of \a baseName with \a path, \a suffixes, and \a prefix. The \a prefix must contain the dot. + + \a qmldirPath is the location of the qmldir file. */ -QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName, +QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, const QString &baseName, const QStringList &suffixes, const QString &prefix) { - foreach (const QString &suffix, suffixes) { - QString pluginFileName = prefix; + QStringList searchPaths = filePluginPath; + bool qmldirPluginPathIsRelative = QDir::isRelativePath(qmldirPluginPath); + if (!qmldirPluginPathIsRelative) + searchPaths.prepend(qmldirPluginPath); - pluginFileName += baseName; - pluginFileName += suffix; + foreach (const QString &pluginPath, searchPaths) { - QFileInfo fileInfo(dir, pluginFileName); + QString resolvedPath; + + if (pluginPath == QLatin1String(".")) { + if (qmldirPluginPathIsRelative) + resolvedPath = qmldirPath.absoluteFilePath(qmldirPluginPath); + else + resolvedPath = qmldirPath.absolutePath(); + } else { + resolvedPath = pluginPath; + } - if (fileInfo.exists()) - return fileInfo.absoluteFilePath(); + // hack for resources, should probably go away + if (resolvedPath.startsWith(QLatin1Char(':'))) + resolvedPath = QCoreApplication::applicationDirPath(); + + QDir dir(resolvedPath); + foreach (const QString &suffix, suffixes) { + QString pluginFileName = prefix; + + pluginFileName += baseName; + pluginFileName += suffix; + + QFileInfo fileInfo(dir, pluginFileName); + + if (fileInfo.exists()) + return fileInfo.absoluteFilePath(); + } } if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::resolvePlugin: Could not resolve plugin" << baseName << "in" << dir.absolutePath(); + qDebug() << "QDeclarativeEngine::resolvePlugin: Could not resolve plugin" << baseName << "in" << qmldirPath.absolutePath(); return QString(); } @@ -1958,17 +2087,17 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString Version number on unix are ignored. */ -QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString &baseName) +QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &qmldirPath, const QString &qmldirPluginPath, const QString &baseName) { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - return resolvePlugin(dir, baseName, + return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, QStringList() # ifdef QT_DEBUG << QLatin1String("d.dll") // try a qmake-style debug build first # endif << QLatin1String(".dll")); #elif defined(Q_OS_SYMBIAN) - return resolvePlugin(dir, baseName, + return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, QStringList() << QLatin1String(".dll") << QLatin1String(".qtplugin")); @@ -1976,7 +2105,7 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString # if defined(Q_OS_DARWIN) - return resolvePlugin(dir, baseName, + return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, QStringList() # ifdef QT_DEBUG << QLatin1String("_debug.dylib") // try a qmake-style debug build first @@ -2010,7 +2139,7 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString // Examples of valid library names: // libfoo.so - return resolvePlugin(dir, baseName, validSuffixList, QLatin1String("lib")); + return resolvePlugin(qmldirPath, qmldirPluginPath, baseName, validSuffixList, QLatin1String("lib")); # endif #endif |