QML - best way to implement C++ ListModel

5.7k Views Asked by At

Currently i have a ListModel defined in QML with many different Fields in each ListElement. The delegate react in different ways based on the "myType" value.

ListView {
        id: createLocalGameViewList
        anchors.fill: parent
        model: ListModel {
            id: createLocalGameViewModel
            ListElement {
                myId: "comboBox_NumberOfPlayers"
                myTitle: qsTr("Number of players")
                myType: "ComboBox"
                myValuesList: [
                    ListElement { value: "10" },
                    ListElement { value: "9" },
                    ListElement { value: "8" },
                    ListElement { value: "7" },
                    ListElement { value: "6" },
                    ListElement { value: "5" },
                    ListElement { value: "4" },
                    ListElement { value: "3" },
                    ListElement { value: "2" }
                ]
                myValueIsIndex: false
                myValue: ""
            }
            ListElement {
                myId: "spinBox_StartCash"
                myTitle: qsTr("Start cash")
                myType: "SpinBox"
                myMaxValue: "1000000"
                myMinValue: "1000"
                myPrefix: "$"
                myValue: ""
            }
            ListElement {
                myId: "spinBox_StartBlind"
                myTitle: qsTr("Start blind")
                myType: "SpinBox"
                myMaxValue: "20000"
                myMinValue: "5"
                myPrefix: "$"
                myValue: ""
            }                
            ListElement {
                myId: "selector_BlindsRaiseInterval"
                myTitle: qsTr("Blinds raise interval")
                myType: "BlindsRaiseInterval"
                myRaiseOnHandsType: "" //if false it is raise on minutes type
                myRaiseOnHandsInterval: ""
                myRaiseOnMinutesInterval: ""
            }
            ListElement {
                myId: "selector_BlindsRaiseMode"
                myTitle: qsTr("Blinds raise mode")
                myType: "BlindsRaiseMode"
                myAlwaysDoubleBlinds: "" //if false it is "Manual Blinds Order"
                myManualBlindsList: []
                myAfterMBAlwaysDoubleBlinds: ""
                myAfterMBAlwaysRaiseAbout: ""
                myAfterMBAlwaysRaiseValue: ""
                myAfterMBStayAtLastBlind: ""
            }
            ListElement {
                myId: "comboBox_GameSpeed"
                myTitle: qsTr("Game speed")
                myType: "ComboBox"
                myValuesList: [
                    ListElement { value: "11" },
                    ListElement { value: "10" },
                    ListElement { value: "9" },
                    ListElement { value: "8" },
                    ListElement { value: "7" },
                    ListElement { value: "6" },
                    ListElement { value: "5" },
                    ListElement { value: "4" },
                    ListElement { value: "3" },
                    ListElement { value: "2" },
                    ListElement { value: "1" }
                ]
                myValue: ""
                myValueIsIndex: false
            }

When the ListView Component is completed i read some config values from a C++ class called "Config".

            Component.onCompleted: {
                //set Config Values from config file
                createLocalGameViewModel.setProperty(0, "myValue", Config.readConfigIntString("NumberOfPlayers"));
                createLocalGameViewModel.setProperty(1, "myValue", Config.readConfigIntString("StartCash"));
                createLocalGameViewModel.setProperty(2, "myValue", Config.readConfigIntString("FirstSmallBlind"));
                createLocalGameViewModel.setProperty(3, "myRaiseOnHandsType", Config.readConfigIntString("RaiseBlindsAtHands"));
                createLocalGameViewModel.setProperty(3, "myRaiseOnHandsInterval", Config.readConfigIntString("RaiseSmallBlindEveryHands"));
                createLocalGameViewModel.setProperty(3, "myRaiseOnMinutesInterval", Config.readConfigIntString("RaiseSmallBlindEveryMinutes"));
                createLocalGameViewModel.setProperty(4, "myAlwaysDoubleBlinds", Config.readConfigIntString("AlwaysDoubleBlinds"));

                var tempList = Config.readConfigIntStringList("ManualBlindsList");
                for(var i=0; i < tempList.length; i++) {
                    createLocalGameViewModel.get(4).myManualBlindsList.append({"blindValue": tempList[i].toString()})
                }

                createLocalGameViewModel.setProperty(4, "myAfterMBAlwaysDoubleBlinds", Config.readConfigIntString("AfterMBAlwaysDoubleBlinds"));
                createLocalGameViewModel.setProperty(4, "myAfterMBAlwaysRaiseAbout", Config.readConfigIntString("AfterMBAlwaysRaiseAbout"));
                createLocalGameViewModel.setProperty(4, "myAfterMBAlwaysRaiseValue", Config.readConfigIntString("AfterMBAlwaysRaiseValue"));
                createLocalGameViewModel.setProperty(4, "myAfterMBStayAtLastBlind", Config.readConfigIntString("AfterMBStayAtLastBlind"));
                createLocalGameViewModel.setProperty(5, "myValue", Config.readConfigIntString("GameSpeed"));
            }

When the listView is finished i need to pass the edited data to C++. So i realized it is not the best way to build the Model in QML. So i'am plan to create the model in C++ but i never did this before. So my question is: Which kind of model structure would be the best for this usecase, but is not too complex to setup?

Or is there another not too ugly way to put the data from the QML model to c++ context?

2

There are 2 best solutions below

2
On

Seems like a using a QQmlListProperty as described in http://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html#properties-with-object-list-types would be a good fit for your model.

And if you happen to still be on Qt 4.8, a QList of your own QObject-derived class would probably work too. More information about this could be found in: http://doc.qt.io/qt-4.8/qdeclarativemodels.html#c-data-models.

1
On

A good way to create powerful data models in Qt is to use QAbstractItemModel (http://doc.qt.io/qt-5/qabstractitemmodel.html) I'm creating a Qt/QML addons lib you can base on : https://github.com/ThomArmax/QtArmax

See https://github.com/ThomArmax/QtArmax/tree/develop/src/core/datamodels for more implementation informations