Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Different property type for enum in 5.15/6.5
QtWS25 Last Chance

Different property type for enum in 5.15/6.5

Scheduled Pinned Locked Moved Unsolved General and Desktop
enumpropertyqvariantqt5qt6
9 Posts 4 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • crueeggC Offline
    crueeggC Offline
    crueegg
    wrote on last edited by
    #1

    If I have an enum as property, Qt6 has a different property type than Qt5.
    My serialization will fail in Qt6 because the property type is a QString and not an int anymore.
    Is this a bug or do I miss something to get the enum property as int (type 2) for all Qt versions?

    Using Q_DECLARE_METATYPE(MyQClass::MyEnum) or qRegisterMetaType<MyQClass::MyEnum>("MyQClass::MyEnum"); didn't made any difference.

    MyQClass.hpp

    #pragma once
    #include <QObject>
    
    class MyQClass : public QObject
    {
      Q_OBJECT
      Q_PROPERTY(MyEnum myEnum READ getMyEnum WRITE setMyEnum)
    public:
      explicit MyQClass(QObject *parent = nullptr) : QObject{parent} {}
    
      enum MyEnum { EnumVal0, EnumVal1, EnumVal2, EnumVal3 };
      Q_ENUM(MyEnum)
    
      void setMyEnum(MyEnum myEnum) { _myEnum = myEnum; }
      MyEnum getMyEnum() const { return _myEnum; }
    
    private:
      MyEnum _myEnum { EnumVal1 };
    };
    

    main.cpp

    #include <QCoreApplication>
    #include <QMetaProperty>
    #include <QVariant>
    #include "MyQClass.hpp"
    
    
    int main(int argc, char *argv[])
    {
      QCoreApplication a(argc, argv);
      qInfo("Qt %s", QT_VERSION_STR);
    
      MyQClass myClass;
    
      const QMetaObject *meta = myClass.metaObject();
      int id = meta->indexOfProperty("myEnum");
      QMetaProperty p = meta->property(id);
      QVariant v(p.read(&myClass));
      qInfo("MetaProperty name=%s, value=%s, typename=%s type=%d, userType=%d, isEnumType=%d",
            p.name(), qPrintable(v.toString()), p.typeName(), p.type(), p.userType(),
            p.isEnumType());
      return 0;
    }
    

    Outputs (value and type is different):

    Qt 5.15.2
    MetaProperty name=myEnum, value=1, typename=MyEnum type=2, userType=2, isEnumType=1
    
    Qt 6.5.0
    MetaProperty name=myEnum, value=EnumVal1, typename=MyQClass::MyEnum type=65536, userType=65537, isEnumType=1
    

    Qt 6.4.2 has the same output as 6.5.0.
    Qt 5.9.7 has the same output as 5.15.2

    Test.pro:

    QT = core
    CONFIG += c++17 cmdline
    HEADERS +=  MyQClass.hpp
    SOURCES += main.cpp
    
    sierdzioS 1 Reply Last reply
    0
    • crueeggC crueegg

      If I have an enum as property, Qt6 has a different property type than Qt5.
      My serialization will fail in Qt6 because the property type is a QString and not an int anymore.
      Is this a bug or do I miss something to get the enum property as int (type 2) for all Qt versions?

      Using Q_DECLARE_METATYPE(MyQClass::MyEnum) or qRegisterMetaType<MyQClass::MyEnum>("MyQClass::MyEnum"); didn't made any difference.

      MyQClass.hpp

      #pragma once
      #include <QObject>
      
      class MyQClass : public QObject
      {
        Q_OBJECT
        Q_PROPERTY(MyEnum myEnum READ getMyEnum WRITE setMyEnum)
      public:
        explicit MyQClass(QObject *parent = nullptr) : QObject{parent} {}
      
        enum MyEnum { EnumVal0, EnumVal1, EnumVal2, EnumVal3 };
        Q_ENUM(MyEnum)
      
        void setMyEnum(MyEnum myEnum) { _myEnum = myEnum; }
        MyEnum getMyEnum() const { return _myEnum; }
      
      private:
        MyEnum _myEnum { EnumVal1 };
      };
      

      main.cpp

      #include <QCoreApplication>
      #include <QMetaProperty>
      #include <QVariant>
      #include "MyQClass.hpp"
      
      
      int main(int argc, char *argv[])
      {
        QCoreApplication a(argc, argv);
        qInfo("Qt %s", QT_VERSION_STR);
      
        MyQClass myClass;
      
        const QMetaObject *meta = myClass.metaObject();
        int id = meta->indexOfProperty("myEnum");
        QMetaProperty p = meta->property(id);
        QVariant v(p.read(&myClass));
        qInfo("MetaProperty name=%s, value=%s, typename=%s type=%d, userType=%d, isEnumType=%d",
              p.name(), qPrintable(v.toString()), p.typeName(), p.type(), p.userType(),
              p.isEnumType());
        return 0;
      }
      

      Outputs (value and type is different):

      Qt 5.15.2
      MetaProperty name=myEnum, value=1, typename=MyEnum type=2, userType=2, isEnumType=1
      
      Qt 6.5.0
      MetaProperty name=myEnum, value=EnumVal1, typename=MyQClass::MyEnum type=65536, userType=65537, isEnumType=1
      

      Qt 6.4.2 has the same output as 6.5.0.
      Qt 5.9.7 has the same output as 5.15.2

      Test.pro:

      QT = core
      CONFIG += c++17 cmdline
      HEADERS +=  MyQClass.hpp
      SOURCES += main.cpp
      
      sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      I think the difference you are measuring here is in QVariant (which did see major changes between Qt5 and Qt6), not QProperty.

      Can you show your serialization code? It's hard to say anything about why it fails without the code :-)

      (Z(:^

      crueeggC 1 Reply Last reply
      0
      • sierdzioS sierdzio

        I think the difference you are measuring here is in QVariant (which did see major changes between Qt5 and Qt6), not QProperty.

        Can you show your serialization code? It's hard to say anything about why it fails without the code :-)

        crueeggC Offline
        crueeggC Offline
        crueegg
        wrote on last edited by
        #3

        @sierdzio I can fix the Serialization quite easy with a if (p.isEnumType()) out << v.toInt(); switch. What worries me more are the 100 other cases, which are difficult to detect.

        For backward compatibility it would be better to have the enums stored as an int inside the Property/QVariant.

        In Qt5.15 the debugger shows me for the v: Value=1, Type=QVariant (int).
        In Qt6.5 the debugger shows me for the v: Value=MyQClass:EnumVal1 (1), Type=QVariant (MyQClass::MyEnum).

        kshegunovK 1 Reply Last reply
        0
        • crueeggC crueegg

          @sierdzio I can fix the Serialization quite easy with a if (p.isEnumType()) out << v.toInt(); switch. What worries me more are the 100 other cases, which are difficult to detect.

          For backward compatibility it would be better to have the enums stored as an int inside the Property/QVariant.

          In Qt5.15 the debugger shows me for the v: Value=1, Type=QVariant (int).
          In Qt6.5 the debugger shows me for the v: Value=MyQClass:EnumVal1 (1), Type=QVariant (MyQClass::MyEnum).

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          @crueegg said in Different property type for enum in 5.15/6.5:

          For backward compatibility it would be better to have the enums stored as an int inside the Property/QVariant.

          That would prevent changes that are good and necessary. Since Qt5 and Qt6 are major releases, you're not guaranteed that breaking changes won't occur, especially if you rely on an implementation detail. People've waited to push such changes for ~3 years, so they don't break your 5.x -> 5.y transitions, so I think your request that the internal structure of QVariant should stay the same is unreasonable. You simply will need to adjust your code to match.

          Read and abide by the Qt Code of Conduct

          crueeggC 1 Reply Last reply
          2
          • kshegunovK kshegunov

            @crueegg said in Different property type for enum in 5.15/6.5:

            For backward compatibility it would be better to have the enums stored as an int inside the Property/QVariant.

            That would prevent changes that are good and necessary. Since Qt5 and Qt6 are major releases, you're not guaranteed that breaking changes won't occur, especially if you rely on an implementation detail. People've waited to push such changes for ~3 years, so they don't break your 5.x -> 5.y transitions, so I think your request that the internal structure of QVariant should stay the same is unreasonable. You simply will need to adjust your code to match.

            crueeggC Offline
            crueeggC Offline
            crueegg
            wrote on last edited by
            #5

            @kshegunov For a new project it's fantastic to have the enums inside the properties, but for a migration it's a nightmare (did I catch all locations?).

            I'm looking for a configuration where the enum-feature is "disabled".

            SGaistS kshegunovK 2 Replies Last reply
            0
            • crueeggC crueegg

              @kshegunov For a new project it's fantastic to have the enums inside the properties, but for a migration it's a nightmare (did I catch all locations?).

              I'm looking for a configuration where the enum-feature is "disabled".

              SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi,

              Are you using QDataStream ? If so, are you explicitly setting the version ?

              It's a good idea to do so in any case so you can easily keep backward compatibility and decide yourself when you want to migrate (and apply the migration on your terms).

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              crueeggC 1 Reply Last reply
              3
              • crueeggC crueegg

                @kshegunov For a new project it's fantastic to have the enums inside the properties, but for a migration it's a nightmare (did I catch all locations?).

                I'm looking for a configuration where the enum-feature is "disabled".

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by
                #7

                @crueegg said in Different property type for enum in 5.15/6.5:

                For a new project it's fantastic to have the enums inside the properties, but for a migration it's a nightmare (did I catch all locations?).

                I don't follow. QVariant coerces the types when necessary, so I really have no idea what the problem is here. Why do you want and expect this enum to be stored in some specific way? You'd stream out the QVariant and then when you read it, you'd get a representation that should be compatible. A call to QVariant::convert should be just about enough to change the type from int to enum or vice versa.

                Read and abide by the Qt Code of Conduct

                crueeggC 1 Reply Last reply
                0
                • SGaistS SGaist

                  Hi,

                  Are you using QDataStream ? If so, are you explicitly setting the version ?

                  It's a good idea to do so in any case so you can easily keep backward compatibility and decide yourself when you want to migrate (and apply the migration on your terms).

                  crueeggC Offline
                  crueeggC Offline
                  crueegg
                  wrote on last edited by
                  #8

                  @SGaist Yes, I'm using a QDataStream with version 4.8.

                  1 Reply Last reply
                  0
                  • kshegunovK kshegunov

                    @crueegg said in Different property type for enum in 5.15/6.5:

                    For a new project it's fantastic to have the enums inside the properties, but for a migration it's a nightmare (did I catch all locations?).

                    I don't follow. QVariant coerces the types when necessary, so I really have no idea what the problem is here. Why do you want and expect this enum to be stored in some specific way? You'd stream out the QVariant and then when you read it, you'd get a representation that should be compatible. A call to QVariant::convert should be just about enough to change the type from int to enum or vice versa.

                    crueeggC Offline
                    crueeggC Offline
                    crueegg
                    wrote on last edited by
                    #9

                    @kshegunov I have ~80 classes, each with 5-10 different properties (enums, POD, custom types, containers). The problem are all implicit (in a loop) conversions of these properties.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved