XML template basics

I’ve spent about 1.5hrs trying to do the most simple of things…

Here is my window.ui file…

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk" version="4.0"/>
  <template class="MyWindow" parent="GtkApplicationWindow">
    <child type="titlebar">
      <object class="GtkHeaderBar"></object>
    </child>
  </template>
</interface>

How do I put the header bar in it’s own file called header.ui?

I’ve tried pretty well everything, except the correct answer!

I think it’s my confusion about the parent part of <template class …> in header.ui that I’m struggling with. The examples I’ve found don’t make that part clear.

Thank you

EDIT:

To give an idea of what I’m trying…

window.ui

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk" version="4.0"/>
  <template class="MyWindow" parent="GtkApplicationWindow">
    <child type="titlebar">
      <object class="HeaderBar"></object>
    </child>
  </template>
</interface>

header.ui

<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="HeaderBar" parent="GtkHeaderBar">
</template>
</interface>
Gtk-CRITICAL **: 23:08:54.960: Error building template class 'MyWindow' for an instance of type 'MyWindow': .:0:0 Invalid object type 'HeaderBar'

GLib type system is a dynamic type system. Custom GTypes are registered during runtime as they are first used. Since you are not using your custom HeaderBar type before instantiating your MyWindow type, it has not yet been registered with the type system and therefore GtkBuilder cannot find any type with name “HeaderBar” in the type system.

If I remember correctly, the solution suggested by experienced GNOME developers is to GObject.type_ensure all the custom types in order of their dependence on each other in Gio.Application.startup.

But what I (and surprisingly GTK and LibAdwaita as well) do is, I GObject.type_ensure all the custom types required by a custom type in its class_init (Visit GObject – 2.0: Type System Concepts for more info). That way, I get to keep track of what custom type requires what other custom types.

Note: The exact solution might look/be different depending on the language you are using. So, if you cannot understand my solution, please, provide name of the language you are using. That way I’ll be able to provide a straightforward answer.

Thank you for replying. I did read about g_type_ensure and played around a bit but didn’t get anywhere.

I’m using Python. I tried scrolling through GitHub looking at apps using Python and multiple .ui files and although the answer must be in some of the code I read, I couldn’t find it!

Thank you

There isn’t nearly enough context to give you a meaningful answer.

For instance:

  • is your HeaderBar an actual class?
  • how did you define it?
  • how are you managing the template files?
  • how is your project structured?

Have you read the tutorial on templates? Have you read the Gtk.Template documentation?

Thank you,

The answer to your first question is ‘no’, which is probably the problem.

I guess I’m correct to think “gtype_name” and “@Gtk.Template” can only be used once per class. After I’ve finished my day-long battle with Gtk.FileDialog I’ll go back to the .ui files. I need to understand those first, really.

Likely. Composite widget templates are not a way to include other random UI definition files: they are a way to automatically tie a UI definition file to a class, so that instantiating that class will parse the UI definition, assign class members to objects defined in the XML, and connect signal handlers.

If you have a HeaderBar template in your UI definition, with a GtkHeaderBar as a parent, then you need to have a HeaderBar class that inherits from Gtk.HeaderBar.

Yes, since they apply to a specific class.

You will need a headerbar.py file with something like:

from gi.repository import Gtk


xml = """
<interface>
  <requires lib="gtk" version="4.0"/>
  <template class="HeaderBar" parent="GtkHeaderBar">
    <property name="title-widget">
      <object class="GtkLabel" name="title_label">
        <property name="label">Window Title</property>
        <style>
          <class name="title" />
        </style>
      </object>
    <property>
  </template>
</interface>
"""

@Gtk.Template(string=xml)
class HeaderBar(Gtk.HeaderBar):
    __gtype_name__ = "HeaderBar"

    title_label = Gtk.Template.Child()

    def set_title(self, title: str):
        self.title_label.set_label(title)

and then your main window file would be:

import gi
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk

from .headerbar import HeaderBar


xml = """
<interface>
  <requires lib="gtk" version="4.0"/>
  <template class="MyWindow" parent="GtkApplicationWindow">
    <child type="titlebar">
      <object class="HeaderBar"></object>
    </child>
  </template>
</interface>
"""

@Gtk.Template(string=xml)
class MyWindow(Gtk.ApplicationWindow):
    __gtype_name__ = "MyWindow"

    header_bar = Gtk.Template.Child()

You probably want to start reading the documentation for PyGObject, GTK4, and the tutorials. A good starting point is:

:slight_smile: Thank you!!

Using your code and the source code from Wike I’ve managed to get the headerbar in it’s own .ui file, including a menubutton and stackswitcher with the stack in another .ui file. It finally clicked!

Docs and tutorials… I’ve read them all many times over the last few days, they just couldn’t quite get me over the finish line.

This topic was automatically closed 45 days after the last reply. New replies are no longer allowed.