I find myself in a pickle trying to dynamically instantiate custom QML elements from C++.
So, to layout the problem:
- I have a light-weight
Node
object data structure that is abstracted from any UI. - Because of the memory heavy
QObject
and derived, I must instantiate the UI elements on demand. - Each
Node
has a_ui*
member, and eachUI
has a_node*
member. - Each
Node
has a unique_id
, eachUI
has anID
PROPERTY
, delivered from the_node*
. The ID property is read only, since the ID is set uponNode
instantiation and should not be modifiable. - QML elements must only have constructors with default parameters, e.g. cannot pass anything to the constructor.
- When the QML element is created, the
_node*
member isNULL
, so any QML child element ofUI
trying to access the ID property cannot, because the_node*
is not set upon instantiation, it can only be set by an aux method, but since the property is effectively a read-only constant, it is not updated anymore after the instantiation when the_node*
member of theUI
is actually set.
So basically, I need to be able to set the link to the corresponding Node
of each UI
upon creation, so that it is accessible to the UI
QML elements, but I cannot pass it to a constructor, and since the property is read-only it is read only once, upon the UI
instantiation, when the _node*
UI
member is still NULL
, so the ID value cannot be accessed.
One quick and dirty solution that comes to mind is to add a NOTIFY
idChanged()
signal to emit when setting the _node*
member post-instantiation even though the ID property never really changes, cannot and should not, and add a check for the ID getter - return a fake dummy arbitrary value if _node*
is NULL
, otherwise fetch the ID value from the _node*
member. Needless to say, this is not elegant, and adds some overhead and the dummy ID value is a potential can of worms, so any ideas how to defeat the ill design of QML internals are welcome.
I just came with a solution, and a rather simple one. Considering that QtQuick is designed in a way that does not allow to specify constructor parameters and considering that the "create and set" approach has huge implications in my particular usage scenario, I decided to simply make the value available to/in the
UI
constructor even if not passed there as a parameter.So, instead of "create and set" I just do a "set and create" and use a static class member that is set before creating each item and used in the item constructor to set the data in time.
and the actual object creation:
Also, another method, which is applicable when you don't need the object set as early as in the constructor is to create the
QQmlComponent
sbeginCreate()
, set the needed properties, and finalize withcompleteCreate()