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

Understanding QML, C++, and Enumerations



  • I have a test project at state_binding_test

    In main.cpp, I have:

    int main(int argc, char *argv[])
        {
            QCoreApplication::setAttribute( Qt::AA_EnableHighDpiScaling );
        
            QGuiApplication app( argc, argv );
        
            qmlRegisterSingletonType<StateMachine>( "com.company.statemachine", 1, 0, "StateMachine", &StateMachine::qmlSingletonInstance );
        
            qmlRegisterUncreatableType<Support>( "com.company.statemachine.support", 1, 0, "Support", QStringLiteral( "Support should not be created in QML" ) );
            qRegisterMetaType<Support::ETestB>( "Support.ETestB" );
           
            QQmlApplicationEngine engine;
            const QUrl url(QStringLiteral("qrc:/main.qml"));
            QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                             &app, [url](QObject *obj, const QUrl &objUrl) {
                if (!obj && url == objUrl)
                    QCoreApplication::exit(-1);
            }, Qt::QueuedConnection);
            engine.load(url);
        
            return app.exec();
        }
    

    In support.h, I have

    enum class ETestB
        {
          Ddddd,
          Eeeee,
          Fffff
        };
        Q_ENUM( ETestB );
    

    In main.qml, I have:

        Label {
            id: label
    
            x: 54
    
            width: 502
            height: 33
    
            text: {
    
              console.log( "Aaaaa: ", StateMachine.Aaaaa );
              console.log( "Aaaaa: ", StateMachine.Bbbbb );
              console.log( "Aaaaa: ", StateMachine.Ccccc );
    
              console.log( "Ddddd: ", Support.Ddddd );
              console.log( "Eeeee: ", Support.Eeeee );
              console.log( "Fffff: ", Support.Fffff );
    
              return StateMachine.support.title;
            }
    
            anchors.top: parent.top
    
            font.bold: true
            font.pointSize: 24
    
            anchors.topMargin: 49
            anchors.horizontalCenter: parent.horizontalCenter
        }
    

    When I run the app, I see in the output:

    qml: Ddddd:  0
    qml: Eeeee:  1
    qml: Fffff:  2
    

    which is what is expected. However, I still have a few questions:

    1. Does or should qmlRegisterUncreatableType and qRegisterMetaType need to go in main.cpp and be executed after QGuiApplication app? Or is considered best practice, etc.?

    2. console.log( "Ddddd: ", Support.Ddddd ); works, but I lose the explicit connection to the ETestB datatype. I would prefer to be able to write Support.ETestB.Ddddd or something. Is that possible now or something that might be implemented in a future version?

    3. If I remove qRegisterMetaType, current behavior remains the same. I am not sure what, exactly, qRegisterMetaType is doing for me here. Can someone provide some insight...?

    4. Let's say that I add:

        enum class ETestC
        {
          Ggggg,
          Ddddd,
          Eeeee,
          Fffff
        };
        Q_ENUM( ETestC );
    

    to the Support class. And qRegisterMetaType<Support::ETestC>( "Support.ETestC" ); to the main function. There is now a namespace collision between ETestC and ETestB. According to some documentation, it seems like I should add Q_CLASSINFO( "RegisterEnumClassesUnscoped", "false" ) to the Support class. However, when I do all of that, I see:

    qml: Ddddd:  undefined
    qml: Eeeee:  undefined
    qml: Fffff:  undefined
    

    in the output. Clearly there is something I did not understand from the documentation.

    I look forward to hearing from anyone who cares to comment so I can understand this system better.


  • Moderators

    @james_h_3010 said in Understanding QML, C++, and Enumerations:

    1. Does or should qmlRegisterUncreatableType and qRegisterMetaType need to go in main.cpp and be executed after QGuiApplication app? Or is considered best practice, etc.?

    It does not need to be in main.cpp. It does need to be executed after QGuiApplication.

    What you wrote is how most people do it. Is it best practice? Well, for big projects I'd say it's good to move that stuff to some other header, just to keep main.cpp cleaner. But it does not matter much, it's only styling "issue". You won't gain or loose performance here.

    1. console.log( "Ddddd: ", Support.Ddddd ); works, but I lose the explicit connection to the ETestB datatype. I would prefer to be able to write Support.ETestB.Ddddd or something. Is that possible now or something that might be implemented in a future version?

    I don't think it's supported and I have not heard of plans to support it. Maybe it will come, though, who knows.

    1. If I remove qRegisterMetaType, current behavior remains the same. I am not sure what, exactly, qRegisterMetaType is doing for me here. Can someone provide some insight...?

    Q_ENUM has already registered it with meta object system. You don't need to do it manually.

    1. Let's say that I add:
        enum class ETestC
        {
          Ggggg,
          Ddddd,
          Eeeee,
          Fffff
        };
        Q_ENUM( ETestC );
    

    to the Support class. And qRegisterMetaType<Support::ETestC>( "Support.ETestC" ); to the main function. There is now a namespace collision between ETestC and ETestB. According to some documentation, it seems like I should add Q_CLASSINFO( "RegisterEnumClassesUnscoped", "false" ) to the Support class. However, when I do all of that, I see:

    qml: Ddddd:  undefined
    qml: Eeeee:  undefined
    qml: Fffff:  undefined
    

    in the output. Clearly there is something I did not understand from the documentation.

    I look forward to hearing from anyone who cares to comment so I can understand this system better.

    I think they would clash, yes. QML engine is very stupid when it comes to understanding enums.