I'm writing a custom widget using gtkmm, and I haven't been able to get it to work in glade. (The widget itself is barely functional; it does work, and I want to get it to work in glade before moving on to the next step.) Glade finds the widget, but when I try to place it in a window, glade crashes.
Based on hints I found during various searches, I added this bit of code to the main source file:
extern "C"
{
GType date_chooser_get_type(void)
{
return DateChooser::get_type();
}
}
I have a suspicion that the code above isn't right, but I can't find any gtkmm or glade documentation about what this function should do.
Based on the catalog documentation for glade, I created the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<glade-catalog name="gtk-date-chooser" library="libgtkdatechooser-0.1.so" language="c++">
<glade-widget-classes>
<glade-widget-class name="DateChooser" generic-name="date-chooser" title="Date Chooser" />
</glade-widget-classes>
<glade-widget-group name="date" title="Date">
<glade-widget-class-ref name="DateChooser"/>
</glade-widget-group>
</glade-catalog>
This is in the root of my widget's source directory with the name gtk-date-chooser.xml
. I run glade in that directory using:
GLADE_CATALOG_SEARCH_PATH=. GLADE_MODULE_SEARCH_PATH=./.libs glade
When the window comes up, my widget appears in a special "Date" group as specified in the catalog, with a default icon. If I place a window and then select the widget for placement in the window, glade crashes. I see the following on the console:
GladeUI-Message: 2 missing displayable value for GtkWidget::events
GladeUI-Message: No displayable values for property GtkTreeSelection::mode
GladeUI-Message: 1 missing displayable value for GtkCellRendererAccel::accel-mode
GladeUI-Message: 14 missing displayable value for GtkCellRendererAccel::accel-mods
(glade:23757): GladeUI-CRITICAL **: gwa_list_signals: assertion `real_type != 0' failed
(glade:23757): GLib-GObject-WARNING **: cannot retrieve class for invalid (unclassed) type `<invalid>'
(glade:23757): GLib-GObject-CRITICAL **: g_object_class_list_properties: assertion `G_IS_OBJECT_CLASS (class)' failed
(glade:23757): GLib-GObject-WARNING **: cannot retrieve class for invalid (unclassed) type `<invalid>'
(glade:23757): Gtk-CRITICAL **: gtk_container_class_list_child_properties: assertion `GTK_IS_CONTAINER_CLASS (cclass)' failed
GladeUI-Message: Glade needs artwork; a default icon will be used for the following classes:
DateChooser needs an icon named 'widget-gtk-date-chooser-date-chooser'
**
GladeUI:ERROR:glade-signal-model.c:800:glade_signal_model_iter_n_children: code should not be reached
It seems like the answer to this (unanswered) question might provide a clue, but I haven't been able to find any answer for that question or clues that will help with my problem.
Versions I'm using:
(I'd be willing to test solutions based on trunk versions, or on Centos 6 or Fedora 16.)
The followings are required to add a custom gtkmm widget to Glade:
The most important thing is the fact that Glade is written in C not in C++, so we have to be able to wrap a plan C widget to a C++ one and we have to register this wrap function to the GType
related to the custom widget. It looks something like the followings:
#include "custom_widget.h"
GType CustomWidget::gtype = 0;
CustomWidget::CustomWidget (GtkEntry *gobj) :
Gtk::Entry (gobj)
{
}
CustomWidget::CustomWidget () :
Glib::ObjectBase ("customwidget")
{
}
Glib::ObjectBase *
CustomWidget::wrap_new (GObject *o)
{
if (gtk_widget_is_toplevel (GTK_WIDGET (o)))
{
return new CustomWidget (GTK_ENTRY (o));
}
else
{
return Gtk::manage(new CustomWidget (GTK_ENTRY (o)));
}
}
void
CustomWidget::register_type ()
{
if (gtype)
return;
CustomWidget dummy;
GtkWidget *widget = GTK_WIDGET (dummy.gobj ());
gtype = G_OBJECT_TYPE (widget);
Glib::wrap_register (gtype, CustomWidget::wrap_new);
}
You should write the catalog file very carefully. Names must be correct (especially glade-widget-class
) for the proper work.
<?xml version="1.0" encoding="UTF-8" ?>
<glade-catalog name="customwidgets" library="customwidgetsglade" depends="gtk+">
<init-function>custom_widgets_glade_init</init-function>
<glade-widget-classes>
<glade-widget-class name="gtkmm__CustomObject_customwidget" generic-name="customwidget" icon-name="widget-gtk-entry" title="Custom Widget">
</glade-widget-class>
</glade-widget-classes>
<glade-widget-group name="customwidgets" title="Custom Widgets" >
<glade-widget-class-ref name="gtkmm__CustomObject_customwidget" />
</glade-widget-group>
</glade-catalog>
There is nothing to do, but implement the function, which registers our widget as the part of the initialization of our Glade library.
extern "C" void
custom_widgets_glade_init ()
{
Gtk::Main::init_gtkmm_internals ();
custom_widgets_register ();
}
Initializing gtkmm internals is a must, because custom_widgets_glade_init
is called from Glade, which is written in C not in C++ so it initializes only the GTK+.
If you are interested in the topic you can find my blog post here with more the details.