diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-04-27 15:03:17 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-05-26 11:35:45 +0200 |
commit | 1e03675dd95129702751b40ec80a999ffab7394e (patch) | |
tree | 2605e2299bf46696d7eb5334631fd7ffd5d1553e | |
parent | 6c067abca5bf539490036c5146f681e632dcf6c1 (diff) |
PropertyCache: Fix resolution of forbidden QObject methods
Despite best intentions the code still hid methods of gadgets when those
were derived from other gadgets.
Fixes: QTBUG-84447
Change-Id: I787300b2a22d6557608772d218e73b9af6f79652
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 1029b2b9f3d0ff88c0900fbfec2fac873aa6bcd4)
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 4 | ||||
-rw-r--r-- | tests/auto/qml/qqmlpropertycache/data/derivedGadgetMethod.qml | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp | 80 |
3 files changed, 90 insertions, 1 deletions
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 0e5534fc04..0911c06cd0 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -496,7 +496,9 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject, static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()"); static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()"); // These indices don't apply to gadgets, so don't block them. - const bool preventDestruction = metaObject->superClass() || metaObject == &QObject::staticMetaObject; + // It is enough to check for QObject::staticMetaObject here because the loop below excludes + // methods of parent classes: It starts at metaObject->methodOffset() + const bool preventDestruction = (metaObject == &QObject::staticMetaObject); int methodOffset = metaObject->methodOffset(); int signalOffset = signalCount - QMetaObjectPrivate::get(metaObject)->signalCount; diff --git a/tests/auto/qml/qqmlpropertycache/data/derivedGadgetMethod.qml b/tests/auto/qml/qqmlpropertycache/data/derivedGadgetMethod.qml new file mode 100644 index 0000000000..6f7f4da0d1 --- /dev/null +++ b/tests/auto/qml/qqmlpropertycache/data/derivedGadgetMethod.qml @@ -0,0 +1,7 @@ +import QtQml 2.0 +import Test.PropertyCache 1.0 + +GadgetUser { + baseString: base.stringValue() + derivedString: derived.stringValue() +} diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp index c9e92cd3c9..00151de34a 100644 --- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp +++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp @@ -55,11 +55,77 @@ private slots: void metaObjectSize(); void metaObjectChecksum(); void metaObjectsForRootElements(); + void derivedGadgetMethod(); private: QQmlEngine engine; }; +class BaseGadget +{ + Q_GADGET + QML_ANONYMOUS +public: + Q_INVOKABLE QString stringValue() { return QLatin1String("base"); } +}; + +Q_DECLARE_METATYPE(BaseGadget) + +class DerivedGadget : public BaseGadget +{ + Q_GADGET + QML_ANONYMOUS +public: + Q_INVOKABLE QString stringValue() { return QLatin1String("derived"); } +}; + +Q_DECLARE_METATYPE(DerivedGadget) + +class GadgetUser : public QObject +{ + Q_OBJECT + Q_PROPERTY(BaseGadget base READ base CONSTANT) + Q_PROPERTY(DerivedGadget derived READ derived CONSTANT) + Q_PROPERTY(QString baseString READ baseString WRITE setBaseString NOTIFY baseStringChanged) + Q_PROPERTY(QString derivedString READ derivedString WRITE setDerivedString NOTIFY derivedStringChanged) + QML_ELEMENT + +public: + BaseGadget base() const { return m_base; } + DerivedGadget derived() const { return m_derived; } + QString baseString() const { return m_baseString; } + QString derivedString() const { return m_derivedString; } + +public slots: + void setBaseString(QString baseString) + { + if (m_baseString == baseString) + return; + + m_baseString = baseString; + emit baseStringChanged(m_baseString); + } + + void setDerivedString(QString derivedString) + { + if (m_derivedString == derivedString) + return; + + m_derivedString = derivedString; + emit derivedStringChanged(m_derivedString); + } + +signals: + void baseStringChanged(QString baseString); + void derivedStringChanged(QString derivedString); + +private: + BaseGadget m_base; + DerivedGadget m_derived; + QString m_baseString; + QString m_derivedString; +}; + class BaseObject : public QObject { Q_OBJECT @@ -554,4 +620,18 @@ void tst_qqmlpropertycache::metaObjectsForRootElements() QCOMPARE(obj->property("result").toString(), QString::fromLatin1("good")); } +void tst_qqmlpropertycache::derivedGadgetMethod() +{ + qmlRegisterTypesAndRevisions<BaseGadget, DerivedGadget, GadgetUser>("Test.PropertyCache", 1); + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("derivedGadgetMethod.qml")); + QVERIFY(c.isReady()); + QScopedPointer<QObject> obj(c.create()); + QVERIFY(!obj.isNull()); + GadgetUser *gadgetUser = qobject_cast<GadgetUser *>(obj.data()); + QVERIFY(gadgetUser); + QCOMPARE(gadgetUser->baseString(), QString::fromLatin1("base")); + QCOMPARE(gadgetUser->derivedString(), QString::fromLatin1("derived")); +} + QTEST_MAIN(tst_qqmlpropertycache) |