Index: configure.in
===================================================================
RCS file: /cvs/gnome/glade3/configure.in,v
retrieving revision 1.76
diff -u -u -p -r1.76 configure.in
--- configure.in	27 Oct 2006 15:20:36 -0000	1.76
+++ configure.in	7 Nov 2006 19:55:43 -0000
@@ -72,6 +72,31 @@ else
 fi
 
 AM_CONDITIONAL(BUILD_GNOME, test x"$have_gnome" = "xyes")
+
+dnl ===============================================================
+dnl Check for Python
+dnl ================================================================
+AC_ARG_ENABLE(python,
+[  --disable-python         disable python scripting module],
+     check_python=$enableval, check_python=yes)
+
+if test x"$check_python" = x"yes"; then
+    PYTHON="nop"
+    AC_PATH_PROGS([PYTHON], [python])
+    
+    if test "$PYTHON" != "nop"; then
+             PKG_CHECK_MODULES(PYGTK, pygtk-2.0 >= 2.8.0)
+             PYTHON_CFLAGS="`$PYTHON -c "from distutils import sysconfig; getvar = sysconfig.get_config_var; flags = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]; print ' '.join(flags)"` $PYGTK_CFLAGS"
+             PYTHON_LIBS="`$PYTHON -c "from distutils import sysconfig; pyver = sysconfig.get_config_var('VERSION'); getvar = sysconfig.get_config_var; libs = getvar('LIBS').split() + getvar('SYSLIBS').split(); libs.append('-lpython'+pyver); libs.insert(0, '-L' + getvar('LIBPL')); print ' '.join(libs)"` $PYGTK_LIBS"
+             AC_SUBST(PYTHON_CFLAGS)
+             AC_SUBST(PYTHON_LIBS)
+             have_python=yes
+     fi
+else
+     have_python=no
+fi
+
+AM_CONDITIONAL(BUILD_PYTHON, test x"$have_python" = "xyes")
 
 dnl ================================================================
 dnl Check for windows
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/glade3/src/Makefile.am,v
retrieving revision 1.61
diff -u -u -p -r1.61 Makefile.am
--- src/Makefile.am	26 Oct 2006 00:45:20 -0000	1.61
+++ src/Makefile.am	7 Nov 2006 19:55:44 -0000
@@ -88,6 +88,7 @@ libgladeui_1_la_SOURCES = \
 	glade-app.c \
 	glade-keysyms.c \
 	glade-fixed.c \
+	glade-binding.c \
 	glade-base-editor.c
 
 libgladeui_1_la_CFLAGS =    \
@@ -145,6 +146,15 @@ libgladeuiinclude_HEADERS = \
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libgladeui-1.0.pc glade-3.pc
 
+if BUILD_PYTHON
+gladepython_LTLIBRARIES = libgladepython.la
+gladepythondir = $(glade_bindingsdir)
+libgladepython_la_SOURCES = glade-python.c
+libgladepython_la_CFLAGS = -g -Wall $(PYTHON_CFLAGS) $(GTK_CFLAGS)
+libgladepython_la_LDFLAGS = -module -avoid-version $(PYTHON_LIBS)
+libgladepython_la_LIBADD = libgladeui-1.la $(PYTHON_LIBS)
+endif
+
 if BUILD_GNOME
 gladegnome_LTLIBRARIES = libgladegnome.la
 gladegnomedir = $(glade_modulesdir)
@@ -160,6 +170,10 @@ if WITH_WIN32
 
 if BUILD_GNOME
   libgladegnome_la_LDFLAGS += -no-undefined
+endif
+
+if BUILD_PYTHON
+  libgladepython_la_LDFLAGS += -no-undefined
 endif
 
 endif
Index: src/glade-app.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-app.c,v
retrieving revision 1.47
diff -u -u -p -r1.47 glade-app.c
--- src/glade-app.c	19 Oct 2006 17:15:09 -0000	1.47
+++ src/glade-app.c	7 Nov 2006 19:55:46 -0000
@@ -30,24 +30,13 @@
 #include <glib/gi18n-lib.h>
 
 #include "glade.h"
-#include "glade-palette.h"
-#include "glade-editor.h"
-#include "glade-clipboard.h"
 #include "glade-clipboard-view.h"
-#include "glade-widget.h"
-#include "glade-property.h"
-#include "glade-property-class.h"
-#include "glade-project.h"
-#include "glade-project-view.h"
-#include "glade-placeholder.h"
-#include "glade-command.h"
 #include "glade-debug.h"
-#include "glade-utils.h"
 #include "glade-cursor.h"
 #include "glade-catalog.h"
-#include "glade-app.h"
 #include "glade-paths.h"
 #include "glade-fixed.h"
+#include "glade-binding.h"
 
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtkstock.h>
@@ -93,8 +82,10 @@ enum
 static guint glade_app_signals[LAST_SIGNAL] = { 0 };
 
 gchar *glade_pixmaps_dir = GLADE_PIXMAPSDIR;
+gchar *glade_scripts_dir = GLADE_SCRIPTSDIR;
 gchar *glade_catalogs_dir = GLADE_CATALOGSDIR;
 gchar *glade_modules_dir = GLADE_MODULESDIR;
+gchar *glade_bindings_dir = GLADE_BINDINGSDIR;
 gchar *glade_plugins_dir = GLADE_PLUGINSDIR;
 gchar *glade_locale_dir = GLADE_LOCALEDIR;
 gchar *glade_icon_dir = GLADE_ICONDIR;
@@ -163,11 +154,17 @@ glade_app_finalize (GObject *app)
 
 #ifdef G_OS_WIN32 
 	g_free (glade_pixmaps_dir);
+	g_free (glade_scripts_dir);
 	g_free (glade_catalogs_dir);
 	g_free (glade_modules_dir);
+	g_free (glade_bindings_dir);	
 	g_free (glade_locale_dir);
 	g_free (glade_icon_dir);
 #endif
+	
+	glade_binding_unload_all ();
+	
+	glade_catalog_modules_close ();
 
 	g_free (GLADE_APP (app)->priv);
 	if (parent_class->finalize)
@@ -319,14 +316,19 @@ glade_app_init (GladeApp *app)
 	
 		prefix = g_win32_get_package_installation_directory (NULL, NULL);
 		glade_pixmaps_dir = g_build_filename (prefix, "share", PACKAGE, "pixmaps", NULL);
+		glade_scripts_dir = g_build_filename (prefix, "share", PACKAGE, GLADE_BINDING_SCRIPT_DIR, NULL);
 		glade_catalogs_dir = g_build_filename (prefix, "share", PACKAGE, "catalogs", NULL);
 		glade_modules_dir = g_build_filename (prefix, "lib", PACKAGE, "modules", NULL);
+		glade_bindings_dir = g_build_filename (prefix, "lib", PACKAGE, "bindings", NULL);
 		glade_locale_dir = g_build_filename (prefix, "share", "locale", NULL);
 		glade_icon_dir = g_build_filename (prefix, "share", "pixmaps", NULL);
 		g_free (prefix);
 #endif
 	
 		glade_cursor_init ();
+		
+		glade_binding_load_all ();
+		
 		initialized = TRUE;
 	}
 	app->priv = g_new0 (GladeAppPriv, 1);
@@ -336,6 +338,8 @@ glade_app_init (GladeApp *app)
 	/* Initialize app objects */
 	app->priv->catalogs = glade_catalog_load_all ();
 	
+	glade_binding_script_setup_items ();
+	
 	/* Create palette */
 	app->priv->palette = (GladePalette *) glade_palette_new (app->priv->catalogs, GLADE_ITEM_ICON_ONLY);
 	g_object_ref (app->priv->palette);
@@ -755,7 +759,7 @@ glade_app_get_project_by_path (const gch
 	GList    *l;
 	gchar *canonical_path;
 
-	if (project_path == NULL) return FALSE;
+	if (project_path == NULL) return NULL;
 
 	app = glade_app_get ();
 
@@ -772,6 +776,35 @@ glade_app_get_project_by_path (const gch
 	}
 
 	g_free (canonical_path);
+
+	return NULL;
+}
+
+/**
+ * glade_app_get_project_by_name:
+ * @project_name: The name of an open project
+ *
+ * Finds an open project by name.
+ *
+ * Returns: A #GladeProject, or NULL if no such open project was found
+ */
+GladeProject *
+glade_app_get_project_by_name (const gchar *project_name)
+{
+	GladeApp *app;
+	GList *l;
+
+	if (project_name == NULL) return NULL;
+
+	app = glade_app_get ();
+
+	for (l = app->priv->projects; l; l = g_list_next (l))
+	{
+		GladeProject *project = l->data;
+
+		if (strcmp (project_name, project->name) == 0)
+			return project;
+	}
 
 	return NULL;
 }
Index: src/glade-app.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-app.h,v
retrieving revision 1.20
diff -u -u -p -r1.20 glade-app.h
--- src/glade-app.h	12 Aug 2006 01:34:01 -0000	1.20
+++ src/glade-app.h	7 Nov 2006 19:55:46 -0000
@@ -99,6 +99,8 @@ LIBGLADEUI_API 
 gboolean           glade_app_is_project_loaded (const gchar *project_path);
 LIBGLADEUI_API 
 GladeProject*      glade_app_get_project_by_path (const gchar *project_path);
+LIBGLADEUI_API
+GladeProject      *glade_app_get_project_by_name (const gchar *project_name);
 LIBGLADEUI_API 
 void               glade_app_show_properties (gboolean raise);
 LIBGLADEUI_API 
Index: src/glade-binding.c
===================================================================
RCS file: src/glade-binding.c
diff -N src/glade-binding.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/glade-binding.c	7 Nov 2006 19:55:47 -0000
@@ -0,0 +1,369 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Juan Pablo Ugarte.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ *   Juan Pablo Ugarte <juanpablougarte@gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "glade.h"
+#include "glade-binding.h"
+#include "glade-paths.h"
+#include <string.h>
+
+static GHashTable *bindings = NULL;
+
+static GList *
+glade_binding_get_script_list (GladeBinding *binding, gchar *directory)
+{
+	const gchar *filename;
+	GList *list = NULL;
+	GDir *dir;
+
+	if ((dir = g_dir_open (directory, 0, NULL)) == NULL) 
+		return NULL;
+
+	while ((filename = g_dir_read_name (dir)))
+	{
+		gchar *tmp, *path = g_build_filename (directory, filename, NULL);
+		
+		if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
+		{
+			GladeBindingScript *script = g_new0 (GladeBindingScript, 1);
+			script->binding = binding;
+			script->path = path;
+			script->name = g_path_get_basename (path);
+			if ((tmp = strrchr (script->name, '.'))) *tmp = '\0';
+			list = g_list_prepend (list, script);
+		}
+		else g_free (path);
+	}
+	
+	return list;
+}
+
+static void
+glade_binding_script_free (gpointer data, gpointer user_data)
+{
+	GladeBindingScript *script = data;
+	if (script->path) g_free (script->path);
+	if (script->name) g_free (script->name);
+	g_free (script);
+}
+
+static void 
+glade_binding_classes_destroy (gpointer value)
+{
+	g_list_foreach (value, glade_binding_script_free, NULL);
+	g_list_free (value);
+}
+
+static void
+glade_binding_scriptdo_load (GladeBinding *binding, gchar *rootdir)
+{
+	const gchar *filename;
+	GDir *dir;
+	
+	if ((dir = g_dir_open (rootdir, 0, NULL)) == NULL) 
+		return;
+
+	while ((filename = g_dir_read_name (dir)))
+	{
+		gchar *path = g_build_filename (rootdir, filename, NULL);
+		GType type;
+
+		if (g_file_test (path, G_FILE_TEST_IS_DIR) &&
+		    (type = glade_util_get_type_from_name (filename)))
+		{
+			GList *list, *old_list;
+
+			list = glade_binding_get_script_list (binding, path);
+			old_list = g_datalist_id_get_data (&binding->classes,
+							   type);
+
+			g_datalist_id_remove_no_notify (&binding->classes, type);
+			list = g_list_concat (old_list, list);
+
+			g_datalist_id_set_data_full (&binding->classes, type, list,
+						     glade_binding_classes_destroy);
+		}
+		
+		g_free (path);
+	}
+}
+
+/**
+ * glade_binding_load_all:
+ *
+ * Loads and initialize every binding plugin.
+ *
+ */
+void
+glade_binding_load_all ()
+{
+	const gchar *filename;
+	GError *error = NULL;
+	GDir *dir;
+
+	/* Read all files in bindings dir */
+	if ((dir = g_dir_open (glade_bindings_dir, 0, &error)) == NULL) 
+	{
+		g_warning ("Failed to open bindings directory: %s", error->message);
+		return;
+	}
+	
+	if (bindings == NULL)
+		bindings = g_hash_table_new (g_str_hash, g_str_equal);
+	
+	while ((filename = g_dir_read_name (dir)))
+	{
+		void (*init)(GladeBinding *);
+		GladeBinding *binding;
+		GModule *module;
+		gchar *path;
+		
+		if (g_str_has_suffix (filename, G_MODULE_SUFFIX) == FALSE)
+			continue;
+		
+		path = g_build_filename (glade_bindings_dir, filename, NULL);
+		module = g_module_open (path, G_MODULE_BIND_LAZY);
+		g_free (path);
+		
+		if (module == NULL) continue;
+	
+		binding = g_new0 (GladeBinding, 1);
+		binding->module = module;
+		
+		g_module_symbol (module, "glade_binding_init", (gpointer)&init);
+	
+		if (init) 
+		{
+			init (binding);
+			g_hash_table_insert (bindings, binding->name, binding);
+			if (binding->run_script)
+			{
+				gchar *rootdir;
+				g_datalist_init (&binding->classes);
+				
+				rootdir = g_build_filename (glade_scripts_dir,
+							    binding->name, NULL);
+				glade_binding_scriptdo_load (binding, rootdir);
+				g_free (rootdir);
+		
+				rootdir = g_build_filename (g_get_user_config_dir (),
+							    PACKAGE_NAME, GLADE_BINDING_SCRIPT_DIR,
+							    binding->name, NULL);
+				glade_binding_scriptdo_load (binding, rootdir);
+				g_free (rootdir);
+			}
+		}
+		else
+		{
+			g_module_close (module);
+			g_free (binding);
+		}
+	}
+}
+
+static void 
+glade_binding_remove (gpointer key, gpointer value, gpointer user_data)
+{
+	GladeBinding *binding = value;
+	if (binding->finalize) binding->finalize();
+	g_free (binding->name);	
+	g_module_close (binding->module);
+	
+	if (binding->classes)
+		g_datalist_clear (&binding->classes);
+	
+	g_free (binding);
+}
+
+/**
+ * glade_binding_unload_all:
+ *
+ * Finalize and unload every binding plugin.
+ *
+ */
+void
+glade_binding_unload_all ()
+{
+	if (bindings == NULL) return;
+		
+	g_hash_table_foreach (bindings, glade_binding_remove, NULL);
+	g_hash_table_destroy (bindings);
+	bindings = NULL;
+}
+
+/**
+ * glade_binding_get:
+ *
+ * @name: the binding name (ie: python)
+ *
+ * Returns the loaded binding.
+ *
+ */
+GladeBinding *
+glade_binding_get (gchar *name)
+{
+	g_return_val_if_fail (name != NULL, NULL);
+	return g_hash_table_lookup (bindings, name);	
+}
+
+static void
+glade_binding_get_all_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+	GList **l = user_data;
+	*l = g_list_append (*l, value);
+}
+
+/**
+ * glade_binding_get_all:
+ *
+ * Return a newly alocated list of every laoded binding.
+ *
+ */
+GList *
+glade_binding_get_all ()
+{
+	GList *l = NULL;
+	
+	g_hash_table_foreach (bindings, glade_binding_get_all_foreach, &l);
+	
+	return l;
+}
+
+/**
+ * glade_binding_library_load:
+ *
+ * @binding: a GladeBinding.
+ * @library: the library name.
+ *
+ * Loads the library name.
+ *
+ */
+void
+glade_binding_library_load (GladeBinding *binding, gchar *library)
+{
+	g_return_if_fail (binding != NULL && library != NULL);
+	binding->library_load (library);
+}
+
+/**
+ * glade_binding_library_init:
+ *
+ * @binding: a GladeBinding.
+ * @init: the library init function name.
+ *
+ * Runs the corresponding init function.
+ *
+ */
+void
+glade_binding_library_init (GladeBinding *binding, gchar *init)
+{
+	g_return_if_fail (binding != NULL && init != NULL);
+	binding->library_init (init);
+}
+
+/**
+ * glade_binding_console_new:
+ *
+ * @binding: a GladeBinding.
+ *
+ * Create a new console.
+ *
+ */
+GtkWidget *
+glade_binding_console_new (GladeBinding *binding)
+{
+	g_return_val_if_fail (binding != NULL, NULL);
+	return binding->console_new ();
+}
+
+/**
+ * glade_binding_run_script:
+ *
+ * @binding: a GladeBinding.
+ * @path: the library init function name.
+ *
+ * Run a script file.
+ *
+ */
+gint
+glade_binding_run_script (GladeBinding *binding, gchar *path)
+{
+	g_return_val_if_fail (binding != NULL && path != NULL, -1);
+	if (binding->run_script)
+		return binding->run_script (path);
+	else
+		return -1;
+}
+
+#include "glade-popup.h"
+
+static void
+glade_popup_script_item_activate_cb (GladeWidgetAdaptor *adaptor,
+				     GladeWidget *widget,
+				     GladeBindingScript *script)
+{
+	glade_binding_run_script (script->binding, script->path);
+}
+
+static void
+glade_binding_script_classes_foreach (GQuark key_id,
+				      gpointer data,
+				      gpointer user_data)
+{
+	GladeWidgetAdaptor *adaptor = glade_widget_adaptor_get_by_type (key_id);
+	GList *l;
+
+	for (l = data; l; l = g_list_next (l))
+	{
+		GladeBindingScript *script = l->data;
+		gchar *detailed_signal = g_strdup_printf ("action-activated::%s", script->name);
+		
+		glade_widget_adaptor_action_add (adaptor, "script-do", script->name, script->name, FALSE);
+
+		g_signal_connect (adaptor, detailed_signal,
+				  G_CALLBACK (glade_popup_script_item_activate_cb),
+				  script);
+
+		g_free (detailed_signal);
+	}
+}
+
+static void
+glade_binding_script_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+	GladeBinding *binding = value;
+	
+	g_datalist_foreach (&binding->classes,
+			    glade_binding_script_classes_foreach, NULL);
+}
+
+void
+glade_binding_script_setup_items (void)
+{
+	glade_widget_adaptor_action_add_group (
+			glade_widget_adaptor_get_by_name ("GtkWidget"),
+			NULL, "script-do", "Script-do");
+	g_hash_table_foreach (bindings, glade_binding_script_foreach, NULL);
+}
Index: src/glade-binding.h
===================================================================
RCS file: src/glade-binding.h
diff -N src/glade-binding.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/glade-binding.h	7 Nov 2006 19:55:47 -0000
@@ -0,0 +1,80 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Juan Pablo Ugarte.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ *   Juan Pablo Ugarte <juanpablougarte@gmail.com>
+ */
+ 
+#ifndef __GLADE_BINDING_H__
+#define __GLADE_BINDING_H__
+
+G_BEGIN_DECLS
+
+#define GLADE_BINDING_SCRIPT_DIR "script-do"
+
+typedef struct _GladeBinding GladeBinding ;
+struct _GladeBinding {
+	GModule  *module;
+	gchar    *name;
+	
+	GData *classes;
+	
+	/* Module symbols */
+	void       (*finalize)(void);
+	void       (*library_load) (gchar *str);
+	void       (*library_init) (gchar *str);
+	gint       (*run_script)   (gchar *path);
+	GtkWidget *(*console_new)  (void);
+};
+
+typedef struct _GladeBindingScript GladeBindingScript ;
+struct _GladeBindingScript {
+	GladeBinding *binding;
+	gchar *name, *path;
+};
+
+LIBGLADEUI_API
+void          glade_binding_load_all (void);
+
+LIBGLADEUI_API
+void          glade_binding_unload_all (void);
+
+LIBGLADEUI_API
+GladeBinding *glade_binding_get (gchar *name);
+
+LIBGLADEUI_API
+GList        *glade_binding_get_all ();
+
+LIBGLADEUI_API
+void          glade_binding_library_load (GladeBinding *binding, gchar *library);
+
+LIBGLADEUI_API
+void          glade_binding_library_init (GladeBinding *binding, gchar *init);
+
+LIBGLADEUI_API
+gint          glade_binding_run_script (GladeBinding *script, gchar *path);
+
+LIBGLADEUI_API
+GtkWidget    *glade_binding_console_new (GladeBinding *binding);
+
+LIBGLADEUI_API
+void          glade_binding_script_setup_items (void);
+
+G_END_DECLS
+
+#endif
Index: src/glade-catalog.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-catalog.c,v
retrieving revision 1.38
diff -u -u -p -r1.38 glade-catalog.c
--- src/glade-catalog.c	19 Oct 2006 17:15:09 -0000	1.38
+++ src/glade-catalog.c	7 Nov 2006 19:55:48 -0000
@@ -36,11 +36,13 @@
 #include "glade.h"
 #include "glade-catalog.h"
 #include "glade-widget-adaptor.h"
+#include "glade-binding.h"
 
 typedef void   (*GladeCatalogInitFunc) (void);
 
 struct _GladeCatalog
 {
+	gchar *language;	 /* Library language, NULL means language is C */
 	gchar *library;          /* Library name for backend support  */
 
 	gchar *name;             /* Symbolic catalog name             */
@@ -147,7 +149,9 @@ catalog_open (const gchar *filename)
 		glade_xml_context_free (context);
 		return NULL;
 	}
-	
+
+	catalog->language =
+		glade_xml_get_property_string (root, GLADE_TAG_LANGUAGE);
 	catalog->library =
 		glade_xml_get_property_string (root, GLADE_TAG_LIBRARY);
 	catalog->dep_catalog =
@@ -159,7 +163,7 @@ catalog_open (const gchar *filename)
 	catalog->init_function_name =
 		glade_xml_get_value_string (root, GLADE_TAG_INIT_FUNCTION);
 	
-	if (catalog->init_function_name)
+	if (catalog->init_function_name && catalog->language)
 		catalog_get_function (catalog, catalog->init_function_name,
 				      (gpointer) &catalog->init_function);
 
@@ -254,11 +258,45 @@ catalog_sort (GList *catalogs)
 	return sorted;
 }
 
+static GHashTable *modules = NULL;
+
+static GModule *
+catalog_load_library (GladeCatalog *catalog)
+{
+	GModule *module;
+
+	if (modules == NULL)
+		modules = g_hash_table_new (g_str_hash, g_str_equal);
+		
+	if (catalog->library == NULL) return NULL;
+
+	if (catalog->language)
+	{
+		GladeBinding *binding = glade_binding_get (catalog->language);
+		if (binding)
+			glade_binding_library_load (binding, catalog->library);
+		return NULL;
+	}
+	else
+	{
+		if ((module = g_hash_table_lookup (modules, catalog->library)))
+			return module;	
+		
+		if ((module = glade_util_load_library (catalog->library)))
+			g_hash_table_insert (modules, g_strdup (catalog->library), module);
+		else
+			g_warning ("Failed to load external library '%s'",
+				   catalog->library);
+		
+		return module;
+	}
+}
 
 static gboolean
 catalog_load_classes (GladeCatalog *catalog, GladeXmlNode *widgets_node)
 {
 	GladeXmlNode *node;
+	GModule *module = catalog_load_library (catalog);
 
 	node = glade_xml_node_get_children (widgets_node);
 	for (; node; node = glade_xml_node_next (node)) 
@@ -271,7 +309,7 @@ catalog_load_classes (GladeCatalog *cata
 			continue;
 	
 		adaptor = glade_widget_adaptor_from_catalog 
-			(node, catalog->name, catalog->library, 
+			(node, catalog->name, module,
 			 catalog->domain ? catalog->domain : catalog->library,
 			 catalog->book);
 
@@ -427,6 +465,19 @@ glade_catalog_load_all (void)
 	for (l = catalogs; l; l = l->next)
 	{
 		catalog = l->data;
+		
+		if (catalog->language)
+		{
+			GladeBinding *binding = glade_binding_get (catalog->language);
+			if (binding)
+			{
+				glade_binding_library_load (binding, catalog->library);
+				if (catalog->init_function_name)
+					glade_binding_library_init (binding, 
+							    catalog->init_function_name);
+			}
+		}
+		
 		if (catalog->init_function) catalog->init_function ();
 	}
 	
@@ -530,4 +581,28 @@ glade_catalog_is_loaded (const gchar *na
 		if (!strcmp (name, (gchar *)l->data))
 			return TRUE;
 	return FALSE;
+}
+
+
+static void 
+catalog_module_close (gpointer key, gpointer value, gpointer user_data)
+{
+	g_module_close (value);
+	g_free (key);
+}
+
+/**
+ * glade_catalog_modules_close:
+ *
+ * Close every opened module.
+ *
+ */
+void
+glade_catalog_modules_close ()
+{
+	if (modules == NULL) return;
+		
+	g_hash_table_foreach (modules, catalog_module_close, NULL);
+	g_hash_table_destroy (modules);
+	modules = NULL;
 }
Index: src/glade-catalog.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-catalog.h,v
retrieving revision 1.16
diff -u -u -p -r1.16 glade-catalog.h
--- src/glade-catalog.h	19 Oct 2006 17:15:09 -0000	1.16
+++ src/glade-catalog.h	7 Nov 2006 19:55:48 -0000
@@ -61,6 +61,9 @@ void          glade_widget_group_free   
 LIBGLADEUI_API 
 gboolean      glade_catalog_is_loaded               (const gchar      *name);
 
+LIBGLADEUI_API
+void          glade_catalog_modules_close           (void);
+
 G_END_DECLS
 
 #endif /* __GLADE_CATALOG_H__ */
Index: src/glade-gnome.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-gnome.c,v
retrieving revision 1.9
diff -u -u -p -r1.9 glade-gnome.c
--- src/glade-gnome.c	19 Oct 2006 17:15:09 -0000	1.9
+++ src/glade-gnome.c	7 Nov 2006 19:55:53 -0000
@@ -517,8 +517,8 @@ glade_gnome_druid_set_child_property (Gl
 		/* Chain Up */
 		GWA_GET_CLASS
 			(GTK_TYPE_CONTAINER)->child_set_property (adaptor,
-								  GTK_CONTAINER (container), 
-								  GTK_WIDGET (child),
+								  container, 
+								  child,
 								  property_name,
 								  value);
 }
@@ -541,8 +541,8 @@ glade_gnome_druid_get_child_property (Gl
 		/* Chain Up */
 		GWA_GET_CLASS
 			(GTK_TYPE_CONTAINER)->child_get_property (adaptor,
-								  GTK_CONTAINER (container), 
-								  GTK_WIDGET (child),
+								  container, 
+								  child,
 								  property_name,
 								  value);
 }
@@ -1813,4 +1813,3 @@ glade_gnome_bonobodock_set_allow_floatin
 	bonobo_dock_allow_floating_items (BONOBO_DOCK (object),
 					  g_value_get_boolean (value));
 }
-
Index: src/glade-paths.sh.in
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-paths.sh.in,v
retrieving revision 1.2
diff -u -u -p -r1.2 glade-paths.sh.in
--- src/glade-paths.sh.in	30 Apr 2006 06:27:36 -0000	1.2
+++ src/glade-paths.sh.in	7 Nov 2006 19:55:53 -0000
@@ -15,7 +15,9 @@ glade_libdir="@glade_libdir@"
 glade_catalogsdir="@glade_catalogsdir@"
 glade_modulesdir="@glade_modulesdir@"
 glade_pluginsdir="@glade_pluginsdir@"
+glade_bindingsdir="@glade_bindingsdir@"
 glade_pixmapsdir="@glade_pixmapsdir@"
+glade_scriptsdir="@glade_scriptsdir@"
 glade_icondir="@glade_icondir@"
 glade_localedir="@glade_localedir@"
 
@@ -31,7 +33,9 @@ cat <<EOF
 #define GLADE_CATALOGSDIR "$glade_catalogsdir"
 #define GLADE_MODULESDIR "$glade_modulesdir"
 #define GLADE_PLUGINSDIR "$glade_pluginsdir"
+#define GLADE_BINDINGSDIR "$glade_bindingsdir"
 #define GLADE_PIXMAPSDIR "$glade_pixmapsdir"
+#define GLADE_SCRIPTSDIR "$glade_scriptsdir"
 #define GLADE_ICONDIR "$glade_icondir"
 #define GLADE_LOCALEDIR "$glade_localedir"
 
Index: src/glade-popup.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-popup.c,v
retrieving revision 1.37
diff -u -u -p -r1.37 glade-popup.c
--- src/glade-popup.c	29 Oct 2006 17:17:58 -0000	1.37
+++ src/glade-popup.c	7 Nov 2006 19:55:53 -0000
@@ -35,6 +35,7 @@
 #include "glade-command.h"
 #include "glade-project.h"
 #include "glade-app.h"
+#include "glade-binding.h"
 
 /********************************************************
                       WIDGET POPUP
@@ -198,6 +199,46 @@ glade_popup_populate_childs (GtkWidget* 
 	}
 }
 
+static void
+glade_popup_menuitem_activated (GtkMenuItem *item, GladeWidget *widget)
+{
+	gchar *detail;
+	
+	if ((detail = g_object_get_data (G_OBJECT (item), "menuitem_detail")))
+		glade_widget_adaptor_emit_action_activated (widget, detail);
+}
+
+static void
+glade_popup_add_actions (GtkWidget *menu, GladeWidget *widget, GList *actions)
+{
+	GList *list;
+	GtkWidget *item;
+	
+	for (list = actions; list; list = g_list_next (list))
+	{
+		GladeAction *action = list->data;
+		GtkWidget *submenu = NULL;
+		
+		if (action->actions)
+		{
+			submenu = gtk_menu_new ();
+			glade_popup_add_actions (submenu, widget, action->actions);
+		}
+		
+		if (action->is_a_group && submenu == NULL) continue;
+		
+		item = glade_popup_append_item (menu, 
+				(action->use_stock) ? action->label : NULL,
+				action->label, TRUE,
+				(action->is_a_group) ? NULL : glade_popup_menuitem_activated,
+				(action->is_a_group) ? NULL : widget);
+		if (action->is_a_group == FALSE)
+			g_object_set_data (G_OBJECT (item), "menuitem_detail", action->id);
+		
+		if (submenu)
+			gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+	}
+}
 
 static GtkWidget *
 glade_popup_create_menu (GladeWidget *widget, gboolean add_childs)
@@ -220,6 +261,8 @@ glade_popup_create_menu (GladeWidget *wi
 
 	glade_popup_append_item (popup_menu, GTK_STOCK_DELETE, NULL, TRUE,
 				 glade_popup_delete_cb, widget);
+
+	glade_popup_add_actions (popup_menu, widget, widget->adaptor->actions);
 
 	if (add_childs &&
 	    !g_type_is_a (widget->adaptor->type, GTK_TYPE_WINDOW)) {
Index: src/glade-project-window.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-project-window.c,v
retrieving revision 1.169
diff -u -u -p -r1.169 glade-project-window.c
--- src/glade-project-window.c	29 Oct 2006 17:17:58 -0000	1.169
+++ src/glade-project-window.c	7 Nov 2006 19:55:59 -0000
@@ -33,6 +33,7 @@
 #include "glade.h"
 #include "glade-design-view.h"
 #include "glade-project-window.h"
+#include "glade-binding.h"
 
 #define GLADE_ACTION_GROUP_STATIC "GladeStatic"
 #define GLADE_ACTION_GROUP_PROJECT "GladeProject"
@@ -69,7 +70,9 @@ struct _GladeProjectWindowPrivate
 	
 	GtkRecentManager *recent_manager;
 	GtkWidget *recent_menu;
-	
+
+	GtkWidget *console;
+
 	gchar *default_path; /* the default path for open/save operations */
 };
 
@@ -989,51 +992,64 @@ gpw_redo_cb (GtkAction *action, GladePro
 	glade_app_command_redo ();
 }
 
-static void
-gpw_doc_search_cb (GladeEditor        *editor,
-		   const gchar        *book,
-		   const gchar        *page,
-		   const gchar        *search,
-		   GladeProjectWindow *gpw)
-{
-	glade_util_search_devhelp (book, page, search);
-}
-
 static gboolean
-gpw_hide_clipboard_view_on_delete (GtkWidget *clipboard_view, gpointer not_used,
-				   GtkUIManager *ui)
+gpw_hide_window_on_delete (GtkWidget *window, gpointer not_used, GtkUIManager *ui)
 {
-	glade_util_hide_window (GTK_WINDOW (clipboard_view));
+	glade_util_hide_window (GTK_WINDOW (window));
 	return TRUE;
 }
 
-static void 
-gpw_create_clipboard_view (GladeProjectWindow *gpw)
-{
-	GtkWidget *view;
-	
-	view = glade_app_get_clipboard_view ();
-
-	g_signal_connect (G_OBJECT (view), "delete_event",
-			  G_CALLBACK (gpw_hide_clipboard_view_on_delete),
-			  gpw->priv->ui);
-}
-
 static void
-gpw_show_clipboard_view (GladeProjectWindow *gpw)
+gpw_create_console (GladeProjectWindow *gpw)
 {
-	static gboolean created = FALSE;
+	GtkWidget *console, *notebook;
+	GList *list, *l;
 	
 	g_return_if_fail (gpw != NULL);
 
-	if (!created)
+	gpw->priv->console = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+	gtk_window_set_title (GTK_WINDOW (gpw->priv->console),
+			      _("Glade's Script-do Console"));
+	gtk_window_set_resizable (GTK_WINDOW (gpw->priv->console), TRUE);
+	gtk_widget_set_size_request (gpw->priv->console, 640, 480);
+	
+	notebook = gtk_notebook_new ();
+	gtk_container_add (GTK_CONTAINER (gpw->priv->console), notebook);
+	gtk_widget_show (notebook);
+	
+	for (list = l = glade_binding_get_all(); l && l->data; l = g_list_next (l))
 	{
-		gpw_create_clipboard_view (gpw);
-		created = TRUE;
+		GladeBinding *binding = l->data;
+		
+		if ((console = glade_binding_console_new (binding)))
+		{
+			gtk_notebook_append_page (GTK_NOTEBOOK (notebook), console,
+						  gtk_label_new (binding->name));
+			gtk_widget_show (console);
+		}
 	}
-	
-	gtk_widget_show_all (GTK_WIDGET (glade_app_get_clipboard_view ()));
-        gtk_window_present (GTK_WINDOW (glade_app_get_clipboard_view ()));
+
+	if (list == NULL)
+		gtk_widget_set_sensitive (gtk_ui_manager_get_widget 
+					  (gpw->priv->ui, "/MenuBar/ViewMenu/Console"),
+					  FALSE);
+
+	g_list_free (list);
+	
+	/* Delete event, don't destroy it */
+	g_signal_connect (gpw->priv->console, "delete_event",
+			  G_CALLBACK (gpw_hide_window_on_delete), gpw->priv->ui);
+}
+
+static void
+gpw_doc_search_cb (GladeEditor        *editor,
+		   const gchar        *book,
+		   const gchar        *page,
+		   const gchar        *search,
+		   GladeProjectWindow *gpw)
+{
+	glade_util_search_devhelp (book, page, search);
 }
 
 static void
@@ -1093,6 +1109,18 @@ gpw_notebook_switch_page_cb (GtkNotebook
 }
 
 static void
+gpw_show_console_cb (GtkAction *action, GladeProjectWindow *gpw)
+{
+	g_return_if_fail (gpw != NULL);
+
+	if (gpw->priv->console == NULL)	gpw_create_console (gpw);
+
+	gtk_widget_show (gpw->priv->console);
+
+	gtk_window_present (GTK_WINDOW (gpw->priv->console));
+}
+
+static void
 gpw_notebook_tab_added_cb (GtkNotebook *notebook,
 			   GladeDesignView *view,
 			   guint page_num,
@@ -1211,7 +1239,20 @@ gpw_palette_toggle_small_icons_cb (GtkAc
 static void
 gpw_show_clipboard_cb (GtkAction *action, GladeProjectWindow *gpw)
 {
-	gpw_show_clipboard_view (gpw);
+	static GtkWidget *view = NULL;
+	
+	g_return_if_fail (gpw != NULL);
+
+	if (view == NULL)
+	{
+		view = glade_app_get_clipboard_view ();
+
+		g_signal_connect (view, "delete_event",
+				  G_CALLBACK (gpw_hide_window_on_delete),
+				  gpw->priv->ui);
+	}
+	
+        gtk_window_present (GTK_WINDOW (view));
 }
 
 static void
@@ -1336,6 +1377,7 @@ static const gchar *ui_info =
 "    </menu>\n"
 "    <menu action='ViewMenu'>\n"
 "      <menuitem action='Clipboard'/>\n"
+"      <menuitem action='Console'/>\n"
 "      <separator/>\n"
 "      <menu action='PaletteAppearance'>\n"
 "        <menuitem action='IconsAndLabels'/>\n"
@@ -1439,7 +1481,11 @@ static GtkActionEntry project_entries[] 
 	{ "Clipboard", NULL, N_("_Clipboard"), NULL,
 	  N_("Show the clipboard"),
 	  G_CALLBACK (gpw_show_clipboard_cb) },
-
+	  
+	{ "Console", NULL, N_("C_onsole"), NULL,
+	  N_("Show Script-do console"),
+	  G_CALLBACK (gpw_show_console_cb) },
+	  
 	/* ProjectsMenu */
 	{ "PreviousProject", NULL, N_("_Previous Project"), "<control>Page_Up",
 	  N_("Activate previous project"), G_CALLBACK (glade_project_window_previous_project_cb) },
Index: src/glade-python.c
===================================================================
RCS file: src/glade-python.c
diff -N src/glade-python.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/glade-python.c	7 Nov 2006 19:56:02 -0000
@@ -0,0 +1,458 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Juan Pablo Ugarte.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Authors:
+ *   Juan Pablo Ugarte <juanpablougarte@gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Python.h>
+#include <pygobject.h>
+#include <glade.h>
+#include <glade-binding.h>
+
+GtkTextBuffer *buffer = NULL;
+static 	PyObject *glade, *GladeError, *GladeStdout, *GladeStderr;
+
+static PyObject *
+glade_python_undo (PyObject *self, PyObject *args)
+{
+	glade_app_command_undo ();
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+glade_python_redo (PyObject *self, PyObject *args)
+{
+	glade_app_command_redo ();
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+glade_python_project_new (PyObject *self, PyObject *args)
+{	
+	glade_app_add_project (glade_project_new (TRUE));
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+glade_python_project_open (PyObject *self, PyObject *args)
+{
+	gchar *path;
+	
+	Py_INCREF(Py_None);
+	
+	if (PyArg_ParseTuple(args, "s", &path))
+	{
+		GladeProject *project;
+		
+		if ((project = glade_app_get_project_by_path (path)))
+			glade_app_set_project (project);
+		else if ((project = glade_project_open (path)))
+			glade_app_add_project (project);
+		else
+			return Py_None;
+	}
+	
+	return Py_None;
+}
+
+static PyObject *
+glade_python_project_save (PyObject *self, PyObject *args)
+{
+	gchar *path;
+	
+	if (PyArg_ParseTuple(args, "s", &path))
+		glade_project_save (glade_app_get_project (), path, NULL);
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+glade_python_project_close (PyObject *self, PyObject *args)
+{
+
+	gchar *name;
+	
+	if (PyArg_ParseTuple(args, "s", &name))
+	{
+		GladeProject *project = glade_app_get_project_by_name (name);
+		if (project) glade_app_remove_project (project);
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+glade_python_project_get (PyObject *self, PyObject *args)
+{
+	GladeProject *project = glade_app_get_project ();
+	return Py_BuildValue ("s", (project) ? project->name : "");
+}
+
+static PyObject *
+glade_python_project_list (PyObject *self, PyObject *args)
+{
+	GList *p, *projects = glade_app_get_projects ();
+	PyObject *list;
+	
+	list = PyList_New (0);
+	
+	for (p = projects; p && p->data; p = g_list_next (p))
+	{
+		GladeProject *project = p->data;
+		PyList_Append (list, Py_BuildValue ("s", project->name));
+	}
+	
+	return list;
+}
+
+static PyObject *
+glade_python_project_set (PyObject *self, PyObject *args)
+{
+	gchar *name;
+	
+	if (PyArg_ParseTuple(args, "s", &name))
+	{
+		GladeProject *project = glade_app_get_project_by_name (name);
+		if (project) glade_app_set_project (project);
+	}
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+glade_python_widget_new (PyObject *self, PyObject *args)
+{
+	GladeProject *project = glade_app_get_project ();
+	GladeWidgetAdaptor *adaptor; 
+	GladeWidget *widget = NULL;
+	gchar *class_name, *parent;
+
+	if (project && PyArg_ParseTuple(args, "ss", &class_name, &parent) &&
+	    (adaptor = glade_widget_adaptor_get_by_name (class_name)))
+		widget = glade_command_create (adaptor,
+				glade_project_get_widget_by_name (project, parent),
+				NULL, project);
+	
+	return Py_BuildValue ("s", (widget) ? widget->name : "");
+}
+
+static PyObject *
+glade_python_widget_delete (PyObject *self, PyObject *args)
+{
+	GladeProject *project = glade_app_get_project ();
+	gchar *name;
+	
+	if (project && PyArg_ParseTuple(args, "s", &name))
+	{
+		GladeWidget *widget;
+		if ((widget = glade_project_get_widget_by_name (project, name)))
+		{
+			GList list;
+			list.data = widget;
+			list.next = list.prev = NULL;
+			glade_command_delete (&list);
+		}
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+glade_python_widget_set (PyObject *self, PyObject *args)
+{
+	GladeProject *project = glade_app_get_project ();
+	gchar *name, *id_property;
+	PyObject *val;
+	
+	if (project && PyArg_ParseTuple(args, "ssO", &name, &id_property, &val))
+	{
+		GladeWidget *widget;
+		GladeProperty *property;
+
+		if ((widget = glade_project_get_widget_by_name (project, name)) &&
+		    (property = glade_widget_get_property (widget, id_property)))
+		{
+			GValue value = {0,};
+			g_value_init (&value, G_VALUE_TYPE (property->value));
+			if (pyg_value_from_pyobject (&value, val) == 0)
+				glade_command_set_property_value (property, &value);
+		}
+	}
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+glade_python_widget_get (PyObject *self, PyObject *args)
+{
+	GladeProject *project = glade_app_get_project ();
+	gchar *name, *id_property;
+	
+	if (project && PyArg_ParseTuple(args, "ss", &name, &id_property))
+	{
+		GladeWidget *widget;
+		GladeProperty *property;
+
+		if ((widget = glade_project_get_widget_by_name (project, name)) &&
+		    (property = glade_widget_get_property (widget, id_property)))
+			return pyg_value_as_pyobject (property->value, TRUE);
+	}
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMethodDef GladeMethods[] = {
+    {"undo",  glade_python_undo, METH_VARARGS, "Execute undo command."},
+    {"redo",  glade_python_redo, METH_VARARGS, "Execute redo command."},
+    {"project_new",  glade_python_project_new, METH_VARARGS, "Create a new project."},
+    {"project_open",  glade_python_project_open, METH_VARARGS, "Open an existing project."},
+    {"project_save",  glade_python_project_save, METH_VARARGS, "Save the current project."},
+    {"project_close",  glade_python_project_close, METH_VARARGS, "Close the current project."},
+    {"project_get",  glade_python_project_get, METH_VARARGS, "Get the current project."},
+    {"project_set",  glade_python_project_set, METH_VARARGS, "Set the current project."},
+    {"project_list",  glade_python_project_list, METH_VARARGS, "List all projects."},
+    {"widget_new",  glade_python_widget_new, METH_VARARGS, "Create a new GtkWidget."},
+    {"widget_delete",  glade_python_widget_delete, METH_VARARGS, "Delete a GtkWidget."},
+    {"widget_set",  glade_python_widget_set, METH_VARARGS, "Set a GtkWidget's property."},
+    {"widget_get",  glade_python_widget_get, METH_VARARGS, "Get a GtkWidget's property."},
+    {NULL, NULL, 0, NULL}
+};
+/*
+widget_list
+container_get_children
+*/
+
+/* GladeStdout GladeStderr write method */
+static PyObject *
+glade_python_std_write (PyObject *self, PyObject *args, gboolean stdout)
+{
+	gchar *string;
+	
+	if (PyArg_ParseTuple(args, "s", &string))
+	{
+		GtkTextIter iter;
+		gtk_text_buffer_get_end_iter (buffer, &iter);
+		if (stdout)
+			gtk_text_buffer_insert (buffer, &iter, string, -1);
+		else
+			gtk_text_buffer_insert_with_tags_by_name (buffer, 
+				&iter, string, -1, "red_foreground", NULL);
+	}
+	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+/* GladeStdout methods */
+static PyObject *
+glade_python_stdout_write (PyObject *self, PyObject *args)
+{
+	return glade_python_std_write (self, args, TRUE);
+}
+
+static PyObject *
+glade_python_get_stdout (PyObject *self, PyObject *args)
+{
+	return GladeStdout;
+}
+
+static PyMethodDef GladeStdoutMethods[] = {
+    {"write",  glade_python_stdout_write, METH_VARARGS, NULL},
+    {"get_object",  glade_python_get_stdout, METH_VARARGS, NULL},
+    {NULL, NULL, 0, NULL}
+};
+
+/* GladeStderr methods */
+static PyObject *
+glade_python_stderr_write (PyObject *self, PyObject *args)
+{
+	return glade_python_std_write (self, args, FALSE);
+}
+
+static PyObject *
+glade_python_get_stderr (PyObject *self, PyObject *args)
+{
+	return GladeStderr;
+}
+
+static PyMethodDef GladeStderrMethods[] = {
+    {"write",  glade_python_stderr_write, METH_VARARGS, NULL},
+    {"get_object",  glade_python_get_stderr, METH_VARARGS, NULL},
+    {NULL, NULL, 0, NULL}
+};
+
+/* Bindings */
+void 
+glade_python_import (gchar *library)
+{
+	gchar *str = g_strdup_printf ("import %s", library);
+	PyRun_SimpleString (str);
+	g_free (str);
+}
+
+void 
+glade_python_run_function (gchar *func)
+{
+	gchar *str = g_strdup_printf ("%s();", func);
+	PyRun_SimpleString (str);
+	g_free (str);
+}
+
+static void
+glage_guile_console_entry_activate (GtkEntry *entry, GtkTextView *textview)
+{
+	const gchar *command = gtk_entry_get_text (entry);
+	GtkTextIter iter;
+	
+	gtk_text_buffer_get_end_iter (buffer, &iter);
+	gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, ">>> ", -1,
+						  "blue_foreground", NULL);
+	gtk_text_buffer_get_end_iter (buffer, &iter);
+	gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, command, -1,
+						  "blue_foreground", NULL);
+	gtk_text_buffer_get_end_iter (buffer, &iter);
+	gtk_text_buffer_insert (buffer, &iter, "\n", -1);
+	
+	if (PyRun_SimpleString (command) == 0) gtk_entry_set_text (entry, "");
+
+	/* agregar esto en una funcion idle!!! */
+	gtk_text_buffer_get_end_iter (buffer, &iter);
+	gtk_text_view_scroll_to_iter (textview, &iter, 0.0, TRUE, 0.0, 1.0);
+}
+
+GtkWidget *
+glade_python_console_new (void)
+{
+	GtkWidget *vbox, *hbox, *textview, *label, *entry, *sw;
+	
+	vbox = gtk_vbox_new (FALSE, 4);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox),
+					GLADE_GENERIC_BORDER_WIDTH);
+	
+	sw = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+					     GTK_SHADOW_ETCHED_IN);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+					GTK_POLICY_AUTOMATIC,
+					GTK_POLICY_AUTOMATIC);
+	gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
+	
+	textview = gtk_text_view_new_with_buffer (buffer);
+	gtk_text_view_set_editable (GTK_TEXT_VIEW (textview), FALSE);
+	gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (textview), FALSE);
+	gtk_container_add (GTK_CONTAINER (sw), textview);
+	
+	hbox = gtk_hbox_new (FALSE, 4);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+	
+	label = gtk_label_new (">>>");
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+	
+	entry = gtk_entry_new ();
+	g_signal_connect (entry, "activate", 
+			  G_CALLBACK (glage_guile_console_entry_activate),
+			  GTK_TEXT_VIEW (textview));
+	gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+	
+	gtk_widget_show (textview);
+	gtk_widget_show (label);
+	gtk_widget_show (entry);
+	gtk_widget_show (hbox);
+	gtk_widget_show (sw);
+
+	return vbox;
+}
+
+gint
+glade_python_run_file (gchar *path)
+{
+	FILE *fp = fopen (path, "r");
+	gint retval;
+	
+	if (fp == NULL) return -1;
+	
+	retval = PyRun_SimpleFile (fp, path);
+	fclose (fp);
+	
+	return retval;
+}
+
+void
+glade_binding_init (GladeBinding *binding)
+{
+	GtkTextIter iter;
+		
+	if (buffer == NULL)
+	{	
+		buffer = gtk_text_buffer_new (NULL);
+		gtk_text_buffer_create_tag (buffer, "blue_foreground",
+					    "foreground", "blue", NULL);  
+		gtk_text_buffer_create_tag (buffer, "red_foreground",
+					    "foreground", "red", NULL);  
+	}
+	else return;		
+	
+    	Py_SetProgramName (PACKAGE_NAME);
+	
+    	/* Initialize the Python interpreter if it is not */
+	if (Py_IsInitialized() == FALSE)
+	{
+		char *argv[2] = {"", NULL};
+		Py_Initialize ();
+		PySys_SetArgv (1, &argv);
+		init_pygobject ();
+	}
+
+	glade = Py_InitModule ("glade", GladeMethods);
+	GladeError = PyErr_NewException ("glade.error", NULL, NULL);
+	Py_INCREF (GladeError);
+	PyModule_AddObject (glade, "error", GladeError);
+	
+	GladeStdout = Py_InitModule ("glade_stdout", GladeStdoutMethods);
+	GladeStderr = Py_InitModule ("glade_stderr", GladeStderrMethods);
+	
+	PyRun_SimpleString ("import sys; import glade; import glade_stdout; import glade_stderr; sys.stdout=glade_stdout.get_object(); sys.stderr=glade_stderr.get_object(); sys.path+=\".\";");
+
+	gtk_text_buffer_get_end_iter (buffer, &iter);
+	gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, ">>> import sys;\n>>> import glade;\n", -1,
+						  "blue_foreground", NULL);
+	
+	/* Setup GladeBinding members */
+	binding->name = g_strdup ("python");
+	binding->console_new = glade_python_console_new;
+	binding->library_load = glade_python_import;
+	binding->library_init = glade_python_run_function;
+	binding->run_script = glade_python_run_file;
+}
Index: src/glade-utils.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-utils.c,v
retrieving revision 1.98
diff -u -u -p -r1.98 glade-utils.c
--- src/glade-utils.c	19 Oct 2006 17:15:09 -0000	1.98
+++ src/glade-utils.c	7 Nov 2006 19:56:08 -0000
@@ -139,8 +139,9 @@ glade_util_get_type_from_name (const gch
 	GType (*get_type) ();
 	GType type = 0;
 	gchar  *func_name;
-
-	if ((func_name = glade_util_compose_get_type_func (name)) != NULL)
+	
+	if ((type = g_type_from_name (name)) == 0 &&
+	    (func_name = glade_util_compose_get_type_func (name)) != NULL)
 	{
 		
 		if (!allsymbols)
@@ -151,17 +152,17 @@ glade_util_get_type_from_name (const gch
 		{
 			g_assert (get_type);
 			type = get_type ();
-		} else {
+		}
+		else
+		{
 			g_warning (_("We could not find the symbol \"%s\""),
 				   func_name);
 		}
 		g_free (func_name);
 	}
 
-	if (type == 0) {
-		g_warning(_("Could not get the type from \"%s"),
-			  name);
-	}
+	if (type == 0)
+		g_warning(_("Could not get the type from \"%s\""), name);
 	
 	return type;
 }
Index: src/glade-widget-adaptor.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-widget-adaptor.c,v
retrieving revision 1.2
diff -u -u -p -r1.2 glade-widget-adaptor.c
--- src/glade-widget-adaptor.c	20 Oct 2006 17:01:24 -0000	1.2
+++ src/glade-widget-adaptor.c	7 Nov 2006 19:56:12 -0000
@@ -40,6 +40,7 @@
 #include "glade-xml-utils.h"
 #include "glade-property-class.h"
 #include "glade-signal.h"
+#include "glade-marshallers.h"
 
 struct _GladeWidgetAdaptorPriv {
 
@@ -55,13 +56,6 @@ struct _GladeWidgetAdaptorPriv {
 
 	GdkCursor   *cursor;       /* a cursor for inserting widgets */
 
-
-	GModule     *module;	   /* Module with the (optional) special functions
-				    * needed for placeholder_replace, post_create_function
-				    * and the set & get functions of the properties
-				    * of this class.
-				    */
-				 
 	gchar       *special_child_type; /* Special case code for children that
 					  * are special children (like notebook tab 
 					  * widgets for example).
@@ -87,13 +81,18 @@ enum {
 	PROP_CURSOR
 };
 
+enum {
+	SIGNAL_ACTION_ACTIVATED,
+	LAST_SIGNAL
+};
+static guint gwa_signals [LAST_SIGNAL] = { 0 };
+
 typedef struct _GladeChildPacking GladeChildPacking;
 
 
 static GObjectClass *parent_class = NULL;
 static GHashTable   *adaptor_hash = NULL;
 
-
 /*******************************************************************************
                               Helper functions
  *******************************************************************************/
@@ -531,6 +530,45 @@ gwa_inherit_child_packing (GladeWidgetAd
 	return child_packings;
 }
 
+static GList *
+gwa_action_copy (GList *src)
+{
+	GList *l, *list = NULL;
+	
+	for (l = src; l; l = g_list_next (l))
+	{
+		GladeAction *action = l->data, *copy = g_new0 (GladeAction, 1);
+	
+		copy->id = g_strdup (action->id);
+		copy->label = g_strdup (action->label);
+		copy->use_stock = action->use_stock;
+		copy->is_a_group = action->is_a_group;
+		
+		list = g_list_append (list, l->data);
+		
+		if (action->actions)
+			copy->actions = gwa_action_copy (action->actions);
+	}
+	
+	return list;
+}
+
+static void
+gwa_action_setup (GladeWidgetAdaptor *adaptor)
+{
+	GladeWidgetAdaptor *parent = NULL;
+	GType type = g_type_parent (adaptor->type);
+	
+	/* Get adaptor's parent */
+	while ((type = g_type_parent (type)))
+		if ((parent = glade_widget_adaptor_get_by_type (type))) break;
+	
+	if (parent && parent->actions)
+		adaptor->actions = gwa_action_copy (parent->actions);
+	else
+		adaptor->actions = NULL;
+}
+
 static GObject *
 glade_widget_adaptor_constructor (GType                  type,
 				  guint                  n_construct_properties,
@@ -561,6 +599,8 @@ glade_widget_adaptor_constructor (GType 
 	/* Inherit packing defaults here */
 	adaptor->child_packings = gwa_inherit_child_packing (adaptor);
 
+	gwa_action_setup (adaptor);
+	
 	return ret_obj;
 }
 
@@ -608,11 +648,6 @@ glade_widget_adaptor_finalize (GObject *
 	if (adaptor->priv->special_child_type)
 		g_free (adaptor->priv->special_child_type);
 
-	if (adaptor->priv->module)
-		if (!g_module_close (adaptor->priv->module))
-			g_warning ("Module error while finalizing adaptor %s (%s)\n",
-				   adaptor->name, g_module_error());
-
 	if (adaptor->priv->cursor != NULL)
 		gdk_cursor_unref (adaptor->priv->cursor);
 
@@ -739,6 +774,18 @@ glade_widget_adaptor_class_init (GladeWi
 	adaptor_class->child_set_property   = NULL;
 	adaptor_class->child_get_property   = NULL;
 
+	
+	/* Signals */
+	gwa_signals [SIGNAL_ACTION_ACTIVATED] =
+		g_signal_new ("action-activated",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+			      G_STRUCT_OFFSET (GladeWidgetAdaptorClass,
+					       action_activated),
+			      NULL, NULL,
+			      glade_marshal_VOID__OBJECT,
+			      G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
 	/* Properties */
 	g_object_class_install_property 
 		(object_class, PROP_NAME,
@@ -1047,6 +1094,7 @@ gwa_set_packing_defaults_from_node (Glad
 static void
 gwa_update_properties_from_node (GladeWidgetAdaptor  *adaptor,
 				 GladeXmlNode        *node,
+				 GModule             *module,
 				 GList              **properties,
 				 const gchar         *domain)
 {
@@ -1093,7 +1141,7 @@ gwa_update_properties_from_node (GladeWi
 		}
 
 		if ((updated = glade_property_class_update_from_node
-		     (child, adaptor->priv->module, adaptor->type,
+		     (child, module, adaptor->type,
 		      &property_class, domain)) == FALSE)
 		{
 			g_warning ("failed to update %s property of %s from xml",
@@ -1114,47 +1162,48 @@ gwa_update_properties_from_node (GladeWi
 static gboolean
 gwa_extend_with_node (GladeWidgetAdaptor *adaptor, 
 		      GladeXmlNode       *node,
+		      GModule            *module,
 		      const gchar        *domain)
 {
 	GladeWidgetAdaptorClass *adaptor_class = 
 		GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor);
 	GladeXmlNode *child;
 
-	if (adaptor->priv->module)
+	if (module)
 	{
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_POST_CREATE_FUNCTION,
 					      (gpointer *)&adaptor_class->post_create);
 
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_GET_INTERNAL_CHILD_FUNCTION,
 					      (gpointer *)&adaptor_class->get_internal_child);
 
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_LAUNCH_EDITOR_FUNCTION,
 					      (gpointer *)&adaptor_class->launch_editor);
 
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_ADD_CHILD_FUNCTION,
 					      (gpointer *)&adaptor_class->add);
 
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_REMOVE_CHILD_FUNCTION,
 					      (gpointer *)&adaptor_class->remove);
 
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_GET_CHILDREN_FUNCTION,
 					      (gpointer *)&adaptor_class->get_children);
 
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_CHILD_SET_PROP_FUNCTION,
 					      (gpointer *)&adaptor_class->child_set_property);
 
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_CHILD_GET_PROP_FUNCTION,
 					      (gpointer *)&adaptor_class->child_get_property);
 
-		glade_xml_load_sym_from_node (node, adaptor->priv->module,
+		glade_xml_load_sym_from_node (node, module,
 					      GLADE_TAG_REPLACE_CHILD_FUNCTION,
 					      (gpointer *)&adaptor_class->replace_child);
 
@@ -1174,12 +1223,12 @@ gwa_extend_with_node (GladeWidgetAdaptor
 	if ((child = 
 	     glade_xml_search_child (node, GLADE_TAG_PROPERTIES)) != NULL)
 		gwa_update_properties_from_node
-			(adaptor, child, &adaptor->properties, domain);
+			(adaptor, child, module, &adaptor->properties, domain);
 
 	if ((child = 
 	     glade_xml_search_child (node, GLADE_TAG_PACKING_PROPERTIES)) != NULL)
 		gwa_update_properties_from_node
-			(adaptor, child, &adaptor->packing_props, domain);
+			(adaptor, child, module, &adaptor->packing_props, domain);
 
 	if ((child = 
 	     glade_xml_search_child (node, GLADE_TAG_PACKING_DEFAULTS)) != NULL)
@@ -1206,13 +1255,12 @@ gwa_extend_with_node (GladeWidgetAdaptor
 GladeWidgetAdaptor *
 glade_widget_adaptor_from_catalog (GladeXmlNode     *class_node,
 				   const gchar      *catname,
-				   const gchar      *library,
+				   GModule          *module,
 				   const gchar      *domain,
 				   const gchar      *book)
 {
 	GladeWidgetAdaptor *adaptor = NULL;
 	gchar              *name, *generic_name;
-	GModule            *module = NULL;
 	GType               object_type, adaptor_type, parent_type;
 
 	if (!glade_xml_node_verify (class_node, GLADE_TAG_GLADE_WIDGET_CLASS))
@@ -1226,18 +1274,6 @@ glade_widget_adaptor_from_catalog (Glade
 	     (class_node, GLADE_TAG_NAME, NULL)) == NULL)
 		return NULL;
 
-	if (library) 
-	{
-		module = glade_util_load_library (library);
-		if (!module)
-		{
-			g_warning ("Failed to load external library '%s'",
-				   library);
-			g_free (name);
-			return NULL;
-		}
-	}
-
 	if ((object_type = glade_util_get_type_from_name (name)) == 0)
 	{
 		g_warning ("Failed to load the GType for '%s'", name);
@@ -1261,8 +1297,6 @@ glade_widget_adaptor_from_catalog (Glade
 				     NULL);
 	if (generic_name)
 		g_free (generic_name);
-
-	adaptor->priv->module = module;
 	
 	if ((adaptor->title = glade_xml_get_property_string_required
 	     (class_node, GLADE_TAG_TITLE,
@@ -1299,7 +1333,7 @@ glade_widget_adaptor_from_catalog (Glade
 	if (book)
 		adaptor->priv->book = g_strdup (book);
 
-	gwa_extend_with_node (adaptor, class_node, domain);
+	gwa_extend_with_node (adaptor, class_node, module, domain);
 
 	/* Set default weight on properties */
 	for (parent_type = adaptor->type;
@@ -1313,9 +1347,6 @@ glade_widget_adaptor_from_catalog (Glade
 	glade_widget_adaptor_register (adaptor);
 
 	return adaptor;
-
-
-
 }
 
 /**
@@ -1947,4 +1978,215 @@ glade_widget_adaptor_get_packing_default
 		}
 	}
 	return NULL;
+}
+
+struct AdaptorData
+{
+	GList *list;
+	GType type;
+};
+
+static void
+glade_widget_adaptor_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+	GladeWidgetAdaptor *adaptor = value;
+	struct AdaptorData *adata = user_data;
+	
+	if (g_type_is_a (adaptor->type, adata->type));
+		adata->list = g_list_prepend (adata->list, adaptor);
+}
+
+/**
+ * glade_widget_adaptor_get_derived_adaptors:
+ *
+ * @type: An object type.
+ *
+ * List all GladeWidgetAdaptor derived from @type.
+ *
+ * Returns: a newly created GList.
+ */
+GList *
+glade_widget_adaptor_get_derived_adaptors (GType type)
+{
+	struct AdaptorData data;
+	
+	data.list = NULL;
+	data.type = type;
+	
+	g_hash_table_foreach (adaptor_hash, glade_widget_adaptor_foreach, &data);
+	return data.list;
+}
+
+static GList **
+gwa_action_lookup (GList **actions, const gchar *id, gboolean only_group)
+{
+	GList **group = actions, *l;
+	
+	for (l = *actions; l; l = g_list_next (l))
+	{
+		GladeAction *action = l->data;
+		
+		if (only_group && action->is_a_group == FALSE) continue;
+		
+		if (strcmp (action->id, id) == 0)
+			return (only_group) ? &action->actions : group;
+			
+		if (action->is_a_group && action->actions &&
+		    (group = gwa_action_lookup (&action->actions, id, only_group)))
+			return group;
+	}
+	
+	return NULL;
+}
+
+static gboolean
+gwa_action_append (GladeWidgetAdaptor *adaptor,
+		   const gchar *group_id,
+		   const gchar *id,
+		   const gchar *label,
+		   gboolean use_stock,
+		   gboolean is_a_group)
+{
+	GList **group, *l, *children;
+	gboolean check = FALSE;
+	
+	g_return_val_if_fail (id != NULL, FALSE);
+	
+	/* Get all derived adaptors */
+	children = glade_widget_adaptor_get_derived_adaptors (adaptor->type);
+	
+	/* Check we can add the this action to every derived adaptor */
+	for (l = children; l; l = g_list_next (l))
+	{
+		GladeWidgetAdaptor *child = l->data;
+
+		if (group_id &&
+		    gwa_action_lookup (&child->actions, group_id, TRUE) == NULL)
+		{
+			check = TRUE;
+			break;
+		}
+
+		if (gwa_action_lookup (&child->actions, id, FALSE))
+		{
+			check = TRUE;
+			break;
+		}
+	}
+
+	if (check)
+	{
+		g_list_free (children);
+		return FALSE;
+	}
+	
+	/* Add this action to every adaptor */
+	for (l = children; l; l = g_list_next (l))
+	{
+		GladeWidgetAdaptor *child = l->data;
+		GladeAction *action;
+		
+		if (group_id)
+		{
+			group = gwa_action_lookup (&child->actions, group_id, TRUE);
+			g_assert (group != NULL);
+		}
+		else
+		{
+			group = &child->actions;
+		}
+		
+		g_assert (gwa_action_lookup (&child->actions, id, FALSE) == FALSE);
+			
+		action = g_new0 (GladeAction, 1);
+		action->id = g_strdup (id);
+		action->label = g_strdup (label);
+		action->use_stock = use_stock;
+		action->is_a_group = is_a_group;	
+		
+		*group = g_list_append (*group, action);
+	}
+	
+	g_list_free (children);
+	
+	return TRUE;
+}
+
+/**
+ * glade_widget_adaptor_action_add_group:
+ *
+ * @adaptor: the GladeWidgetAdaptor.
+ * @group: the group id or NULL.
+ * @id: the action id.
+ * @label: the action label.
+ *
+ * Adds a group of actions.
+ *
+ * Returns whether the group was added or not.
+ */
+gboolean
+glade_widget_adaptor_action_add_group (GladeWidgetAdaptor *adaptor,
+				       const gchar *group_id,
+				       const gchar *id,
+				       const gchar *label)
+{
+	return gwa_action_append (adaptor, group_id, id, label, FALSE, TRUE);
+}
+
+/**
+ * glade_widget_adaptor_action_add:
+ *
+ * @adaptor: the GladeWidgetAdaptor.
+ * @group: A group id or NULL.
+ * @id: The action id (detail of GladeWidgetAdaptor's action-activated signal).
+ * @label: The action label.
+ * @use_stock: Weather to use a stock item or not.
+ *
+ * Adds an action item.
+ *
+ * Returns whether the action was added or not.
+ */
+gboolean
+glade_widget_adaptor_action_add (GladeWidgetAdaptor *adaptor,
+				 const gchar *group_id,
+				 const gchar *id,
+				 const gchar *label,
+				 gboolean use_stock)
+{
+	return gwa_action_append (adaptor, group_id, id, label, use_stock, FALSE);
+}
+
+/**
+ * glade_widget_adaptor_emit_detail_activated:
+ *
+ * @widget: the GladeWidgetAdaptor.
+ * @detail: The action id (detail of GladeWidgetAdaptor's action-activated signal).
+ *
+ * Emit @widget's adaptor action-activated::@detail signal.
+ *
+ */
+void
+glade_widget_adaptor_emit_action_activated (GladeWidget *widget,
+					    const gchar *detail)
+{
+	GladeWidgetAdaptor *adaptor;
+	guint signal_id;
+	GQuark detailq;
+	GType type;
+		
+	g_return_if_fail (GLADE_IS_WIDGET (widget) && detail);
+	
+	signal_id = gwa_signals [SIGNAL_ACTION_ACTIVATED];
+	detailq = g_quark_from_string (detail);
+	
+	for (type = widget->adaptor->type; type; type = g_type_parent (type))
+	{
+		if ((adaptor = glade_widget_adaptor_get_by_type (type)))
+		{
+			if (gwa_action_lookup (&adaptor->actions, detail, FALSE))
+				g_signal_emit (adaptor, signal_id, detailq, widget);
+			else
+				return;
+		}
+	}
 }
Index: src/glade-widget-adaptor.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-widget-adaptor.h,v
retrieving revision 1.1
diff -u -u -p -r1.1 glade-widget-adaptor.h
--- src/glade-widget-adaptor.h	19 Oct 2006 17:15:09 -0000	1.1
+++ src/glade-widget-adaptor.h	7 Nov 2006 19:56:12 -0000
@@ -215,6 +215,14 @@ struct _GladeSignalClass
 
 };
 
+typedef struct _GladeAction GladeAction;
+struct _GladeAction
+{
+	gchar *id, *label;
+	gboolean use_stock, is_a_group;
+	GList *actions;
+};
+
 /* Note that everything that must be processed at the creation of
  * every instance is managed on the instance structure, and everywhere
  * that we want to take advantage of inheritance is handled in the class
@@ -255,6 +263,7 @@ struct _GladeWidgetAdaptor
 
         GList       *child_packings; /* Default packing property values */
 
+	GList       *actions;        /* A list of GladeAction */
 
 	GladeWidgetAdaptorPriv *priv;
 
@@ -296,6 +305,8 @@ struct _GladeWidgetAdaptorClass
 						    * replace a placeholder with
 						    * a widget and viceversa.
 						    */
+	/* Signals */
+	void                       (*action_activated) (GladeWidgetAdaptor *, GladeWidget *);
 };
 
 #define glade_widget_adaptor_create_widget(adaptor, query, ...) \
@@ -311,7 +322,7 @@ GType glade_widget_adaptor_get_type     
 LIBGLADEUI_API
 GladeWidgetAdaptor  *glade_widget_adaptor_from_catalog     (GladeXmlNode         *class_node,
 							    const gchar          *catname,
-							    const gchar          *library,
+							    GModule              *module,
 							    const gchar          *domain,
 							    const gchar          *book);
 LIBGLADEUI_API
@@ -396,7 +407,20 @@ LIBGLADEUI_API G_CONST_RETURN
 gchar               *glade_widget_adaptor_get_packing_default(GladeWidgetAdaptor *child_adaptor,
 							      GladeWidgetAdaptor *parent_adaptor,
 							      const gchar        *propert_id);
-
+LIBGLADEUI_API
+void                 glade_widget_adaptor_emit_action_activated (GladeWidget     *widget,
+							         const gchar     *detail);
+LIBGLADEUI_API
+gboolean             glade_widget_adaptor_action_add_group   (GladeWidgetAdaptor *adaptor,
+							      const gchar        *group_id,
+							      const gchar        *id,
+							      const gchar        *label);
+LIBGLADEUI_API
+gboolean             glade_widget_adaptor_action_add         (GladeWidgetAdaptor *adaptor,
+							      const gchar        *group_id,
+							      const gchar        *id,
+							      const gchar        *label,
+							      gboolean            use_stock);
 G_END_DECLS
 
 #endif /* __GLADE_WIDGET_ADAPTOR_H__ */
Index: src/glade.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade.h,v
retrieving revision 1.76
diff -u -u -p -r1.76 glade.h
--- src/glade.h	19 Oct 2006 17:15:09 -0000	1.76
+++ src/glade.h	7 Nov 2006 19:56:12 -0000
@@ -22,10 +22,6 @@
 # define LIBGLADEUI_API		extern
 #endif
 
-#ifdef GLADE_H
-# error libglade included with libgladeui is not compatible
-#endif
-
 /* Circular header dependancie are fixed here with forward 
  * declarations.
  */
@@ -90,6 +86,7 @@ typedef enum   _GladeItemAppearance Glad
 #define GLADE_TAG_GLADE_WIDGET_GROUP              "glade-widget-group"
 #define GLADE_TAG_GLADE_WIDGET_CLASS_REF          "glade-widget-class-ref"
 
+#define GLADE_TAG_LANGUAGE                        "language"
 #define GLADE_TAG_LIBRARY                         "library"
 #define GLADE_TAG_DEPENDS                         "depends"
 #define GLADE_TAG_DOMAIN                          "domain"
@@ -158,9 +155,11 @@ typedef enum   _GladeItemAppearance Glad
 LIBGLADEUI_API gboolean glade_verbose;
 
 LIBGLADEUI_API gchar* glade_pixmaps_dir;
+LIBGLADEUI_API gchar* glade_scripts_dir;
 LIBGLADEUI_API gchar* glade_catalogs_dir;
 LIBGLADEUI_API gchar* glade_modules_dir;
 LIBGLADEUI_API gchar* glade_plugins_dir;
+LIBGLADEUI_API gchar* glade_bindings_dir;
 LIBGLADEUI_API gchar* glade_locale_dir;
 LIBGLADEUI_API gchar* glade_icon_dir;
