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) } } }
-
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 atDelegateChooser
?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.
-
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 atDelegateChooser
?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.:
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.
-
@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.
-
¿ʕ?
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) } } }
-
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 doroot.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.