diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-01-07 11:51:37 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2015-01-07 15:34:19 +0100 |
commit | 05fd01c14a7a4b26f366704fb0b0a4eddaceccf4 (patch) | |
tree | 583f404187502c83721db32e901bb8ed108ab51d /src | |
parent | 353e43cb6d73ee97ebff1a8c737b2c133b135ab8 (diff) |
Fix property access and method invocation on value types that use inheritance
For gadgets/value types we use moc's static_metacall, which doesn't call the
parent class implementation. Therefore before placing a static metacall we
must resolve the indicies and find the right meta-object.
Change-Id: I258e3d9ecfc704498c68772dc42b16134a3bfd83
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 40 | ||||
-rw-r--r-- | src/qml/qml/qqmlpropertycache_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 10 |
4 files changed, 52 insertions, 6 deletions
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index b5bc29aaa6..182e6a7814 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -1510,6 +1510,39 @@ bool QQmlMetaObject::canConvert(const QQmlMetaObject &from, const QQmlMetaObject return false; } +void QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index) +{ + int offset; + + switch (type) { + case QMetaObject::ReadProperty: + case QMetaObject::WriteProperty: + case QMetaObject::ResetProperty: + case QMetaObject::QueryPropertyDesignable: + case QMetaObject::QueryPropertyEditable: + case QMetaObject::QueryPropertyScriptable: + case QMetaObject::QueryPropertyStored: + case QMetaObject::QueryPropertyUser: + offset = (*metaObject)->propertyOffset(); + while (*index < offset) { + *metaObject = (*metaObject)->superClass(); + offset = (*metaObject)->propertyOffset(); + } + break; + case QMetaObject::InvokeMetaMethod: + offset = (*metaObject)->methodOffset(); + while (*index < offset) { + *metaObject = (*metaObject)->superClass(); + offset = (*metaObject)->methodOffset(); + } + break; + default: + Q_UNIMPLEMENTED(); + } + + *index -= offset; +} + QQmlPropertyCache *QQmlMetaObject::propertyCache(QQmlEnginePrivate *e) const { if (_m.isNull()) return 0; @@ -1652,8 +1685,11 @@ void QQmlObjectOrGadget::metacall(QMetaObject::Call type, int index, void **argv { if (ptr.isT1()) QMetaObject::metacall(ptr.asT1(), type, index, argv); - else - _m.asT1()->metaObject()->d.static_metacall(reinterpret_cast<QObject*>(ptr.asT2()), type, index, argv); + else { + const QMetaObject *metaObject = _m.asT1()->metaObject(); + QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &index); + metaObject->d.static_metacall(reinterpret_cast<QObject*>(ptr.asT2()), type, index, argv); + } } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 77bbd3dc14..033ff1de31 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -432,6 +432,10 @@ public: static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to); + // static_metacall (on Gadgets) doesn't call the base implementation and therefore + // we need a helper to find the correct meta object and property/method index. + static void resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index); + protected: QBiPointer<QQmlPropertyCache, const QMetaObject> _m; }; diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index e901a9c0d7..7f0e3a3a61 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -231,7 +231,9 @@ void QQmlValueType::objectDestroyed(QObject *) int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **argv) { - d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), type, _id, argv); + const QMetaObject *mo = _metaObject; + QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &mo, &_id); + mo->d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), type, _id, argv); return _id; } diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index 332cfefde9..85a391fd98 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -307,11 +307,15 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope if (result->propType == metatype) { \ cpptype v; \ void *args[] = { &v, 0 }; \ - metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, result->coreIndex, args); \ + metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); \ return QV4::Encode(constructor(v)); \ } const QMetaObject *metaObject = r->d()->propertyCache->metaObject(); + + int index = result->coreIndex; + QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index); + void *gadget = r->d()->gadget(); // These four types are the most common used by the value type wrappers @@ -322,9 +326,9 @@ ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasPrope QVariant v(result->propType, (void *)0); void *args[] = { v.data(), 0 }; - metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, result->coreIndex, args); + metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); return QV8Engine::fromVariant(v4, v); -#undef VALUE_TYPE_ACCESSOR +#undef VALUE_TYPE_LOAD } void QQmlValueTypeWrapper::put(Managed *m, String *name, const ValueRef value) |