Child's property not constructed when the parent is being constructed

Hi all,

I’m having trouble with a widget that’s set up using a composite template (.ui file), in particular getting a property of that child. (In particular, using the rust bindings for gtk4.) When the parent tries to access that property in its constructor, I get back a

property 'model' of type 'ConstraintView' not found

even though the constructed of the child is supposed to set up the model field.

The relevant parts of the child structure are as follows

#[derive(Debug, Default, Properties)]
#[properties(wrapper_type = super::ConstraintView)]
pub struct ConstraintView {
  #[property(get)]
  model : OnceCell<FlattenListModel>,
  drag_widget : RefCell<Option<Widget>>,
}

impl ObjectImpl for ConstraintView {
  fn constructed(&self) {
    // ...
    self.model.set(FlattenListModel::new(Some(list)))
      .expect("model exists, but should not be!");
    // ...
    self.parent_constructed();
  }

and the relevant parts of the parent structure are

#[derive(Debug, Default, Properties, CompositeTemplate)]
#[properties(wrapper_type = super::ConstraintEditorWindow)]
#[template(resource = "/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui")]
pub struct ConstraintEditorWindow {
  // ...
  #[template_child]
  pub view : TemplateChild<ConstraintView>,
  // ...
}

impl ObjectImpl for ConstraintEditorWindow {
  fn constructed(&self) {
    // crashes here
    let model = self.view.model();
    // ...
  }
}

This is a reimplementation of the gtk/demos/constraint-editor application, so the .ui files can be found there. In particular constraint-editor-window.ui.

I might be misunderstanding what constructed is supposed to do / when it runs. My intention and understanding was that it fulfills the role of the _init functions, that is, sets up all the objects in the struct whenever the object is initialised. (See, for comparison, the function constraint_view_init in the constraint-view.c file).

I worked it out. The issue is that I made model a property, in order to be able to access it from other objects. However, I guess that properties have to be initialised in the template. And so I speculate that, as the template does not initialise model, that overwrote the constructor. Removing the property annotation, and making a custom getter, resolves the issue.