QMetaProperty::write should reset the property if an empty QVariant is given

[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 <jedrzej.nowacki@theqtcompany.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
Olivier Goffart 2015-10-06 10:14:26 +02:00 committed by Olivier Goffart (Woboq GmbH)
parent 54b5287adf
commit de70798859
4 changed files with 30 additions and 6 deletions

View File

@ -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 Writes \a value as the property's value to the given \a object. Returns
true if the write succeeded; otherwise returns \c false. 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() \sa read(), reset(), isWritable()
*/ */
bool QMetaProperty::write(QObject *object, const QVariant &value) const 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) if (t == QMetaType::UnknownType)
return false; return false;
} }
if (t != QMetaType::QVariant && int(t) != value.userType() && !v.convert(t)) if (t != QMetaType::QVariant && int(t) != value.userType()) {
return false; 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 // the status variable is changed by qt_metacall to indicate what it did

View File

@ -3831,7 +3831,7 @@ int QObjectPrivate::signalIndex(const char *signalName,
\b{Note:} Dynamic properties starting with "_q_" are reserved for internal \b{Note:} Dynamic properties starting with "_q_" are reserved for internal
purposes. purposes.
\sa property(), metaObject(), dynamicPropertyNames() \sa property(), metaObject(), dynamicPropertyNames(), QMetaProperty::write()
*/ */
bool QObject::setProperty(const char *name, const QVariant &value) bool QObject::setProperty(const char *name, const QVariant &value)
{ {

View File

@ -55,7 +55,7 @@ class tst_QMetaProperty : public QObject
Q_OBJECT Q_OBJECT
Q_PROPERTY(EnumType value WRITE setValue READ getValue) Q_PROPERTY(EnumType value WRITE setValue READ getValue)
Q_PROPERTY(EnumType value2 WRITE set_value READ get_value) 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 value8 READ value8)
Q_PROPERTY(int value9 READ value9 CONSTANT) Q_PROPERTY(int value9 READ value9 CONSTANT)
Q_PROPERTY(int value10 READ value10 FINAL) Q_PROPERTY(int value10 READ value10 FINAL)
@ -79,6 +79,7 @@ public:
void set_value(EnumType) {} void set_value(EnumType) {}
EnumType get_value() const { return EnumType1; } EnumType get_value() const { return EnumType1; }
void resetValue7() { value7 = QStringLiteral("reset"); }
int value8() const { return 1; } int value8() const { return 1; }
int value9() const { return 1; } int value9() const { return 1; }
int value10() const { return 1; } int value10() const { return 1; }
@ -236,6 +237,17 @@ void tst_QMetaProperty::conversion()
QVERIFY(!customP.write(this, QVariant::fromValue(this))); QVERIFY(!customP.write(this, QVariant::fromValue(this)));
QVERIFY(!value7P.write(this, QVariant::fromValue(this))); QVERIFY(!value7P.write(this, QVariant::fromValue(this)));
QVERIFY(!value7P.write(this, QVariant::fromValue<QObject*>(this))); QVERIFY(!value7P.write(this, QVariant::fromValue<QObject*>(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) QTEST_MAIN(tst_QMetaProperty)

View File

@ -1925,7 +1925,7 @@ void tst_QObject::property()
QCOMPARE(object.property("string"), QVariant("String1")); QCOMPARE(object.property("string"), QVariant("String1"));
QVERIFY(object.setProperty("string", "String2")); QVERIFY(object.setProperty("string", "String2"));
QCOMPARE(object.property("string"), QVariant("String2")); QCOMPARE(object.property("string"), QVariant("String2"));
QVERIFY(!object.setProperty("string", QVariant())); QVERIFY(object.setProperty("string", QVariant()));
const int idx = mo->indexOfProperty("variant"); const int idx = mo->indexOfProperty("variant");
QVERIFY(idx != -1); QVERIFY(idx != -1);
@ -2027,7 +2027,7 @@ void tst_QObject::property()
QCOMPARE(object.property("customString"), QVariant("String1")); QCOMPARE(object.property("customString"), QVariant("String1"));
QVERIFY(object.setProperty("customString", "String2")); QVERIFY(object.setProperty("customString", "String2"));
QCOMPARE(object.property("customString"), QVariant("String2")); QCOMPARE(object.property("customString"), QVariant("String2"));
QVERIFY(!object.setProperty("customString", QVariant())); QVERIFY(object.setProperty("customString", QVariant()));
} }
void tst_QObject::metamethod() void tst_QObject::metamethod()