From 84627464eb11ca1149d46946b12e3c82eb54a8bf Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Fri, 24 May 2013 10:46:39 +0300 Subject: Fallback to QMetaObject for properties not in QQmlPropertyCache QQmlOpenMetaObject does not update the QQmlPropertyCache when new properties are added, meaning that the QQmlPropertyCache might not contain all of the dynamic properties of an object. Therefore, make QQmlPropertyCache fallback to reading the QMetaObject when a property is not found. Task-number: QTBUG-31226 Change-Id: I760aaa155b1952f6f52ab9ce173fb9547f8e34a6 Reviewed-by: Alan Alpert --- src/qml/qml/qqmlpropertycache.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/qml/qml/qqmlpropertycache.cpp') diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index b1ffc9a2d5..dee9f26c80 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -1328,8 +1328,14 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS rv.load(p); return rv; } else { - while (cmo && cmo->propertyOffset() >= idx) + bool changed = false; + while (cmo && cmo->propertyOffset() >= idx) { cmo = cmo->superClass(); + changed = true; + } + /* If the "cmo" variable didn't change, set it to 0 to + * avoid running into an infinite loop */ + if (!changed) cmo = 0; } } else { cmo = 0; @@ -1395,7 +1401,8 @@ qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, const T &name, if (cache) { rv = cache->property(name, obj, context); - } else { + } + if (!rv) { local = qQmlPropertyCacheCreate(obj->metaObject(), qQmlPropertyCacheToString(name)); if (local.isValid()) rv = &local; -- cgit v1.2.3 From 843e222b17970c211dfab82215cf41adc4547ab5 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Wed, 29 May 2013 11:29:52 +0300 Subject: QQmlPropertyCache: check methods before properties When creating the QQmlPropertyData, search within the methods list before searching for properties. The reason is that if the meta object is dynamic, looking up a property will always return a result (if the property doesn't exist, it will be created) and therefore all methods will be obscured. By swapping the search order, we eliminate this risk (methods are not dynamically added). Task-number: QTBUG-29836 Change-Id: Ie367f757c37ef4bc834a6c1c009f27bcf344fe76 Reviewed-by: Matthew Vogt Reviewed-by: Alan Alpert --- src/qml/qml/qqmlpropertycache.cpp | 46 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'src/qml/qml/qqmlpropertycache.cpp') diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index dee9f26c80..4712fbd614 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -1317,6 +1317,31 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS Q_ASSERT(metaObject); QQmlPropertyData rv; + + /* It's important to check the method list before checking for properties; + * otherwise, if the meta object is dynamic, a property will be created even + * if not found and it might obscure a method having the same name. */ + + //Used to block access to QObject::destroyed() and QObject::deleteLater() from QML + static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); + static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()"); + static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()"); + + int methodCount = metaObject->methodCount(); + for (int ii = methodCount - 1; ii >= 0; --ii) { + if (ii == destroyedIdx1 || ii == destroyedIdx2 || ii == deleteLaterIdx) + continue; + QMetaMethod m = metaObject->method(ii); + if (m.access() == QMetaMethod::Private) + continue; + QString methodName = QString::fromUtf8(m.name().constData()); + + if (methodName == property) { + rv.load(m); + return rv; + } + } + { const QMetaObject *cmo = metaObject; const QByteArray propertyName = property.toUtf8(); @@ -1342,27 +1367,6 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS } } } - - //Used to block access to QObject::destroyed() and QObject::deleteLater() from QML - static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); - static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()"); - static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()"); - - int methodCount = metaObject->methodCount(); - for (int ii = methodCount - 1; ii >= 0; --ii) { - if (ii == destroyedIdx1 || ii == destroyedIdx2 || ii == deleteLaterIdx) - continue; - QMetaMethod m = metaObject->method(ii); - if (m.access() == QMetaMethod::Private) - continue; - QString methodName = QString::fromUtf8(m.name().constData()); - - if (methodName == property) { - rv.load(m); - return rv; - } - } - return rv; } -- cgit v1.2.3