--- gtk/src/builder.ccg.old	2008-07-26 15:30:05.000000000 +0400
+++ gtk/src/builder.ccg	2009-03-11 19:18:27.000000000 +0300
@@ -214,7 +214,49 @@
 }
 
 
+namespace Private
+{
 
+struct SignalInfo {
+  const gchar *object_name;
+  gchar *signal_name;
+  gchar *handler_name;
+};
+
+typedef std::list<struct Private::SignalInfo> SignalInfoList;
+
+static void connect_signals_private(GtkBuilder *builder,
+	GObject *object, const gchar *signal_name, const gchar *handler_name,
+	GObject *connect_object, GConnectFlags flags, gpointer user_data)
+{
+  GValue value = {};
+  g_value_init(&value, G_TYPE_STRING);
+  g_object_get_property(object, "name", &value);
+  SignalInfoList *list = (SignalInfoList *)user_data;
+  /* gtk_builder_connect_signals_full() destroys all the signal-related
+   * data, so we need to g_strdup() the strings. */
+  list->push_back((struct SignalInfo){ g_value_get_string(&value),
+	g_strdup(signal_name), g_strdup(handler_name) });
+}
+
+} // namespace Private
+
+void Builder::connect_signals(Glib::SlotsContainer& slots)
+{
+  Private::SignalInfoList siginfo;
+  gtk_builder_connect_signals_full(gobj(),
+	Private::connect_signals_private, &siginfo);
+  for (Private::SignalInfoList::const_iterator it = siginfo.begin();
+	it != siginfo.end(); it++) {
+    Widget *widget = get_widget_checked(it->object_name,
+	    Widget::get_base_type());
+    if (!widget->connect(it->signal_name, it->handler_name, slots))
+      g_warning("Widget %s cannot connect signal %s to %s\n",
+    	it->object_name, it->signal_name, it->handler_name);
+    g_free(it->signal_name);
+    g_free(it->handler_name);
+  }
+}
 
 } // namespace Gtk
 
--- gtk/src/builder.hg.old	2008-07-26 15:30:05.000000000 +0400
+++ gtk/src/builder.hg	2009-03-11 15:40:58.000000000 +0300
@@ -308,7 +308,9 @@
   //_WRAP_METHOD(void connect_signals_full(GtkBuilderConnectFunc func, gpointer       user_data), gtk_builder_connect_signals_full)
   _WRAP_METHOD(void set_translation_domain(const Glib::ustring& domain), gtk_builder_set_translation_domain)
   _WRAP_METHOD(Glib::ustring get_translation_domain() const, gtk_builder_get_translation_domain)
-  
+
+  void connect_signals(Glib::SlotsContainer& slots);
+
   //We ignore gtk_builder_get_type_from_name() because it only seems useful when implementing GtkBuildable for widgets.
   _IGNORE(gtk_builder_get_type_from_name)
 
@@ -330,3 +332,9 @@
 
 } // namespace Gtk
 
+#define GTKBUILDER_SLOT(n, s) register_slot(__STRING(s), &n::s)
+#define GTKBUILDER_DECLARE_SLOTS(...) \
+virtual void __init_slots(void) \
+{ \
+    __VA_ARGS__; \
+}
--- gtk/src/button.ccg.old	2008-07-01 13:22:21.000000000 +0400
+++ gtk/src/button.ccg	2009-03-11 19:32:15.000000000 +0300
@@ -39,5 +39,27 @@
   _CONSTRUCT("use_stock", 1, "label", stock_id.get_c_str())
 {}
 
+bool Button::connect(Glib::ustring signal_name,
+	Glib::ustring handler_name, Glib::SlotsContainer& slots)
+{
+#define CONNECT_SIG(sig, sig_name, handler_name) \
+  do { \
+    if (sig_name == __STRING(sig)) { \
+      slots.connect(signal_##sig(), handler_name); \
+      return true; \
+    } \
+  } while (0)
+#define DO_CONNECT(sig) CONNECT_SIG(sig, signal_name, handler_name)
+
+  DO_CONNECT(clicked);
+  DO_CONNECT(released);
+  DO_CONNECT(clicked);
+  DO_CONNECT(enter);
+  DO_CONNECT(leave);
+  DO_CONNECT(activate);
+
+  return false;
+}
+
 } // namespace Gtk
 
--- gtk/src/button.hg.old	2008-07-01 13:22:21.000000000 +0400
+++ gtk/src/button.hg	2009-03-11 19:31:29.000000000 +0300
@@ -78,6 +78,9 @@
   _WRAP_METHOD(void enter(), gtk_button_enter)
   _WRAP_METHOD(void leave(), gtk_button_leave)
 
+  bool connect(Glib::ustring signal_name,
+	Glib::ustring handler_name, Glib::SlotsContainer& slots);
+
   _WRAP_METHOD(void set_relief(ReliefStyle newstyle), gtk_button_set_relief)
   _WRAP_METHOD(ReliefStyle get_relief() const, gtk_button_get_relief)
 
--- gtk/src/widget.ccg.old	2008-07-11 00:11:29.000000000 +0400
+++ gtk/src/widget.ccg	2009-03-11 18:57:37.000000000 +0300
@@ -583,6 +583,11 @@
   return Glib::wrap((GdkPixmapObject*)(gtk_widget_get_snapshot(const_cast<GtkWidget*>(gobj()), NULL)));
 }
 
+bool Widget::connect(Glib::ustring signal_name,
+	Glib::ustring handler_name, Glib::SlotsContainer& slots)
+{
+  return false;
+}
 
 } // namespace Gtk
 
--- gtk/src/widget.hg.old	2008-09-03 17:24:53.000000000 +0400
+++ gtk/src/widget.hg	2009-03-11 18:47:56.000000000 +0300
@@ -640,6 +640,9 @@
   _WRAP_SIGNAL(void size_request(Requisition* requisition), "size_request")
   _WRAP_SIGNAL(void size_allocate(Allocation& allocation), "size_allocate")
 
+  virtual bool connect(Glib::ustring signal_name,
+	Glib::ustring handler_name, Glib::SlotsContainer& slots);
+
 // Changed signals -- inform widget of internal changes.
 // We rename parent_set => parent_changed 
 //  and      style_set  => style_changed 
