diff options
Diffstat (limited to 'src/declarative')
-rw-r--r-- | src/declarative/qml/qmlengine.cpp | 183 | ||||
-rw-r--r-- | src/declarative/qml/qmlengine_p.h | 21 |
2 files changed, 123 insertions, 81 deletions
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index 9a5efdb..124c8f3 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -208,16 +208,101 @@ QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p) typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache; Q_GLOBAL_STATIC(FunctionCache, functionCache); +QScriptClass::QueryFlags +QmlEnginePrivate::queryContext(const QString &propName, uint *id, + QmlContext *bindContext) +{ + resolveData.safetyCheckId++; + *id = resolveData.safetyCheckId; + resolveData.clear(); + + QScriptClass::QueryFlags rv = 0; + QHash<QString, int>::Iterator contextProperty = + bindContext->d_func()->propertyNames.find(propName); + + if (contextProperty != bindContext->d_func()->propertyNames.end()) { + rv |= QScriptClass::HandlesReadAccess; + + resolveData.context = bindContext; + resolveData.contextIndex = *contextProperty; + + return rv; + } + + for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) { + rv = queryObject(propName, id, + bindContext->d_func()->defaultObjects.at(ii)); + } + + return rv; +} + +QScriptValue +QmlEnginePrivate::propertyContext(const QScriptString &name, + QmlContext *bindContext, + uint id) +{ + Q_ASSERT(id == resolveData.safetyCheckId); + + + if (resolveData.context) { + QmlContext *bindContext = resolveData.context; + QmlContextPrivate *contextPrivate = bindContext->d_func(); + int index = resolveData.contextIndex; + + QScriptValue rv; + if (index < contextPrivate->idValueCount) { + rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(contextPrivate->idValues[index].data()))); + } else { + QVariant value = contextPrivate->propertyValues.at(index); + if (QmlMetaType::isObject(value.userType())) { + rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(value)); + } else { + rv = scriptEngine.newVariant(value); + } + } + capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + contextPrivate->notifyIndex); + return rv; + + } else { + + return propertyObject(name, resolveData.object, id); + + } + + return QScriptValue(); +} + +void QmlEnginePrivate::setPropertyContext(const QScriptValue &value, uint id) +{ + // As context properties cannot be written, we can assume that the + // write is a object property write + setPropertyObject(value, id); +} + +void QmlEnginePrivate::setPropertyObject(const QScriptValue &value, uint id) +{ + Q_ASSERT(id == resolveData.safetyCheckId); + Q_Q(QmlEngine); + + resolveData.property.write(QmlScriptClass::toVariant(q, value)); +} + QScriptClass::QueryFlags QmlEnginePrivate::queryObject(const QString &propName, uint *id, QObject *obj) { + resolveData.safetyCheckId++; + *id = resolveData.safetyCheckId; + resolveData.clear(); + QScriptClass::QueryFlags rv = 0; QmlContext *ctxt = QmlEngine::contextForObject(obj); if (!ctxt) ctxt = rootContext; QmlMetaProperty prop(obj, propName, ctxt); + if (prop.type() == QmlMetaProperty::Invalid) { QPair<const QMetaObject *, QString> key = qMakePair(obj->metaObject(), propName); @@ -232,12 +317,13 @@ QmlEnginePrivate::queryObject(const QString &propName, } if (isFunction) { - *id = QmlScriptClass::FunctionId; + resolveData.object = obj; + resolveData.isFunction = true; rv |= QScriptClass::HandlesReadAccess; - } + } } else { - *id = QmlScriptClass::PropertyId; - *id |= prop.save(); + resolveData.object = obj; + resolveData.property = prop; rv |= QScriptClass::HandlesReadAccess; if (prop.isWritable()) @@ -257,15 +343,16 @@ Q_DECLARE_METATYPE(QmlValueTypeReference); QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName, QObject *obj, uint id) { - if (id == QmlScriptClass::FunctionId) { + Q_ASSERT(id == resolveData.safetyCheckId); + Q_ASSERT(resolveData.object); + + if (resolveData.isFunction) { + // ### Optimize QScriptValue sobj = scriptEngine.newQObject(obj); QScriptValue func = sobj.property(propName); return func; } else { - QmlMetaProperty prop; - prop.restore(id, obj); - if (!prop.isValid()) - return QScriptValue(); + const QmlMetaProperty &prop = resolveData.property; if (prop.needsChangedNotifier()) capturedProperties << CapturedProperty(prop); @@ -856,23 +943,11 @@ QmlContextScriptClass::queryProperty(const QScriptValue &object, Q_UNUSED(flags); QmlContext *bindContext = static_cast<QmlContext*>(object.data().toQObject()); - QueryFlags rv = 0; QString propName = name.toString(); - *id = InvalidId; - if (bindContext->d_func()->propertyNames.contains(propName)) { - rv |= HandlesReadAccess; - *id = VariantPropertyId; - } - - for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) { - rv = QmlEnginePrivate::get(engine)->queryObject(propName, id, bindContext->d_func()->defaultObjects.at(ii)); - if (rv) - *id |= (ii << 24); - } - - return rv; + QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); + return ep->queryContext(propName, id, bindContext); } QScriptValue QmlContextScriptClass::property(const QScriptValue &object, @@ -882,46 +957,8 @@ QScriptValue QmlContextScriptClass::property(const QScriptValue &object, QmlContext *bindContext = static_cast<QmlContext*>(object.data().toQObject()); - uint basicId = id & QmlScriptClass::ClassIdMask; - - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); - - switch (basicId) { - case VariantPropertyId: - { - QmlContextPrivate *contextPrivate = bindContext->d_func(); - QString propName = name.toString(); - int index = contextPrivate->propertyNames.value(propName); - - QScriptValue rv; - if (index < contextPrivate->idValueCount) { - rv = scriptEngine->newObject(ep->objectClass, scriptEngine->newVariant(QVariant::fromValue(contextPrivate->idValues[index].data()))); - } else { - QVariant value = contextPrivate->propertyValues.at(index); - if (QmlMetaType::isObject(value.userType())) { - rv = scriptEngine->newObject(ep->objectClass, scriptEngine->newVariant(value)); - } else { - rv = scriptEngine->newVariant(value); - } - } - ep->capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + bindContext->d_func()->notifyIndex); - return rv; - } - default: - { - int objId = (id & ClassIdSelectorMask) >> 24; - QObject *obj = bindContext->d_func()->defaultObjects.at(objId); - QScriptValue rv = ep->propertyObject(name, obj, - id & ~QmlScriptClass::ClassIdSelectorMask); - if (rv.isValid()) { - return rv; - } - break; - } - } - - return QScriptValue(); + return ep->propertyContext(name, bindContext, id); } void QmlContextScriptClass::setProperty(QScriptValue &object, @@ -931,17 +968,7 @@ void QmlContextScriptClass::setProperty(QScriptValue &object, { Q_UNUSED(name); - QmlContext *bindContext = - static_cast<QmlContext*>(object.data().toQObject()); - - int objIdx = (id & QmlScriptClass::ClassIdSelectorMask) >> 24; - QObject *obj = bindContext->d_func()->defaultObjects.at(objIdx); - - QmlMetaProperty prop; - prop.restore(id, obj); - - QVariant v = QmlScriptClass::toVariant(engine, value); - prop.write(v); + QmlEnginePrivate::get(engine)->setPropertyContext(value, id); } ///////////////////////////////////////////////////////////// @@ -1119,14 +1146,8 @@ void QmlObjectScriptClass::setProperty(QScriptValue &object, const QScriptValue &value) { Q_UNUSED(name); - - QObject *obj = object.data().toQObject(); - - QmlMetaProperty prop; - prop.restore(id, obj); - - QVariant v = QmlScriptClass::toVariant(engine, value); - prop.write(v); + Q_UNUSED(object); + QmlEnginePrivate::get(engine)->setPropertyObject(value, id); } diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index b595e7c..2c7409b 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -97,10 +97,17 @@ public: void init(); + QScriptClass::QueryFlags queryContext(const QString &name, uint *id, + QmlContext *); + QScriptValue propertyContext(const QScriptString &propName, QmlContext *, + uint id); + void setPropertyContext(const QScriptValue &, uint id); QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *); QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0); + void setPropertyObject(const QScriptValue &, uint id); + struct CapturedProperty { CapturedProperty(QObject *o, int c, int n) @@ -120,6 +127,20 @@ public: QScriptEngineDebugger *debugger; #endif + struct ResolveData { + ResolveData() : safetyCheckId(0) {} + int safetyCheckId; + + void clear() { + object = 0; context = 0; contextIndex = -1; isFunction = false; + } + QObject *object; + QmlContext *context; + + int contextIndex; + bool isFunction; + QmlMetaProperty property; + } resolveData; QmlContextScriptClass *contextClass; QmlObjectScriptClass *objectClass; QmlValueTypeScriptClass *valueTypeClass; |