Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

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

    QML and Qt Quick
    2
    11
    163
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • fcarney
      fcarney last edited by

      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.

      C++ is a perfectly valid school of magic.

      1 Reply Last reply Reply Quote 0
      • fcarney
        fcarney last edited by fcarney

        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)
                                }
                            }
                        }
        

        C++ is a perfectly valid school of magic.

        1 Reply Last reply Reply Quote 1
        • GrecKo
          GrecKo Qt Champions 2018 last edited by

          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.

          fcarney 1 Reply Last reply Reply Quote 2
          • fcarney
            fcarney last edited by

            @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.

            C++ is a perfectly valid school of magic.

            1 Reply Last reply Reply Quote 0
            • fcarney
              fcarney @GrecKo last edited by

              @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.

              C++ is a perfectly valid school of magic.

              1 Reply Last reply Reply Quote 0
              • GrecKo
                GrecKo Qt Champions 2018 last edited by

                @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.

                1 Reply Last reply Reply Quote 0
                • fcarney
                  fcarney last edited by

                  @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.

                  C++ is a perfectly valid school of magic.

                  1 Reply Last reply Reply Quote 0
                  • GrecKo
                    GrecKo Qt Champions 2018 last edited by

                    ¿ʕ?
                    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
                                    }
                                }
                            }
                        }
                    }
                    
                    
                    1 Reply Last reply Reply Quote 1
                    • fcarney
                      fcarney last edited by

                      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)
                                          }
                                      }
                                  }
                      

                      C++ is a perfectly valid school of magic.

                      1 Reply Last reply Reply Quote 0
                      • GrecKo
                        GrecKo Qt Champions 2018 last edited by

                        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.

                        1 Reply Last reply Reply Quote 0
                        • fcarney
                          fcarney last edited by

                          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.

                          C++ is a perfectly valid school of magic.

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post