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

So close, yet so far. Why index in instatiators should be available outside the delegate.



  • Not sure if this is even feasible with instantiators. I will most likely have to create my own object to do this, somehow. Shouldn't be that hard, I hope.

                    Instantiator {
                        id: instantiator
    
                        property var obj_list: []
                        property var comp_list: []
    
                        delegate: instantiator.comp_list[index]
    
                        onObjectAdded: comp_list.splice(index,0,object.type)
                        onObjectRemoved: comp_list.splice(index,1)
    
                        Component.onCompleted: {
                            obj_list.push({type: connectors.opcuaconnector})
                            obj_list.push({type: StandardPoint, dataSource: "opcua://default:1/Modules/Power Supply Module/Parameters/Current"})
                        }
                    }
    

    The idea is that the instantiator can get the delegate type by index. However, index is only available inside the created delegate component. But if I use say an Item to do this then the properties from the object are not applied to the correct object.

    I don't think there is a solution here other than writing a custom object to manage instances. Which is fine. I am just lamenting how close I got with Instantiators.



  • It wasn't that hard:

                   ListModel {
                        id: obj_list
    
                        dynamicRoles: false
    
                        Component.onCompleted: {
                            obj_list.insert(obj_list.count, {comptype: connectors.opcuaconnector, config: {}})
                            obj_list.insert(obj_list.count, {comptype: standardPoint_comp, config: {dataSource: "opcua://default:1/Modules/Power Supply Module/Parameters/Current"}})
                        }
                    }
    
                    Component {
                        id: standardPoint_comp
    
                        StandardPoint {
                        }
                    }
    
                    Item {
                        id: customInstantiator
    
                        property var model: obj_list
                        property var inst_list: []
    
                        function insertRow(row, object){
                            var obj = object.comptype.createObject(parent, object.config)
                            inst_list.slice(row, 0, obj)
                        }
    
                        function removeRow(row){
                            var obj = inst_list[row]
                            inst_list.slice(row, 1)
                            obj.destroy()
                        }
    
                        Connections {
                            target: obj_list
    
                            function onRowsInserted(parent, first, last) {
                                customInstantiator.insertRow(first, obj_list.get(first))
                            }
                            function onRowsRemoved(parent, first, last) {
                                customInstantiator.removeRow(first)
                            }
                        }
                    }
    

  • Qt Champions 2018

    Why not just use a Loader as a component, you could assign it a sourceComponent according to the index.

    Also why do you have such an heterogeneous list?
    Have you looked at DelegateChooser?

    Can you describe us what's your higher level goal is? I have a bad feeling about your current solution.



  • @GrecKo said in So close, yet so far. Why index in instatiators should be available outside the delegate.:

    what's your higher level goal is?

    I am working on a data driven display. I basically want to keep a list of objects that I can stored as a json string or in a Settings parameter. I intend to build a drag and drop display app that is configurable by the user.

    No, I had not see DelegateChooser. I will look into that. The problem with a loader is that I could not specify the configured properties for each object. With createObject you provide the properties for each instance.

    I finally built something that can be loaded by a Repeater, but provide properties for each object. I plan on generating two types of main objects: RuntimeObject and EditorObject. Both will take the same data. But EditorObject will be able to be dragged around and adjusting size. RuntimeObject will allow some interaction, but no editing. The base object for RuntimeObject is InstanceObject that handles the lifetime of the object. the EditorObject will most likely be based on RuntimeObject so it can do everything it does, plus add editing features.

    The InstanceObject will be what is created by the definition of the object by the properties object.



  • @GrecKo said in So close, yet so far. Why index in instatiators should be available outside the delegate.:

    Have you looked at DelegateChooser?

    I think this could work if there was a simple way to set the properties in a javascript object when the delegate is built. I need to push the properties of an js object into the created object. I have written a util function to setProperty/getProperty of any QObject programmatically. This will aid in saving objects after editing. I can parse a list of of properties and save only those properties.

    It amazes me all the qml objects there are that I don't know about. I am always finding new ones that solve specific problems.


  • Qt Champions 2018

    @fcarney said in So close, yet so far. Why index in instatiators should be available outside the delegate.:

    I think this could work if there was a simple way to set the properties in a javascript object when the delegate is built.

    Why?
    The delegate can access the data of your model.

    It can be done with a Loader too.

    I've created something similar to you I believe, a UI editor in QML, with different types possible and forwarded the data to the correct delegate.

    You are doing too much in imperative javascript. Stay declarative.



  • @GrecKo said in So close, yet so far. Why index in instatiators should be available outside the delegate.:

    You are doing too much in imperative javascript.

    But I need imperative to set the properties on the object. Either I do it in createObject or do it inside the delegate. Right now createObject is cleaner.


  • Qt Champions 2018

    ¿ʕ?
    By doing it your way, the delegates are not bound to the model data.

    There's multiple ways to do it declaratively, here's one:

    import QtQuick 2.15
    import QtQuick.Window 2.15
    import QtQuick.Controls 2.15
    import Qt.labs.qmlmodels 1.0
    
    Window {
        id: root
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        property var elementsModel: [
            {
                type: "circle",
                x: 10,
                y: 10,
                width: 20,
                height: 20,
                properties: {
                    color: "blue"
                }
            },
            {
                type: "button",
                x: 50,
                y: 30,
                width: 200,
                height: 20,
                properties: {
                    text: "push"
                }
            }
        ]
        Repeater {
            model: root.elementsModel
            delegate: DelegateChooser {
                role: "type"
                DelegateChoice {
                    roleValue: "circle"
                    Rectangle {
                        x: modelData.x
                        y: modelData.y
                        width: modelData.width
                        height: modelData.height
                        color: modelData.properties.color
                        radius: width / 2
                    }
                }
                DelegateChoice {
                    roleValue: "button"
                    Button {
                        x: modelData.x
                        y: modelData.y
                        width: modelData.width
                        height: modelData.height
                        text: modelData.properties.text
                    }
                }
            }
        }
    }
    
    


  • I am struggling to modify the model. Either it won't change, or it does, but it is not notifying of the changes. I tweaked your example to show you what I mean:

                DelegateChoice {
                    roleValue: "button"
                    Button {
                        x: modelData.x
                        y: modelData.y
                        width: modelData.width
                        height: modelData.height
                        text: modelData.properties.text
    
                        onClicked: {
                            console.log(modelData.properties.text)
                            modelData.properties.text = "push again"
                            console.log(modelData.properties.text)
    
                            console.log(elementsModel[index].properties.text)
                            elementsModel[index].properties.text = "please push"
                            console.log(elementsModel[index].properties.text)
                        }
                    }
                }
    

  • Qt Champions 2018

    That's because it's a plain JS array as a model, it doesn't know it has changed. Use a proper model to do that, or as a workaround call root.elementsModelChanged() or do root.elementsModel = root.elementsModel.



  • Yeah, I think I need a list model of json objects. I will store qvariants, but assume they are json objects. I can handle data change by the normal list signals for insert, change, etc. Part of my issue was trying to do the data heavy lifting is js when I should have been using c++.

    Thanks for your insight @GrecKo! I learned quite a bit from you.


Log in to reply