diff options
author | Bea Lam <bea.lam@nokia.com> | 2010-03-16 02:09:27 (GMT) |
---|---|---|
committer | Bea Lam <bea.lam@nokia.com> | 2010-03-16 02:09:27 (GMT) |
commit | dd703f7a7e676f26dcb3ad634d75e0c9f677db43 (patch) | |
tree | f29f903c584349fe7ef67d43613f9fddaeb85aba /src/declarative/qml/qdeclarativeengine.cpp | |
parent | 081fafe395d52ae42b57c36d1279e6ac05ae2cde (diff) | |
parent | e56c5483fe8b292545bb9f004d796abd8ae00589 (diff) | |
download | Qt-dd703f7a7e676f26dcb3ad634d75e0c9f677db43.zip Qt-dd703f7a7e676f26dcb3ad634d75e0c9f677db43.tar.gz Qt-dd703f7a7e676f26dcb3ad634d75e0c9f677db43.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7
Conflicts:
src/declarative/qml/qdeclarativeengine.cpp
tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp
Diffstat (limited to 'src/declarative/qml/qdeclarativeengine.cpp')
-rw-r--r-- | src/declarative/qml/qdeclarativeengine.cpp | 193 |
1 files changed, 123 insertions, 70 deletions
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 3b8d603..e84e267 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -146,11 +146,11 @@ static bool qt_QmlQtModule_registered = false; void QDeclarativeEnginePrivate::defineModule() { - QML_REGISTER_TYPE(Qt,4,6,Component,QDeclarativeComponent); - QML_REGISTER_TYPE(Qt,4,6,QtObject,QObject); - QML_REGISTER_TYPE(Qt,4,6,WorkerScript,QDeclarativeWorkerScript); + qmlRegisterType<QDeclarativeComponent>("Qt",4,6,"Component"); + qmlRegisterType<QObject>("Qt",4,6,"QtObject"); + qmlRegisterType<QDeclarativeWorkerScript>("Qt",4,6,"WorkerScript"); - QML_REGISTER_NOCREATE_TYPE(QDeclarativeBinding); + qmlRegisterType<QDeclarativeBinding>(); } QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) @@ -242,7 +242,6 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr qtObject.setProperty(QLatin1String("formatDateTime"),newFunction(QDeclarativeEnginePrivate::formatDateTime, 2)); //misc methods - qtObject.setProperty(QLatin1String("closestAngle"), newFunction(QDeclarativeEnginePrivate::closestAngle, 2)); qtObject.setProperty(QLatin1String("openUrlExternally"),newFunction(QDeclarativeEnginePrivate::desktopOpenUrl, 1)); qtObject.setProperty(QLatin1String("md5"),newFunction(QDeclarativeEnginePrivate::md5, 1)); qtObject.setProperty(QLatin1String("btoa"),newFunction(QDeclarativeEnginePrivate::btoa, 1)); @@ -541,9 +540,9 @@ QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const This example creates a provider with id \e colors: - \snippet examples/declarative/imageprovider/main.cpp 0 + \snippet examples/declarative/imageprovider/imageprovider.cpp 0 - \snippet examples/declarative/imageprovider/view.qml 0 + \snippet examples/declarative/imageprovider/imageprovider.qml 0 \sa removeImageProvider() */ @@ -667,6 +666,61 @@ void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContex context->d_func()->contextObjects = data; } +/*! +\enum QDeclarativeEngine::ObjectOwnership + +Ownership controls whether or not QML automatically destroys the QObject when the object +is garbage collected by the JavaScript engine. The two ownership options are: + +\list +\o CppOwnership - The object is owned by C++ code, and will never be deleted by QML. The +JavaScript destroy() method cannot be used on objects with CppOwnership. This option +is similar to QScriptEngine::QtOwnership. + +\o JavaScriptOwnership - The object is owned by JavaScript. When the object is returned to QML +as the return value of a method call or property access, QML will delete the object if there +are no remaining JavaScript references to it and it has no QObject::parent(). This option +is similar to QScriptEngine::ScriptOwnership. +\endlist + +Generally an application doesn't need to set an object's ownership explicitly. QML uses +a heuristic to set the default object ownership. By default, an object that is created by +QML has JavaScriptOwnership. The exception to this are the root objects created by calling +QDeclarativeCompnent::create() or QDeclarativeComponent::beginCreate() which have +CppOwnership by default. The ownership of these root-level objects is considered to have +been transfered to the C++ caller. + +Objects not-created by QML have CppOwnership by default. The exception to this is objects +returned from a C++ method call. The ownership of these objects is passed to JavaScript. + +Calling setObjectOwnership() overrides the default ownership heuristic used by QML. +*/ + +/*! +Sets the \a ownership of \a object. +*/ +void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership) +{ + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object, true); + if (!ddata) + return; + + ddata->indestructible = (ownership == CppOwnership)?true:false; + ddata->explicitIndestructibleSet = true; +} + +/*! +Returns the ownership of \a object. +*/ +QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object) +{ + QDeclarativeDeclarativeData *ddata = QDeclarativeDeclarativeData::get(object, false); + if (!ddata) + return CppOwnership; + else + return ddata->indestructible?CppOwnership:JavaScriptOwnership; +} + void qmlExecuteDeferred(QObject *object) { QDeclarativeDeclarativeData *data = QDeclarativeDeclarativeData::get(object); @@ -777,6 +831,11 @@ void QDeclarativeDeclarativeData::destroyed(QObject *object) delete this; } +void QDeclarativeDeclarativeData::parentChanged(QObject *, QObject *parent) +{ + if (!parent && scriptValue.isValid()) scriptValue = QScriptValue(); +} + bool QDeclarativeDeclarativeData::hasBindingBit(int bit) const { if (bindingBitsSize > bit) @@ -857,6 +916,7 @@ QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QUrl url = QUrl(context->resolvedUrl(QUrl(arg))); QDeclarativeComponent *c = new QDeclarativeComponent(activeEngine, url, activeEngine); c->setCreationContext(context); + QDeclarativeDeclarativeData::get(c, true)->setImplicitDestructible(); return activeEnginePriv->objectClass->newQObject(c, qMetaTypeId<QDeclarativeComponent*>()); } } @@ -927,7 +987,8 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS if(gobj && gparent) gobj->setParentItem(gparent); - return qmlScriptObject(obj, activeEngine); + QDeclarativeDeclarativeData::get(obj, true)->setImplicitDestructible(); + return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar); } QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine) @@ -1176,25 +1237,6 @@ QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptE return QScriptValue(); } -QScriptValue QDeclarativeEnginePrivate::closestAngle(QScriptContext *ctxt, QScriptEngine *e) -{ - if(ctxt->argumentCount() < 2) - return e->newVariant(QVariant(0.0)); - qreal a = ctxt->argument(0).toNumber(); - qreal b = ctxt->argument(1).toNumber(); - qreal ret = b; - qreal diff = b-a; - while(diff > 180.0){ - ret -= 360.0; - diff -= 360.0; - } - while(diff < -180.0){ - ret += 360.0; - diff += 360.0; - } - return e->newVariant(QVariant(ret)); -} - QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 2) @@ -1300,10 +1342,13 @@ QVariant QDeclarativeScriptClass::toVariant(QDeclarativeEngine *engine, const QS // XXX this beyonds in QUrl::toLocalFile() static QString toLocalFileOrQrc(const QUrl& url) { - QString r = url.toLocalFile(); - if (r.isEmpty() && url.scheme() == QLatin1String("qrc")) - r = QLatin1Char(':') + url.path(); - return r; + if (url.scheme() == QLatin1String("qrc")) { + if (url.authority().isEmpty()) + return QLatin1Char(':') + url.path(); + qWarning() << "Invalid url:" << url.toString() << "authority" << url.authority() << "not known."; + return QString(); + } + return url.toLocalFile(); } ///////////////////////////////////////////////////////////// @@ -1315,7 +1360,7 @@ struct QDeclarativeEnginePrivate::ImportedNamespace { QList<bool> isLibrary; QList<QString> qmlDirContent; - bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return) const + bool find(const QByteArray& type, int *vmajor, int *vminor, QDeclarativeType** type_return, QUrl* url_return) { for (int i=0; i<urls.count(); ++i) { int vmaj = majversions.at(i); @@ -1325,14 +1370,10 @@ struct QDeclarativeEnginePrivate::ImportedNamespace { qt += '/'; qt += type; - if (qmlImportTrace()) - qDebug() << "Look in" << qt; QDeclarativeType *t = QDeclarativeMetaType::qmlType(qt,vmaj,vmin); if (t) { if (vmajor) *vmajor = vmaj; if (vminor) *vminor = vmin; - if (qmlImportTrace()) - qDebug() << "Found" << qt; if (type_return) *type_return = t; return true; @@ -1340,14 +1381,8 @@ struct QDeclarativeEnginePrivate::ImportedNamespace { QUrl url = QUrl(urls.at(i) + QLatin1Char('/') + QString::fromUtf8(type) + QLatin1String(".qml")); QString qmldircontent = qmlDirContent.at(i); - if (vmaj>=0 || !qmldircontent.isEmpty()) { - // Check version file - XXX cache these in QDeclarativeEngine! - if (qmldircontent.isEmpty()) { - QFile qmldir(toLocalFileOrQrc(QUrl(urls.at(i)+QLatin1String("/qmldir")))); - if (qmldir.open(QIODevice::ReadOnly)) { - qmldircontent = QString::fromUtf8(qmldir.readAll()); - } - } + + if (!qmldircontent.isEmpty()) { const QString typeName = QString::fromUtf8(type); @@ -1361,7 +1396,6 @@ struct QDeclarativeEnginePrivate::ImportedNamespace { if (c.typeName == typeName) { if (url_return) *url_return = url.resolved(QUrl(c.fileName)); - return true; } } @@ -1395,8 +1429,9 @@ public: QSet<QString> qmlDirFilesForWhichPluginsHaveBeenLoaded; - bool add(const QUrl& base, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, const QStringList& importPath, QDeclarativeEngine *engine) + bool add(const QUrl& base, const QString &qmldircontentnetwork, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType, const QStringList& importPath, QDeclarativeEngine *engine) { + QString qmldircontent = qmldircontentnetwork; QDeclarativeEnginePrivate::ImportedNamespace *s; if (prefix.isEmpty()) { s = &unqualifiedset; @@ -1409,15 +1444,21 @@ public: if (importType == QDeclarativeScriptParser::Import::Library) { url.replace(QLatin1Char('.'), QLatin1Char('/')); bool found = false; - QString content; QString dir; // user import paths QStringList paths; // base.. - paths += QFileInfo(base.toLocalFile()).path(); + QString localFileOrQrc = toLocalFileOrQrc(base); + QString localFileOrQrcPath = QFileInfo(localFileOrQrc).path(); + paths += localFileOrQrcPath; paths += importPath; + + QString applicationDirPath = QCoreApplication::applicationDirPath(); + if (!applicationDirPath.isEmpty()) + paths += applicationDirPath; + paths += QDeclarativeEnginePrivate::get(engine)->environmentImportPath; #if (QT_VERSION >= QT_VERSION_CHECK(4,7,0)) QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath); @@ -1429,6 +1470,7 @@ public: foreach (const QString &p, paths) { dir = p+QLatin1Char('/')+url; + QFileInfo fi(dir+QLatin1String("/qmldir")); const QString absoluteFilePath = fi.absoluteFilePath(); @@ -1438,22 +1480,31 @@ public: url = QUrl::fromLocalFile(fi.absolutePath()).toString(); QFile file(absoluteFilePath); - if (file.open(QFile::ReadOnly)) - content = QString::fromUtf8(file.readAll()); + if (file.open(QFile::ReadOnly)) { + qmldircontent = QString::fromUtf8(file.readAll()); + if (qmlImportTrace()) + qDebug() << "QDeclarativeEngine::add: loaded" << absoluteFilePath; + } if (! qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(absoluteFilePath)) { qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(absoluteFilePath); QDeclarativeDirParser qmldirParser; - qmldirParser.setSource(content); + qmldirParser.setSource(qmldircontent); qmldirParser.parse(); foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) { - QString resolvedFilePath = QDeclarativeEnginePrivate::get(engine)->resolvePlugin(QDir(dir + QDir::separator() + plugin.path), - plugin.name); - - if (!resolvedFilePath.isEmpty()) + QDir pluginDir(dir + QDir::separator() + plugin.path); + if (p.startsWith(QLatin1Char(':'))) + pluginDir = QDir(QCoreApplication::applicationDirPath()); + QString resolvedFilePath = + QDeclarativeEnginePrivate::get(engine) + ->resolvePlugin(pluginDir, + plugin.name); + + if (!resolvedFilePath.isEmpty()) { engine->importExtension(resolvedFilePath, uri); + } } } @@ -1641,9 +1692,10 @@ QUrl QDeclarativeEnginePrivate::Imports::baseUrl() const type version mapping and possibly declarative extensions plugins. The engine searches in the base directory of the qml file, then - the paths added via addImportPath(), then the paths specified in the - \c QML_IMPORT_PATH environment variable, then the builtin \c ImportsPath from - QLibraryInfo. + the paths added via addImportPath(), then in the directory containing the + application executable (QCoreApplication::applicationDirPath()), + then the paths specified in the \c QML_IMPORT_PATH environment variable, then the + builtin \c ImportsPath from QLibraryInfo. */ void QDeclarativeEngine::addImportPath(const QString& path) @@ -1655,13 +1707,13 @@ void QDeclarativeEngine::addImportPath(const QString& path) } /*! - Imports the given \a extension into this QDeclarativeEngine. Returns - true if the extension was successfully imported. - - \sa QDeclarativeExtensionInterface + Imports the extension named \a fileName from the \a uri provided. + Returns true if the extension was successfully imported. */ bool QDeclarativeEngine::importExtension(const QString &fileName, const QString &uri) { + if (qmlImportTrace()) + qDebug() << "QDeclarativeEngine::importExtension" << uri << "from" << fileName; QFileInfo fileInfo(fileName); const QString absoluteFilePath = fileInfo.absoluteFilePath(); QPluginLoader loader(absoluteFilePath); @@ -1785,6 +1837,9 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString return resolvePlugin(dir, baseName, QStringList() +# ifdef QT_DEBUG + << QLatin1String("_debug.dylib") // try a qmake-style debug build first +# endif << QLatin1String(".dylib") << QLatin1String(".so") << QLatin1String(".bundle"), @@ -1831,12 +1886,12 @@ QString QDeclarativeEnginePrivate::resolvePlugin(const QDir &dir, const QString The base URL must already have been set with Import::setBaseUrl(). */ -bool QDeclarativeEnginePrivate::addToImport(Imports* imports, const QString& qmldircontent, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType) const +bool QDeclarativeEnginePrivate::addToImport(Imports* imports, const QString &qmldircontentnetwork, const QString& uri, const QString& prefix, int vmaj, int vmin, QDeclarativeScriptParser::Import::Type importType) const { QDeclarativeEngine *engine = QDeclarativeEnginePrivate::get(const_cast<QDeclarativeEnginePrivate *>(this)); - bool ok = imports->d->add(imports->d->base,qmldircontent,uri,prefix,vmaj,vmin,importType,fileImportPath, engine); if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::addToImport(" << imports << uri << prefix << vmaj << '.' << vmin << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File") << ": " << ok; + qDebug() << "QDeclarativeEngine::addToImport(" << imports << uri << prefix << vmaj << '.' << vmin << (importType==QDeclarativeScriptParser::Import::Library? "Library" : "File"); + bool ok = imports->d->add(imports->d->base,qmldircontentnetwork, uri,prefix,vmaj,vmin,importType,fileImportPath, engine); return ok; } @@ -1856,8 +1911,6 @@ bool QDeclarativeEnginePrivate::resolveType(const Imports& imports, const QByteA { ImportedNamespace* ns = imports.d->findNamespace(QString::fromUtf8(type)); if (ns) { - if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::resolveType" << type << "is namespace for" << ns->urls; if (ns_return) *ns_return = ns; return true; @@ -1865,15 +1918,15 @@ bool QDeclarativeEnginePrivate::resolveType(const Imports& imports, const QByteA if (type_return || url_return) { if (imports.d->find(type,vmaj,vmin,type_return,url_return)) { if (qmlImportTrace()) { + if (type_return && *type_return && url_return && !url_return->isEmpty()) + qDebug() << "QDeclarativeEngine::resolveType" << type << '=' << (*type_return)->typeName() << *url_return; if (type_return && *type_return) qDebug() << "QDeclarativeEngine::resolveType" << type << '=' << (*type_return)->typeName(); - if (url_return) + if (url_return && !url_return->isEmpty()) qDebug() << "QDeclarativeEngine::resolveType" << type << '=' << *url_return; } return true; } - if (qmlImportTrace()) - qDebug() << "QDeclarativeEngine::resolveType" << type << "not found"; } return false; } |