QML Registered classes loses visibility upon reloading qml



  • I have a simple app.
    In homepage, i have a list of menu-items.
    When user clicks on menu-item, menu-item opens.
    User can change the options of the selected menu-item.
    Before applying the changes to the selected-menu-item-options, user needs to confirm.

    Issue :
    I have exposed some enums in my business logic.
    The enums were coming correctly for the first time when app is loaded.
    But when qml (corresponding to any menu-item) is reloaded, i am getting an undefined reference error.

    Typically i am doing the following actions in my app.

    I have registered a class(for exposing enums to QML) in main.cpp.

    Registered class MyEnums

    class MyEnums : public QObject
    {
        Q_OBJECT
        Q_ENUMS(FILE_TYPE)
    
        public:
        enum FILE_TYPE {
           QT_FILE_TYPE_REGULAR = 1,
           QT_FILE_TYPE_SOFTLINK
        };
    };
    

    main.cpp

    int main(int argc, char* argv[]) 
    {
        QApplication qapp(argc, argv);
        QDeclarativeView* view = new QDeclarativeView();
        ...
        qmlRegisterUncreatableType<MyEnums>("MyEnums", 1, 0, "MyEnums", "");
        ...
        view->setSource(QUrl::fromLocalFile("File:///Main.qml"));
        ...
        return qapp.exec();
    }
    

    Main.qml manages all the qml's.
    It has couple of functions.

    gotoHome() : to load home screen

    showPopup() : to load confirmation screen

    dismissPopup() : to dismiss confirmation screen

    When confirmation is dismissed a signal will be emitted, app can connect to this signal to perform any business logic.

    Main.qml

    import QtQuick 1.1
    Rectangle {
        id: main
        ...
        Loader {
            id: appLoader  // shows menu-items
            source: ""
            visible: true
        }
        Loader {
            id: popupLoader // to show confirmation for all apps-options
            source: ""
            visible: false
        }
        ...
        signal loadQml(string file)
        onLoadQml : {
            appLoader.source = file
            appLoader.visible = true
            popupLoader.visible = false
            appLoader.forceActiveFocus()
        }
        ...
        function gotoHome() {
             loadQml("Home.qml")
        }
        ...
        property variant activeQmlRef
        signal leftButtonClicked(variant qmlId)
        signal rightButtonClicked(variant qmlId)
    
        function showPopup(id, text) {
            activeQmlRef = id
            popupLoader.source = "Popup.qml"
            popupLoader.visible = true
            appLoader.visible = false
            popupLoader.forceActiveFocus()
        }
    
        function dismissPopup(isLeftButtonClicked) {
            popupLoader.visible = false
            appLoader.visible = true
            appLoader.forceActiveFocus()
            if (isLeftButtonClicked) {
                leftButtonClicked(activeQmlRef)
            } else {
                rightButtonClicked(activeQmlRef)
            }
        }
        ...
        Component.onCompleted: {
            ...
            gotoHome()
        }
    }
    

    Home.qml contains the menu items list

    import QtQuick 1.1
    Rectangle {
        ...
        ListModel {
            id: menuListModel
        }
        ListView {
            id: menuListView
            model: menuListModel
            ...
            delegate: MyDelegate { title: name, url: qmlSrc }
        }
        ...
        Component.onCompleted: {
            menuListModel.append({ "name" : "APP1", "qmlSrc" : "app1.qml" });
            menuListModel.append({ "name" : "APP2", "qmlSrc" : "app2.qml" });
            ...
        }
    }
    

    MyDelegate.qml

    import QtQuick 1.1
    Rectangle {
        property string name
        property string qmlSrc
        ...
        Text {
            ...
            text: name
        }
    
        MouseArea {
            anchors.fill: parent
            onClicked: {
                main.loadQml(qmlSrc)
            }
        }
    }
    

    Popup.qml

    import QtQuick 1.1
    Item {
        id: popup
        ...
        Text {
            id: title
            ...
        }
        Text {
            id: msg
            ...
        }
        Rectangle {
            id: leftButton
            ...
            MouseArea {
                ...
                onClicked : {
                    main.dismissPopup(true)
                }
            }
        }
        Rectangle {
            id: rightButton
            ...
            MouseArea {
                ...
                onClicked : {
                    main.dismissPopup(false)
                }
            }
        }
    }
    

    app1.qml Qml for menu-item1.

    Lets say this item has two options. (app1Option1 & app1Option2)

    When user clicks on any option, a confirmation-prompt appears and the changes (business-logic + ui-changes) will happen only when user clicks on confirm-button on the confirmation-prompt.

    function onConfirm() is connected to main.leftButtonClicked() signal and the changes(business-logic + ui-changes) are performed in this function.

    I am using "MyEnums" class in this function.

    For the first-time when the app is loaded, i am getting enum values correctly.

    But when the same qml is reloaded again, i am getting "undefined reference error for <b>MyEnums</b>".

    import QtQuick 1.1
    import MyEnums 1.0
    
    Rectangle {
        id: app1Options
    
        Rectangle {
            id: header
            ...
            MouseArea {
                onClicked : {
                    main.gotoHome()
                }
            }
        }
        ....
        Rectangle {
            id: app1Option1
            ...
            MouseArea {
                onClicked : {
                    main.showPopup(app1Options, "app1Option1Text");
                }
            }
        }
        Rectangle {
            id: app1Option2
            ...
        }
        ...
        // Following function is triggered: 
        // - when user clicks on "app1Option1" (popup appears)
        // - When user again clicks on "Confirm" (id:leftButton in Popup.qml)
        function onConfirm {
             ...
            /*
             * When app is loaded initially (for the first time), output : MyEnums.QT_FILE_TYPE_REGULAR [1]
             * When the screen is loaded again
             * - goback to home by clicking on header-area
             * - click APP1 on home
             * - click on "app1Option1"
             * - click on "Confirm" in popup
             * Output : undefined reference to "MyEnums"
             */
            console.log("MyEnums.QT_FILE_TYPE_REGULAR [" + MyEnums.QT_FILE_TYPE_REGULAR + "]")
            ...
        }
    
        function onCancel {
            ...
        }
    
        Component.onCompleted: {
            main.leftButtonClicked.connect(onConfirm)
            main.rightButtonClicked.connect(onCancel)
        }
    }
    

    I do not see any warnings/errors during build-time or run-time. (except for the above one)

    Could anyone suggest me what am i doing wrong here.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.