3

Consider the following:

class MyCustomWidget : Gtk.Widget {
    public MyCustomWidget () {
        Object ();
    }
}

void main (string args[]) {
    string ui_string = """
    <?xml version="1.0" encoding="UTF-8"?>
    <interface>
        <object class="MyCustomWidget">
        </object>
    </interface>
    """;

    Gtk.init (ref args);    
    Gtk.Builder builder = new Gtk.Builder.from_string (ui_string, ui_string.length);
}

I am creating a custom Widget derived from Gtk.Widget. When using this widget with Gtk.Builder, I get the following error and the program crashes:

(bla:22282): Gtk-ERROR **: failed to add UI: .:4:1 Invalid object type 'MyCustomWidget'

1 Answers1

2

This happens because the type MyCustomWidget is not yet known to Gtk.Builder. This is why custom widgets should be instantiated at least once before being used with Gtk.Builder. This instance can then be thrown away.

void main (string args[]) {
    string ui_string = """
    <?xml version="1.0" encoding="UTF-8"?>
    <interface>
        <object class="MyCustomWidget">
        </object>
    </interface>
    """;

    Gtk.init (ref args);
    // create a throw-away instance of MyCustomWidget
    var tmp = new MyCustomWidget ();   
    Gtk.Builder builder = new Gtk.Builder.from_string (ui_string, ui_string.length);
}
  • 1
    Does Vala have a way to register the class without creating a new object, equivalent to calling the `classname_get_type()` function in C? Will the object be destroyed immediately? (I have not used Vala in a while...) – andlabs May 28 '17 at 23:53
  • possible duplicate of: https://stackoverflow.com/questions/22219788/adding-custom-widget-to-glade – José Fonte May 28 '17 at 23:56
  • 1
    @JoséFonte no, because that answer is about using custom widgets in the glade UI editor, not in actual code –  May 29 '17 at 14:03
  • @stunningpotato So what do you plan on achieving? Just add the creation of a custom widget to a UI definition file just for the sake of doing so? I see no goal on doing that. – José Fonte May 29 '17 at 14:06
  • @JoséFonte I have a project where I use some custom widgets. Because the rest of the window is defined using UI definition files it would be kinda hacky to add one single widget from Vala –  May 29 '17 at 14:28
  • @stunningpotato I don't see why it would be hacky... Ultimately you would want to add that custom widget to glade, that is the correct path. If that is a lot of work, just add your custom widget, programmatically, to the container you would retrieve from GtkBuilder. Not hacky at all. – José Fonte May 29 '17 at 14:55
  • 1
    I do not agree that creating a dummy instance is the right solution. It shouldn't be needed and might even be optimised out in some languages unless you get creative... @andlabs: The `type-func` attribute in the `GtkBuilder` `.ui` file *should* work... At least, I feel like a saw a bug going past that would have fixed it. Besides that, according to an experienced GNOME dev, if `type-func` isn't usable, then the answer is to invoke `typeof (Gtk.Whatever)` in Vala code: https://debarshiray.wordpress.com/2017/08/29/gtkbuilder-vala-and-webkit/ – underscore_d Jun 12 '19 at 13:28
  • Agree that 22219788 is not a duplicate. Getting the widget into glade is not the same as getting `GtkBuilder` to correctly load it. I arrived at this question having accomplished the latter (getting it into glade) but failing on the former (loading the created glade file). – cheshirekow Jul 20 '19 at 05:52
  • 1
    @underscore_d I can confirm that `type-func="mycustomwidget_get_type"` added to the UI definition file correctly solved this same problem for me. – cheshirekow Jul 20 '19 at 05:53
  • The `type-func` isn't working for me. I create a `FooBarWidget`, check the built source, find that it transpiles to have the function `foo_bar_widget_get_type`, but if I replace `class="FooBarWidget"` with `type-func="foo_bar_widget_get_type"` then I get `Invalid object in ui file` and if I have both then I get `Invalid type function 'foo_bar_widget_get_type'` (and Debarshi's blog does say that it won't work with Vala). I can't get `typeof(FooBarWidget)` working either. Using Vala 0.48.5. – IBBoard May 16 '20 at 18:04