From 2171d542acd8eea32962d1b24aef67d5df75a396 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 23 Feb 2022 12:17:44 +0100 Subject: QQmlMetaType: Don't duplicate notify signals for extended types We have to add the methods first, so that the properties can be associated with their proper notification signals once we add them. If we add the properties first, the "missing" notification signals are synthesized. Fixes: QTBUG-101155 Change-Id: I1aacbf33a24f7a98d05dece77c804bd7cba8a041 Reviewed-by: Fabian Kosmale (cherry picked from commit 57614680f760068c1db39888beba46944f409ff0) Reviewed-by: Qt Cherry-pick Bot --- src/qml/qml/qqmlmetatype.cpp | 28 +++++++++++----------- .../auto/qml/qqmllanguage/data/foreignExtended.qml | 7 +++++- tests/auto/qml/qqmllanguage/testtypes.h | 14 +++++++++-- tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 11 +++++++++ 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 85fa57d8eb..610a39a992 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -253,20 +253,7 @@ void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo, } } - // Clone Q_PROPERTY - for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) { - QMetaProperty property = mo->property(ii); - - int otherIndex = ignoreEnd->indexOfProperty(property.name()); - if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) { - builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void")); - // Skip - } else { - builder.addProperty(property); - } - } - - // Clone Q_METHODS + // Clone Q_METHODS - do this first to avoid duplicating the notify signals. for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) { QMetaMethod method = mo->method(ii); @@ -290,6 +277,19 @@ void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo, m.setAccess(QMetaMethod::Private); } + // Clone Q_PROPERTY + for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) { + QMetaProperty property = mo->property(ii); + + int otherIndex = ignoreEnd->indexOfProperty(property.name()); + if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) { + builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void")); + // Skip + } else { + builder.addProperty(property); + } + } + // Clone Q_ENUMS for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) { QMetaEnum enumerator = mo->enumerator(ii); diff --git a/tests/auto/qml/qqmllanguage/data/foreignExtended.qml b/tests/auto/qml/qqmllanguage/data/foreignExtended.qml index 4863e0d567..b01af6d229 100644 --- a/tests/auto/qml/qqmllanguage/data/foreignExtended.qml +++ b/tests/auto/qml/qqmllanguage/data/foreignExtended.qml @@ -5,12 +5,17 @@ QtObject { property Foreign foreign: Foreign { objectName: "foreign" } - property Extended extended: Extended {} + property Extended extended: Extended { + objectName: "extended" + property int changeCount: 0 + onExtensionChanged: ++changeCount + } property ForeignExtended foreignExtended: ForeignExtended { objectName: "foreignExtended" } property int extendedBase: extended.base + property int extendedChangeCount: extended.changeCount property int extendedInvokable: extended.invokable() property int extendedSlot: extended.slot() diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 06554ef87a..cfc0ad6e71 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -1470,13 +1470,23 @@ public: class Extension : public QObject { Q_OBJECT - Q_PROPERTY(int extension READ extension CONSTANT) + Q_PROPERTY(int extension READ extension WRITE setExtension NOTIFY extensionChanged FINAL) public: Extension(QObject *parent = nullptr) : QObject(parent) {} - int extension() const { return 42; } + int extension() const { return ext; } + void setExtension(int e) { + if (e != ext) { + ext = e; + emit extensionChanged(); + } + } Q_INVOKABLE int invokable() { return 123; } +Q_SIGNALS: + void extensionChanged(); public slots: int slot() { return 456; } +private: + int ext = 42; }; class Extended : public QObject diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 7e30dcad6c..263b44ae22 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -5634,9 +5634,20 @@ void tst_qqmllanguage::extendedForeignTypes() QScopedPointer o(component.create()); QVERIFY(!o.isNull()); + QObject *extended = o->property("extended").value(); + QVERIFY(extended); + QSignalSpy extensionChangedSpy(extended, SIGNAL(extensionChanged())); + QCOMPARE(o->property("extendedBase").toInt(), 43); QCOMPARE(o->property("extendedExtension").toInt(), 42); QCOMPARE(o->property("foreignExtendedExtension").toInt(), 42); + + QCOMPARE(extensionChangedSpy.count(), 0); + extended->setProperty("extension", 44); + QCOMPARE(extensionChangedSpy.count(), 1); + QCOMPARE(o->property("extendedChangeCount").toInt(), 1); + QCOMPARE(o->property("extendedExtension").toInt(), 44); + QCOMPARE(o->property("foreignObjectName").toString(), QLatin1String("foreign")); QCOMPARE(o->property("foreignExtendedObjectName").toString(), QLatin1String("foreignExtended")); QCOMPARE(o->property("extendedInvokable").toInt(), 123); -- cgit v1.2.3