Details
-
Bug
-
Resolution: Cannot Reproduce
-
Not Evaluated
-
None
-
5.15.2
-
None
Description
When a Q_PROPERTY-declared property has a Q_ENUM-specified enum type, neither QMetaProperty::write nor QObject::setProperty can convert a QVariant of type QVariant::ULongLong or QVariant::LongLong to that type, and the write fails. By contrast, there is no issue with QVariant::Int or QVariant::UInt.
This causes interoperability problems with e.g. QJsonValue::toVariant, which uses QVariant::[U]LongLong to store integer values parsed via QJsonDocument::FromJson.
The expectation is that the property writes to enums succeed for any integer-typed QVariant, not just Int and UInt.
Full test code is attached, and also available at https://gist.github.com/JC3/81609c9527989de88355d0cec058f9e2.
Example snippet:
static void test1 (int type) { for (Example::Color c : {Example::Red, Example::Green, Example::Blue}) { Example x; QVariant v = c; v.convert(type); x.setProperty("color", v); QVariant newv = x.property("color"); qDebug() << ((newv == c)?"pass":"FAIL") << type << c << v << newv; } }
In that code, a QVariant is assigned the enum then converted to some type. The property is written and read back. The test passes if the read value equals the written value. That test will succeed for Int and UInt but fail for LongLong and ULongLong.
A run of those tests with Int, UInt, LongLong, and ULongLong, respectively, will output:
pass 2 Example::Red QVariant(int, 0) QVariant(int, 0) pass 2 Example::Green QVariant(int, 1) QVariant(int, 1) pass 2 Example::Blue QVariant(int, 2) QVariant(int, 2) pass 3 Example::Red QVariant(uint, 0) QVariant(int, 0) pass 3 Example::Green QVariant(uint, 1) QVariant(int, 1) pass 3 Example::Blue QVariant(uint, 2) QVariant(int, 2) FAIL 4 Example::Red QVariant(qlonglong, 0) QVariant(int, 3) FAIL 4 Example::Green QVariant(qlonglong, 1) QVariant(int, 3) FAIL 4 Example::Blue QVariant(qlonglong, 2) QVariant(int, 3) FAIL 5 Example::Red QVariant(qulonglong, 0) QVariant(int, 3) FAIL 5 Example::Green QVariant(qulonglong, 1) QVariant(int, 3) FAIL 5 Example::Blue QVariant(qulonglong, 2) QVariant(int, 3)
Example 2:
QString jsonstr = "{\"color\":2}"; QJsonObject json = QJsonDocument::fromJson(jsonstr.toLatin1()).object(); Example x; // this will fail, type is ULongLong QVariant v = json["color"].toVariant(); x.setProperty("color", v); qDebug() << v << x.property("color"); // this will succeed, type is UInt v.convert(QVariant::UInt); x.setProperty("color", v); qDebug() << v << x.property("color");
That code demonstrates a more realistic scenario. There, JSON is parsed and an attempt is made to store a value in a property. The attempt will fail because the value is a ULongLong. The attempt will succeed if the value is converted to a UInt first, outputting:
QVariant(qlonglong, 2) QVariant(Example::Color, "None") QVariant(uint, 2) QVariant(Example::Color, "Blue")