From 361a605e9269f3072c1f5597a8db0622cf3b116b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 1 Oct 2009 17:36:35 +1000 Subject: Read/write property directly from QmlObjectScriptClass --- src/declarative/qml/qmlcontext.cpp | 1 - src/declarative/qml/qmlobjectscriptclass.cpp | 110 +++++++++------------------ src/declarative/qml/qmlobjectscriptclass_p.h | 2 + src/declarative/qml/qmlpropertycache.cpp | 37 +++++++++ src/declarative/qml/qmlpropertycache_p.h | 16 ++-- 5 files changed, 83 insertions(+), 83 deletions(-) diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 1c9d177..5e74d1a 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -386,7 +386,6 @@ void QmlContextPrivate::setIdProperty(const QString &name, int idx, notifyIndex = q->metaObject()->methodCount(); } - propertyNames->add(name, idx); idValues[idx].priv = this; idValues[idx] = obj; } diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 0ae1809..28a808a 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -149,20 +149,19 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, } if (cache) { - QmlPropertyCache::Data *property = cache->property(name); - if (!property) return 0; - - if (flags == QScriptClass::HandlesReadAccess) { - lastData = property; - return QScriptClass::HandlesReadAccess; - } else if (property->propType > 0 && property->propType < QVariant::UserType) { - lastData = property; - return flags; - } + lastData = cache->property(name); + } else { + local = QmlPropertyCache::create(obj->metaObject(), toString(name)); + if (local.isValid()) + lastData = &local; } - // Fallback - return QmlEnginePrivate::get(engine)->queryObject(toString(name), &m_id, obj); + if (!lastData) return 0; + + QScriptClass::QueryFlags rv = QScriptClass::HandlesReadAccess; + if (lastData->flags & QmlPropertyCache::Data::IsWritable) + rv |= QScriptClass::HandlesWriteAccess; + return rv; } QScriptValue QmlObjectScriptClass::property(const Object &object, const Identifier &name) @@ -175,35 +174,31 @@ QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name if (name == m_destroyId->identifier) return m_destroy; + Q_ASSERT(lastData); + Q_ASSERT(obj); + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); - if (!obj) { - return QScriptValue(); - } else if (lastData) { + if (lastData->flags & QmlPropertyCache::Data::IsFunction) { + // ### Optimize + QScriptValue sobj = scriptEngine->newQObject(obj); + return sobj.property(toString(name)); + } else { + + QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); + if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { + enginePriv->capturedProperties << + QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex); + } - if (lastData->flags & QmlPropertyCache::Data::IsFunction) { - // ### Optimize - QScriptValue sobj = scriptEngine->newQObject(obj); - return sobj.property(toString(name)); + if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { + QObject *rv = *(QObject **)var.constData(); + return newQObject(rv); } else { - QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj); - if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) { - enginePriv->capturedProperties << - QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, - lastData->notifyIndex); - } - - if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) { - QObject *rv = *(QObject **)var.constData(); - return newQObject(rv); - } else { - return qScriptValueFromValue(scriptEngine, var); - } + return qScriptValueFromValue(scriptEngine, var); } - } else { - return QmlEnginePrivate::get(engine)->propertyObject(toString(name), obj, m_id); } } @@ -219,51 +214,16 @@ void QmlObjectScriptClass::setProperty(QObject *obj, const QScriptValue &value) { Q_UNUSED(name); - Q_UNUSED(object); + + Q_ASSERT(obj); + Q_ASSERT(lastData); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine); - if (!obj) { - return; - } else if (lastData) { - switch (lastData->propType) { - case 1: - { - bool b = value.toBoolean(); - void *a[1]; - a[0] = &b; - QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); - } - break; - - case 2: - { - int b = value.toInteger(); - void *a[1]; - a[0] = &b; - QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); - } - break; - - case 6: - { - double b = value.toNumber(); - void *a[1]; - a[0] = &b; - QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, a); - } - break; - - default: - { - QMetaProperty p = obj->metaObject()->property(lastData->coreIndex); - p.write(obj, value.toVariant()); - } - } - } else { - QmlEnginePrivate::get(engine)->setPropertyObject(value, m_id); - } + // ### Can well known types be optimized? + QVariant v = QmlScriptClass::toVariant(engine, value); + QmlMetaPropertyPrivate::write(obj, *lastData, v, enginePriv->currentExpression->context()); } QObject *QmlObjectScriptClass::toQObject(const Object &object, bool *ok) diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h index c25718c..f126192 100644 --- a/src/declarative/qml/qmlobjectscriptclass_p.h +++ b/src/declarative/qml/qmlobjectscriptclass_p.h @@ -86,6 +86,8 @@ protected: private: uint m_id; QmlPropertyCache::Data *lastData; + QmlPropertyCache::Data local; + struct Dummy {}; PersistentIdentifier *m_destroyId; QScriptValue m_destroy; diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index 7d234fd..cc4c2ab 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -54,6 +54,8 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p) if (p.isConstant()) flags |= Data::IsConstant; + if (p.isWritable()) + flags |= Data::IsWritable; if (propType == qMetaTypeId()) { flags |= Data::IsQmlBinding; @@ -100,6 +102,41 @@ QmlPropertyCache::~QmlPropertyCache() (*iter)->release(); } +QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject, + const QString &property) +{ + Q_ASSERT(metaObject); + + QmlPropertyCache::Data rv; + + int propCount = metaObject->propertyCount(); + for (int ii = propCount - 1; ii >= 0; --ii) { + QMetaProperty p = metaObject->property(ii); + QString propName = QLatin1String(p.name()); + if (propName == property) { + rv.load(p); + return rv; + } + } + + int methodCount = metaObject->methodCount(); + for (int ii = methodCount - 1; ii >= 0; --ii) { + QMetaMethod m = metaObject->method(ii); + QString methodName = QLatin1String(m.signature()); + + int parenIdx = methodName.indexOf(QLatin1Char('(')); + Q_ASSERT(parenIdx != -1); + methodName = methodName.left(parenIdx); + + if (methodName == property) { + rv.load(m); + return rv; + } + } + + return rv; +} + // ### Optimize - check engine for the parent meta object etc. QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject *metaObject) { diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index 149d2a0..82b8737 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -73,15 +73,16 @@ public: enum Flag { // Can apply to all properties, except IsFunction - IsConstant = 0x00000004, + IsConstant = 0x00000001, + IsWritable = 0x00000002, // These are mutually exclusive - IsFunction = 0x00000001, - IsQObjectDerived = 0x00000002, - IsEnumType = 0x00000008, - IsQmlList = 0x00000010, - IsQList = 0x00000020, - IsQmlBinding = 0x00000040 + IsFunction = 0x00000004, + IsQObjectDerived = 0x00000008, + IsEnumType = 0x00000010, + IsQmlList = 0x00000020, + IsQList = 0x00000040, + IsQmlBinding = 0x00000080 }; Q_DECLARE_FLAGS(Flags, Flag) @@ -105,6 +106,7 @@ public: #endif static QmlPropertyCache *create(QmlEngine *, const QMetaObject *); + static Data create(const QMetaObject *, const QString &); inline Data *property(const QScriptDeclarativeClass::Identifier &id) const; Data *property(const QString &) const; -- cgit v0.12