Deriving from `Gtk::BuilderScope`, missing type-from-name vfunc

Hello,

I’m experimenting with using UI templates with Gtkmm (previously discussed here). I was able to get it working by invoking gtk_widget_class_set_template_from_resource and gtk_widget_init_template at the appropriate times with the help of Glib::ExtraClassInit. Now I’m running into an issue where the gtkmm__CustomObject_ prefix breaks name resolution – I can only load the template if I include the prefix and name my class gtkmm__CustomObject_ExampleWindow in the .ui file, otherwise I get the following error:

(<unknown>:7000): Gtk-CRITICAL **: 18:05:08.337: Error building template class 'gtkmm__CustomObject_DemoWindow' for an instance of type 'gtkmm__CustomObject_ExampleWindow': .:0:0 Parsed template definition for type 'ExampleWindow', expected type 'gtkmm__CustomObject_ExampleWindow'

In the past, it was possible to handle this by subclassing Builder and overriding get_type_from_name_vfunc_callback() but that was removed a few years ago in favor of Gtk::BuilderScope.

It looks like the existing BuilderScope callback handles the prefix gtkmm__, but not gtkmm__CustomObject_. If I’m reading the code correctly, I should be able to provide different behavior with my own get_type_from_name_vfunc_callback. This vfunc doesn’t actually appear as a virtual function in BuilderScope that I can override, and the default version is provided as an implementation of BuilderScope_Class, which is produced by macros.

Where can I implement my own type-from-name callback? Is there a working example that derives from BuilderScope?

Thank you for your help!

Okay, I was able to test the (Gtk) BuilderScope by manually replacing the callback used by GtkBuilderCScope (the default). For anyone curious, here’s the code, which must come after set_template_from_resource:

...
auto scope = gtk_builder_cscope_new();
auto scopeInterface = GTK_BUILDER_SCOPE_GET_IFACE(scope);
scopeInterface->get_type_from_name = [](GtkBuilderScope *scope, GtkBuilder *builder, const char *name) {
    std::cout << "name: " << name << std::endl;
    auto type = g_type_from_name(name);
    if (type != G_TYPE_INVALID)
        // todo: extra name resolution would go here 
        // e.g. try adding the `gtkmm__CustomObject_` prefix and calling g_type_from_name() again
        return type;
    return type;
};
gtk_widget_class_set_template_scope(
        klass,
        GTK_BUILDER_SCOPE(scope)
);
...

Note: Don’t use this in real code, it’s a terrible hack!
By replacing a property of the interface, the change actually applies to all BuilderScope instances.

Unfortunately, this isn’t able to solve my problem. I printed out each name, hoping to see ExampleWindow so that adding the gtkmm__CustomObject_ prefix can help with name resolution. All of the widgets that make up the template appear, but ExampleWindow itself never does. From reading Gtk’s code, it looks like the BuilderScope is used when parsing the elements of the composite widget, but not the root itself.

It looks like the issue is pretty deep in Gtk’s template parsing logic, so for now I might have to settle for including the prefix in my UI file, unless someone else has any ideas.

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