Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-108188

Meta property writes fail to convert [u]longlong to enum

    XMLWordPrintable

Details

    • Bug
    • Resolution: Cannot Reproduce
    • Not Evaluated
    • None
    • 5.15.2
    • Core: Object Model
    • 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")

       

      Attachments

        1. main.cpp
          2 kB
        2. main.h
          0.3 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            thiago Thiago Macieira
            jasonc Jason Cipriani
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes