From 87d71b29a8c4239cb807f13ac9d009cef1ca1a69 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 8 Feb 2010 13:49:09 +1000 Subject: Allow objects to be shared between QmlEngines QTBUG-7957 --- src/declarative/qml/qmlcompiledbindings.cpp | 33 +----------- src/declarative/qml/qmlcontext.cpp | 15 +++--- src/declarative/qml/qmlengine_p.h | 1 + src/declarative/qml/qmlmetaproperty.cpp | 23 ++------- src/declarative/qml/qmlobjectscriptclass.cpp | 18 +------ src/declarative/qml/qmlpropertycache.cpp | 60 ++++++++++++++++++++++ src/declarative/qml/qmlpropertycache_p.h | 8 +++ .../qmlecmascript/data/multiEngineObject.qml | 5 ++ .../qmlecmascript/tst_qmlecmascript.cpp | 24 +++++++++ 9 files changed, 112 insertions(+), 75 deletions(-) create mode 100644 tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml diff --git a/src/declarative/qml/qmlcompiledbindings.cpp b/src/declarative/qml/qmlcompiledbindings.cpp index d09f7eb..cdea96f 100644 --- a/src/declarative/qml/qmlcompiledbindings.cpp +++ b/src/declarative/qml/qmlcompiledbindings.cpp @@ -807,36 +807,6 @@ static QObject *variantToQObject(const QVariant &value, bool *ok) } } -QmlPropertyCache::Data * -QmlCompiledBindingsPrivate::findproperty(QObject *obj, - const QScriptDeclarativeClass::Identifier &name, - QmlEnginePrivate *enginePriv, - QmlPropertyCache::Data &local) -{ - QmlPropertyCache *cache = 0; - QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); - if (ddata) - cache = ddata->propertyCache; - if (!cache) { - cache = enginePriv->cache(obj); - if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; } - } - - QmlPropertyCache::Data *property = 0; - - if (cache) { - property = cache->property(name); - } else { - qWarning() << "QmlBindingVME: Slow search" << enginePriv->objectClass->toString(name); - local = QmlPropertyCache::create(obj->metaObject(), - enginePriv->objectClass->toString(name)); - if (local.isValid()) - property = &local; - } - - return property; -} - bool QmlCompiledBindingsPrivate::findproperty(QObject *obj, Register *output, QmlEnginePrivate *enginePriv, int subIdx, const QScriptDeclarativeClass::Identifier &name, @@ -848,7 +818,8 @@ bool QmlCompiledBindingsPrivate::findproperty(QObject *obj, Register *output, } QmlPropertyCache::Data local; - QmlPropertyCache::Data *property = findproperty(obj, name, enginePriv, local); + QmlPropertyCache::Data *property = + QmlPropertyCache::property(QmlEnginePrivate::get(enginePriv), obj, name, local); if (property) { if (subIdx != -1) diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 0eb497d..4c6dc6f 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -461,16 +461,13 @@ QVariant QmlContext::contextProperty(const QString &name) const QByteArray utf8Name = name.toUtf8(); for (int ii = d->defaultObjects.count() - 1; ii >= 0; --ii) { QObject *obj = d->defaultObjects.at(ii); - QmlDeclarativeData *data = QmlDeclarativeData::get(obj); - if (data && data->propertyCache) { - QmlPropertyCache::Data *property = data->propertyCache->property(name); - if (property) - value = obj->metaObject()->property(property->coreIndex).read(obj); - } else { - value = obj->property(utf8Name); - } - if (value.isValid()) + QmlPropertyCache::Data local; + QmlPropertyCache::Data *property = QmlPropertyCache::property(d->engine, obj, name, local); + + if (property) { + value = obj->metaObject()->property(property->coreIndex).read(obj); break; + } } if (!value.isValid() && parentContext()) value = parentContext()->contextProperty(name); diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index 6aa5d69..8349090 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -309,6 +309,7 @@ public: static QmlEngine *getEngine(QScriptEngine *e) { return static_cast(e)->p->q_func(); } static QmlEnginePrivate *get(QmlEngine *e) { return e->d_func(); } static QmlEnginePrivate *get(QScriptEngine *e) { return static_cast(e)->p; } + static QmlEngine *get(QmlEnginePrivate *p) { return p->q_func(); } QmlContext *getContext(QScriptContext *); }; diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 0603a9c..09c936e 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -188,24 +188,11 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) } // Property - QmlPropertyCache *cache = 0; - QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); - if (ddata) - cache = ddata->propertyCache; - if (!cache) - cache = enginePrivate?enginePrivate->cache(obj):0; - - if (cache) { - QmlPropertyCache::Data *data = cache->property(name); - - if (data && !(data->flags & QmlPropertyCache::Data::IsFunction)) - core = *data; - - } else { - // No cache available - QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData()); - core.load(p); - } + QmlPropertyCache::Data local; + QmlPropertyCache::Data *property = + QmlPropertyCache::property(context?context->engine():0, obj, name, local); + if (property && !(property->flags & QmlPropertyCache::Data::IsFunction)) + core = *property; } /*! diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 4ff4746..7bbb7df 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -144,23 +144,7 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, return 0; QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine); - - QmlPropertyCache *cache = 0; - QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); - if (ddata) - cache = ddata->propertyCache; - if (!cache) { - cache = enginePrivate->cache(obj); - if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; } - } - - if (cache) { - lastData = cache->property(name); - } else { - local = QmlPropertyCache::create(obj->metaObject(), toString(name)); - if (local.isValid()) - lastData = &local; - } + lastData = QmlPropertyCache::property(engine, obj, name, local); if (lastData) return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index 51753b8..04cffe1 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -352,4 +352,64 @@ QStringList QmlPropertyCache::propertyNames() const return stringCache.keys(); } +QmlPropertyCache::Data *QmlPropertyCache::property(QmlEngine *engine, QObject *obj, + const QScriptDeclarativeClass::Identifier &name, Data &local) +{ + QmlPropertyCache::Data *rv = 0; + + QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine); + + QmlPropertyCache *cache = 0; + QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); + if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine) + cache = ddata->propertyCache; + if (!cache) { + cache = enginePrivate->cache(obj); + if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; } + } + + if (cache) { + rv = cache->property(name); + } else { + local = QmlPropertyCache::create(obj->metaObject(), enginePrivate->objectClass->toString(name)); + if (local.isValid()) + rv = &local; + } + + return rv; +} + +QmlPropertyCache::Data *QmlPropertyCache::property(QmlEngine *engine, QObject *obj, + const QString &name, Data &local) +{ + QmlPropertyCache::Data *rv = 0; + + if (!engine) { + local = QmlPropertyCache::create(obj->metaObject(), name); + if (local.isValid()) + rv = &local; + } else { + QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine); + + QmlPropertyCache *cache = 0; + QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj); + if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine) + cache = ddata->propertyCache; + if (!cache) { + cache = enginePrivate->cache(obj); + if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; } + } + + if (cache) { + rv = cache->property(name); + } else { + local = QmlPropertyCache::create(obj->metaObject(), name); + if (local.isValid()) + rv = &local; + } + } + + return rv; +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index 8d54e35..efc4643 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -132,6 +132,9 @@ public: Data *property(int) const; QStringList propertyNames() const; + inline QmlEngine *qmlEngine() const; + static Data *property(QmlEngine *, QObject *, const QScriptDeclarativeClass::Identifier &, Data &); + static Data *property(QmlEngine *, QObject *, const QString &, Data &); protected: virtual void clear(); @@ -181,6 +184,11 @@ bool QmlPropertyCache::ValueTypeData::operator==(const ValueTypeData &o) valueTypePropType == o.valueTypePropType; } +QmlEngine *QmlPropertyCache::qmlEngine() const +{ + return engine; +} + QT_END_NAMESPACE #endif // QMLPROPERTYCACHE_P_H diff --git a/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml b/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml new file mode 100644 index 0000000..7da09e4 --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml @@ -0,0 +1,5 @@ +import Qt 4.6 + +QtObject { + property string test: thing.stringProperty +} diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index c41e248..1ba9a52 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -119,6 +119,7 @@ private slots: void jsObject(); void undefinedResetsProperty(); void listToVariant(); + void multiEngineObject(); void bug1(); @@ -1610,7 +1611,30 @@ void tst_qmlecmascript::listToVariant() QCOMPARE(object->property("test"), QVariant::fromValue(container.children())); delete object; +} + +// QTBUG-7957 +void tst_qmlecmascript::multiEngineObject() +{ + MyQmlObject obj; + obj.setStringProperty("Howdy planet"); + + QmlEngine e1; + e1.rootContext()->setContextProperty("thing", &obj); + QmlComponent c1(&e1, TEST_FILE("multiEngineObject.qml")); + + QmlEngine e2; + e2.rootContext()->setContextProperty("thing", &obj); + QmlComponent c2(&e2, TEST_FILE("multiEngineObject.qml")); + + QObject *o1 = c1.create(); + QObject *o2 = c2.create(); + + QCOMPARE(o1->property("test").toString(), QString("Howdy planet")); + QCOMPARE(o2->property("test").toString(), QString("Howdy planet")); + delete o2; + delete o1; } QTEST_MAIN(tst_qmlecmascript) -- cgit v0.12