Search code examples
c++gtkgtkmm

Gtkmm Custom Widget throws error when building from Glade file


I have made a custom widget and have struggled all afternoon due to the lack of documentation to get a custom object that extends Gtk::Entry to work. I have gotten to the point where I can add the widget in Glade. I am now getting an error:

terminate called after throwing an instance of 'Gtk::BuilderError'

Upon loading. My gdb skills are not excellent but I know that the error is being thrown from auto builder = Gtk::Builder::create_from_file("glade/window_main.glade");

This is what my custom object implementation looks like:

...

IntEntry::IntEntry(GtkEntry *gobj) : Gtk::Entry(gobj)
{

}

IntEntry::IntEntry() : Glib::ObjectBase("intentry")
{
}

void IntEntry::set_value(int value)
{
  this->value = value;
  this->set_text(std::to_string(value));
}

void IntEntry::on_insert_text(const Glib::ustring &text, int *position)
{
  if (is_int(text))
  {
    Gtk::Entry::on_insert_text(text, position);
    auto full_text = this->get_text();
    std::string str_text = full_text.c_str();
    this->set_value(std::stoi(str_text));
  }else{
    Gtk::Entry::on_insert_text(text, position);
  }
}

Glib::ObjectBase *
IntEntry::wrap_new(GObject *o)
{
  if (gtk_widget_is_toplevel(GTK_WIDGET(o)))
  {
    return new IntEntry(GTK_ENTRY(o));
  }
  else
  {
    return Gtk::manage(new IntEntry(GTK_ENTRY(o)));
  }
}

void IntEntry::register_type()
{
  if (gtype)
    return;

  IntEntry dummy;

  GtkWidget *widget = GTK_WIDGET(dummy.gobj());

  gtype = G_OBJECT_TYPE(widget);
  
  Glib::wrap_register(gtype, IntEntry::wrap_new);
}


extern "C" void custom_widgets_init()
{
  Gtk::Main::init_gtkmm_internals();
  IntEntry::register_type();
}

This is mostly adapted from a blog post on a site that doesn't exist anymore but can be found archived here.

My catalog looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<glade-catalog name="customwidgets" library="customwidgetsglade" depends="gtk+">

  <init-function>custom_widgets_init</init-function>

  <glade-widget-classes>
    <glade-widget-class name="gtkmm__CustomObject_intentry" generic-name="intentry" icon-name="widget-gtk-entry" title="Int Entry">
    </glade-widget-class>
  </glade-widget-classes>

  <glade-widget-group name="customwidgets" title="Custom Widgets" >
    <glade-widget-class-ref name="gtkmm__CustomObject_intentry" />
  </glade-widget-group>

</glade-catalog>

Solution

  • As it turns out in the course of writing the question I figured out my issue.

    I had forgotten to register my custom objects before trying to use them.

    I needed to call custom_widgets_init() prior to calling Gtk::Builder::create_from_file("glade/window_main.glade");