Handling different objects in Repeater



  • Sorry for the vague title, couldn't find a way to describe my problem.

    I'm trying to find out if I should migrate my Data logger program from QWidgets to QML. I'm new to QML but already like how it works and the fact that (at least for me), it is easier to get a clear front end and back end separation. Also that it is easier to make a more user friendly UI design.

    To decide wether or not I should migrate to QML I'm looking into how to solve small problems, I know I will need to implement my data logger program.

    In my program I have a lot of different types of loggers. All have their own class in c++, but all inherits from the same base class, so they all share some simple functions (like get logged data). However, all of the loggers will have different properties as well they don't share. My goal is to make it possible for the user to add the logger types he needs (there can be duplicates), display the settings for each logger in the UI so he can alter the settings.

    I've succesfully implemented a QAbstractListModel in c++ and connected it to QML so I can access the items in the model through a repeater. I can also add new loggers to the list. And this approach works well as long as all loggers in the list are of the same type. Then i can draw out labels and text fields, comboboxes etc, and change the properties of the individual items. All is great.

    However, in my setup I will need the list of loggers to contain all kinds of different loggers, and I would like the Repeater to draw out different layouts depending on which type of logger the item is. I guess I can already hear by the name, that Repeater may not be the solution i need.

    My attempts at resolving this is:

    • Create a list model for each type of logger, and the use a repeater on each list. But I need the to loop through all loggers when the program is running to log data from each logger, which is tedious if I have multiple list of different kinds of loggers. Also I don't think this solution is very scalable
    • I also tried putting a logger_type attribute in the base class, then in the repeater checking which type it was (using a Loader), and then trying to create a layout depending on the type. However, I could not find a way to do this, where I had access to setter and getters of the items. That is I could print out a square of differnt color depending on the logger_type, but I could not make meaningfull text fields, with the abillity to display and change settings.

    I think that I may need some ideas on how to approach this, because I think I may be going in a completely wrong direction.

    Hope someone can help me in the right direction



  • States and Transitions sounds pretty good. You can have your QML delegate enter different states based on stuff (variable value, expression, whatever etc)?

    But that's just what immediately comes to mind... I know I myself don't fully utilize them like I could/should.

    The times I have though I've come back and seen it a couple times now and thought "that's so good, don't have to really do anything at all" :-)

    You probably are more suited to tell, a simple example is at:
    https://qmlbook.github.io/en/ch05/index.html#states-and-transitions

    reference stuff:
    http://doc.qt.io/qt-5/qml-qtquick-item.html#states-prop
    http://doc.qt.io/qt-5/qtquick-statesanimations-animations.html



  • Thanks for your suggestion. I couldn't get it working exactly as I wanted, however, it let me to other posts where I eventually found a solution. Se working code below.

    The important line was

    property QtObject obj: model.item
    

    It makes this variable available to the loaded components. It turns out that this is well described in the documentation of QML (Using loader within a view delegate). Easy enough to find, when you know it exist :-).

    import QtQuick 2.6
    import QtQuick.Window 2.2
    import ObjectTypes 1.0
    import QtQuick.Controls 1.5
    
    Window {
        id: window
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Column
        {
            Repeater {
                model: msg
                delegate: Component {
                    id: delegate
                    Loader {
                        property QtObject obj: model.item
                        sourceComponent: {
                            if(model.item.type === "A")
                                return obj_a
    
                            if(model.item.type === "B")
                                return obj_b
    
                            return obj_default
                        }
                    }
                }
            }
        }
    
        Component {
            id: obj_a
            Rectangle {
                width: 200
                height: 60
                color: "green"
                Text {
                    id: text2
                    text: obj.type
                }
                TextField {
                    anchors.top: text2.bottom
                    text: obj.type
                    onEditingFinished: obj.type = text
                }
            }
        }
    
        Component {
            id: obj_b
            Rectangle {
                width: 200
                height: 90
                color: "red"
                Text {
                    id: text2
                    text: obj.type
                }
                TextField {
                    id: text3
                    anchors.top: text2.bottom
                    text: obj.type
                    onEditingFinished: obj.type = text
                }
                TextField {
                    anchors.top: text3.bottom
                    text: "Test"
                }
            }
        }
    
        Component {
            id: obj_default
            Rectangle {
                width: 200
                height: 60
                color: "blue"
                Text {
                    id: text2
                    text: obj.type
                }
                TextField {
                    anchors.top: text2.bottom
                    text: obj.type
                    onEditingFinished: obj.type = text
                }
            }
        }
    }
    
    

Log in to reply
 

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