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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With