Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Cannot compare C++ enum in QML



  • Hi,

    I have exported a C++ enum to QML and it seems to be recognized correctly in QML. When I use the enum as a property type in another class then the property isn't compared correctly with the enum value and comparison returns false. I have added a small example below.

    Class with enum

    #ifndef TYPES_H
    #define TYPES_H
    
    #include <QObject>
    
    class SystemStateClass
    {
        Q_GADGET
    public:
        enum SystemStateEnum {
            Idle = 0,
            MainView,
        };
        Q_ENUM(SystemStateEnum)
    private:
        explicit SystemStateClass() {}
    };
    
    using SystemState = SystemStateClass::SystemStateEnum;
    
    #endif // TYPES_H
    

    Class with enum property

    #ifndef CTRL_H
    #define CTRL_H
    
    #include <QObject>
    #include "Types.h"
    
    class Ctrl : public QObject
    {
         Q_OBJECT
    public:
    
        Ctrl() {};
        ~Ctrl() = default;
        Q_PROPERTY(SystemState state READ state NOTIFY stateChanged)
        SystemState state() { return m_state; }
    
    signals:
        void stateChanged(SystemState);
    
    private:
        SystemState m_state = SystemState::MainView;
    };
    
    #endif // CTRL_H
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "Ctrl.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
    
        qRegisterMetaType<SystemState>("SystemState");
        engine.rootContext()->setContextProperty("ctrl", new Ctrl());
        qmlRegisterUncreatableType<SystemStateClass>("App.Types", 1, 0, "SystemState", "Not creatable as it is an enum type");
    
        engine.load("qrc:/main.qml");
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.14
    import QtQuick.Window 2.14
    import App.Types 1.0
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Test enum")
    
        Component.onCompleted: {
            console.log("ctrl.state:", ctrl.state)
            console.log("Enum value:", SystemState.MainView)
            console.log("Equals enum val:", (ctrl.state === SystemState.MainView))
            console.log("Equals int:", (ctrl.state === 1))
        }
    }
    
    

    Output

    qml: ctrl.state: MainView
    qml: Enum value: 1
    qml: Equals enum val: false
    qml: Equals int: false
    


  • I solved it. The type used in the Q_PROPERTY must be stated explicitly as SystemStateClass::SystemStateEnum instead of using using-declaration (or typedef) SystemState.

    Q_PROPERTY(SystemStateClass::SystemStateEnum state READ state NOTIFY stateChanged)
    

    This will allow QML to interpret the enum as int and the output will be:

    qml: ctrl.state: 1
    qml: Enum value: 1
    qml: Equals enum val: true
    qml: Equals int: true
    

    The using-declaration SystemState can be used in all other parts of C++ code except in Q_PROPERTY.


Log in to reply