From de70798859e0363c8ca3133a4ed1a1092cfe47f5 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 6 Oct 2015 10:14:26 +0200 Subject: QMetaProperty::write should reset the property if an empty QVariant is given MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][QtCore][QMetaProperty] write() now resets the property if an empty QVariant is given, or set a default constructed object if the property is not resettable Change-Id: I9f9b57114e740f03ec4db6f223c1e8280a3d5209 Reviewed-by: Jędrzej Nowacki Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qmetaobject.cpp | 16 ++++++++++++++-- src/corelib/kernel/qobject.cpp | 2 +- .../corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp | 14 +++++++++++++- tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 4 ++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 6abec27684..820af298c0 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -3028,6 +3028,11 @@ QVariant QMetaProperty::read(const QObject *object) const Writes \a value as the property's value to the given \a object. Returns true if the write succeeded; otherwise returns \c false. + If \a value is not of the same type type as the property, a conversion + is attempted. An empty QVariant() is equivalent to a call to reset() + if this property is resetable, or setting a default-constructed object + otherwise. + \sa read(), reset(), isWritable() */ bool QMetaProperty::write(QObject *object, const QVariant &value) const @@ -3068,8 +3073,15 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const if (t == QMetaType::UnknownType) return false; } - if (t != QMetaType::QVariant && int(t) != value.userType() && !v.convert(t)) - return false; + if (t != QMetaType::QVariant && int(t) != value.userType()) { + if (!value.isValid()) { + if (isResettable()) + return reset(object); + v = QVariant(t, 0); + } else if (!v.convert(t)) { + return false; + } + } } // the status variable is changed by qt_metacall to indicate what it did diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 4bd8b4b662..c9884cd76c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3831,7 +3831,7 @@ int QObjectPrivate::signalIndex(const char *signalName, \b{Note:} Dynamic properties starting with "_q_" are reserved for internal purposes. - \sa property(), metaObject(), dynamicPropertyNames() + \sa property(), metaObject(), dynamicPropertyNames(), QMetaProperty::write() */ bool QObject::setProperty(const char *name, const QVariant &value) { diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp index 10656a0dcd..22c78f8e48 100644 --- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp +++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp @@ -55,7 +55,7 @@ class tst_QMetaProperty : public QObject Q_OBJECT Q_PROPERTY(EnumType value WRITE setValue READ getValue) Q_PROPERTY(EnumType value2 WRITE set_value READ get_value) - Q_PROPERTY(QString value7 MEMBER value7) + Q_PROPERTY(QString value7 MEMBER value7 RESET resetValue7) Q_PROPERTY(int value8 READ value8) Q_PROPERTY(int value9 READ value9 CONSTANT) Q_PROPERTY(int value10 READ value10 FINAL) @@ -79,6 +79,7 @@ public: void set_value(EnumType) {} EnumType get_value() const { return EnumType1; } + void resetValue7() { value7 = QStringLiteral("reset"); } int value8() const { return 1; } int value9() const { return 1; } int value10() const { return 1; } @@ -236,6 +237,17 @@ void tst_QMetaProperty::conversion() QVERIFY(!customP.write(this, QVariant::fromValue(this))); QVERIFY(!value7P.write(this, QVariant::fromValue(this))); QVERIFY(!value7P.write(this, QVariant::fromValue(this))); + + // none of this should have changed the values + QCOMPARE(value7, hello); + QCOMPARE(custom.str, hello); + + // Empty variant should be converted to default object + QVERIFY(customP.write(this, QVariant())); + QCOMPARE(custom.str, QString()); + // or reset resetable + QVERIFY(value7P.write(this, QVariant())); + QCOMPARE(value7, QLatin1Literal("reset")); } QTEST_MAIN(tst_QMetaProperty) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 4617ce5e74..a3c6d8e9df 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -1925,7 +1925,7 @@ void tst_QObject::property() QCOMPARE(object.property("string"), QVariant("String1")); QVERIFY(object.setProperty("string", "String2")); QCOMPARE(object.property("string"), QVariant("String2")); - QVERIFY(!object.setProperty("string", QVariant())); + QVERIFY(object.setProperty("string", QVariant())); const int idx = mo->indexOfProperty("variant"); QVERIFY(idx != -1); @@ -2027,7 +2027,7 @@ void tst_QObject::property() QCOMPARE(object.property("customString"), QVariant("String1")); QVERIFY(object.setProperty("customString", "String2")); QCOMPARE(object.property("customString"), QVariant("String2")); - QVERIFY(!object.setProperty("customString", QVariant())); + QVERIFY(object.setProperty("customString", QVariant())); } void tst_QObject::metamethod() -- cgit v1.2.3