aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-04-27 15:03:17 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-05-26 11:35:45 +0200
commit1e03675dd95129702751b40ec80a999ffab7394e (patch)
tree2605e2299bf46696d7eb5334631fd7ffd5d1553e
parent6c067abca5bf539490036c5146f681e632dcf6c1 (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.cpp4
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/derivedGadgetMethod.qml7
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp80
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)