Index: configure.in
===================================================================
RCS file: /cvs/gnome/glade3/configure.in,v
retrieving revision 1.73
diff -u -u -p -r1.73 configure.in
--- configure.in	29 Sep 2006 18:01:59 -0000	1.73
+++ configure.in	17 Oct 2006 17:12:12 -0000
@@ -57,6 +57,31 @@ AC_SUBST(GTK_LIBS)
 AC_SUBST(GTK_CFLAGS)
 
 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 optional gnome libs
 dnl ================================================================
 AC_ARG_ENABLE(gnome,
@@ -93,8 +118,10 @@ glade_datadir='${datadir}/${PACKAGE}'
 glade_libdir='${libdir}/${PACKAGE}'
 glade_catalogsdir='${glade_datadir}/catalogs'
 glade_pixmapsdir='${glade_datadir}/pixmaps'
+glade_scriptsdir='${glade_datadir}/script-do'
 glade_modulesdir='${glade_libdir}/modules'
 glade_pluginsdir='${glade_libdir}/plugins'
+glade_bindingsdir='${glade_libdir}/bindings'
 glade_icondir='${datadir}/pixmaps'
 glade_localedir='${prefix}/${DATADIRNAME}/locale'
 AC_SUBST(glade_version)
@@ -103,7 +130,9 @@ AC_SUBST(glade_libdir)
 AC_SUBST(glade_catalogsdir)
 AC_SUBST(glade_modulesdir)
 AC_SUBST(glade_pluginsdir)
+AC_SUBST(glade_bindingsdir)
 AC_SUBST(glade_pixmapsdir)
+AC_SUBST(glade_scriptsdir)
 AC_SUBST(glade_icondir)
 AC_SUBST(glade_localedir)
 
@@ -129,5 +158,6 @@ Configuration:
 	Source code location:	${srcdir}
 	Compiler:		${CC} 
 	GnomeUI Catalog:	${have_gnome}
+	Python Scripting:	${have_python}
 
 "
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/glade3/src/Makefile.am,v
retrieving revision 1.59
diff -u -u -p -r1.59 Makefile.am
--- src/Makefile.am	13 Jul 2006 21:38:19 -0000	1.59
+++ src/Makefile.am	17 Oct 2006 17:12:13 -0000
@@ -86,6 +86,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 =    \
@@ -141,6 +142,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)
@@ -156,6 +166,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.46
diff -u -u -p -r1.46 glade-app.c
--- src/glade-app.c	12 Aug 2006 01:34:00 -0000	1.46
+++ src/glade-app.c	17 Oct 2006 17:12:15 -0000
@@ -49,6 +49,7 @@
 #include "glade-app.h"
 #include "glade-paths.h"
 #include "glade-fixed.h"
+#include "glade-binding.h"
 
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtkstock.h>
@@ -94,8 +95,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;
@@ -164,8 +167,10 @@ 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
@@ -320,8 +325,10 @@ 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);
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	17 Oct 2006 17:12:15 -0000
@@ -0,0 +1,347 @@
+/* -*- 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_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_hash_table_lookup (binding->classes,
+							GINT_TO_POINTER (type));
+			
+			list = g_list_concat (old_list, list);
+			
+			g_hash_table_insert (binding->classes,
+					     GINT_TO_POINTER (type), list);
+		}
+		
+		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;
+				binding->classes = g_hash_table_new (g_int_hash, g_int_equal);
+				
+				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_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_remove (gpointer key, gpointer value, gpointer user_data)
+{
+	g_list_foreach (value, glade_binding_script_free, NULL);
+	g_list_free (value);
+}
+
+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_hash_table_foreach (binding->classes,
+				      glade_binding_classes_remove, NULL);
+	
+	g_free (binding);
+}
+
+/**
+ * glade_binding_unload_all:
+ *
+ * Finalize and unload every binding plugin.
+ *
+ */
+void
+glade_binding_unload_all ()
+{
+	if (bindings)
+		g_hash_table_foreach (bindings, glade_binding_remove, 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 ();
+}
+
+static GType script_type;
+static void
+glade_binding_script_get_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+	GList *list, **l = user_data;
+	GladeBinding *binding = value;
+	
+	if ((list = g_hash_table_lookup (binding->classes, 
+					 GINT_TO_POINTER (script_type))))
+		*l = g_list_concat (*l, g_list_copy (list));
+}
+
+/**
+ * glade_binding_script_get:
+ *
+ * @type:
+ *
+ * Returns a newly allocated list of GladeBindingScript for @type.
+ * Scripts can be placed in the folowing directories:
+ *  o package_installation/share/glade3/script-do/"binding name"/"widget class name"/
+ *  o g_get_user_config_dir()/glade3/script-do/"binding name"/"widget class name"/
+ *
+ */
+GList *
+glade_binding_script_get (GType type)
+{
+	GList *l = NULL;
+	script_type = type;
+	g_hash_table_foreach (bindings, glade_binding_script_get_foreach, &l);
+	return l;
+}
+
+/**
+ * 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;
+}
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	17 Oct 2006 17:12:15 -0000
@@ -0,0 +1,67 @@
+/* -*- 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__
+
+#define GLADE_BINDING_SCRIPT_DIR "script-do"
+
+typedef struct _GladeBinding GladeBinding ;
+struct _GladeBinding {
+	GModule  *module;
+	gchar    *name;
+	
+	GHashTable *classes;
+	
+	/* Module symbols */
+	void       (*finalize)(void);
+	void       (*library_load) (gchar *str);
+	void       (*library_init) (gchar *str);
+	GtkWidget *(*console_new)  (void);
+	gint       (*run_script)   (gchar *path);
+};
+
+typedef struct _GladeBindingScript GladeBindingScript ;
+struct _GladeBindingScript {
+	GladeBinding *binding;
+	gchar *name, *path;
+};
+
+void          glade_binding_load_all (void);
+
+void          glade_binding_unload_all (void);
+
+GladeBinding *glade_binding_get (gchar *name);
+
+GList        *glade_binding_get_all ();
+
+void          glade_binding_library_load (GladeBinding *binding, gchar *library);
+
+void          glade_binding_library_init (GladeBinding *binding, gchar *init);
+
+GtkWidget    *glade_binding_console_new (GladeBinding *binding);
+
+GList        *glade_binding_script_get (GType type);
+
+gint          glade_binding_run_script (GladeBinding *script, gchar *path);
+
+#endif
Index: src/glade-catalog.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-catalog.c,v
retrieving revision 1.37
diff -u -u -p -r1.37 glade-catalog.c
--- src/glade-catalog.c	5 Jul 2006 18:59:49 -0000	1.37
+++ src/glade-catalog.c	17 Oct 2006 17:12:16 -0000
@@ -36,11 +36,13 @@
 #include "glade.h"
 #include "glade-catalog.h"
 #include "glade-widget-class.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);
 
@@ -271,7 +275,8 @@ catalog_load_classes (GladeCatalog *cata
 			continue;
 	
 		widget_class = glade_widget_class_new 
-			(node, catalog->name, catalog->library, 
+			(node, catalog->name,
+			 catalog->language ? NULL : catalog->library,
 			 catalog->domain ? catalog->domain : catalog->library,
 			 catalog->book);
 
@@ -429,6 +434,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 ();
 	}
 	
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	17 Oct 2006 17:12:16 -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.35
diff -u -u -p -r1.35 glade-popup.c
--- src/glade-popup.c	12 Aug 2006 01:34:01 -0000	1.35
+++ src/glade-popup.c	17 Oct 2006 17:12:17 -0000
@@ -35,6 +35,7 @@
 #include "glade-command.h"
 #include "glade-project.h"
 #include "glade-app.h"
+#include "glade-binding.h"
 
 /********************************************************
                       WIDGET POPUP
@@ -118,6 +119,11 @@ glade_popup_add_item_cb (GtkMenuItem *it
 				      glade_app_get_project ());
 }
 
+static void
+glade_popup_script_activate_cb (GtkMenuItem *item, GladeBindingScript *script)
+{
+	glade_binding_run_script (script->binding, script->path);
+}
 
 /********************************************************
                   PLACEHOLDER POPUP
@@ -219,6 +225,36 @@ glade_popup_populate_childs (GtkWidget* 
 	}
 }
 
+void
+glade_popup_populate_scriptdo (GtkWidget* popup_menu, GladeWidget *widget)
+{
+	GtkWidget *child;
+	GtkWidget *child_menu;
+	GList *l, *scripts = glade_binding_script_get (G_OBJECT_TYPE (glade_widget_get_object (widget)));
+	
+	if (scripts == NULL) return;
+	
+	child = gtk_menu_item_new_with_label ("Script-do");
+	gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), child);
+	gtk_widget_show (child);
+	
+	child_menu = gtk_menu_new ();
+	gtk_menu_item_set_submenu (GTK_MENU_ITEM (child), child_menu);
+	
+	for (l = scripts; l; l = g_list_next (l))
+	{
+		GladeBindingScript *script = l->data;
+		
+		glade_popup_append_item (child_menu, NULL, script->name, TRUE,
+					 glade_popup_script_activate_cb, script);
+	}
+	
+	g_list_free (scripts);
+	
+	
+	gtk_widget_show (child_menu);
+}
+
 static void
 glade_popup_add_children (GtkWidget* popup_menu, GladeWidget *widget)
 {
@@ -294,6 +330,8 @@ glade_popup_create_menu (GladeWidget *wi
 		glade_popup_populate_childs(popup_menu, parent);
 	}
 
+	glade_popup_populate_scriptdo (popup_menu, widget);
+	
 	return popup_menu;
 }
 
Index: src/glade-project-window.c
===================================================================
RCS file: /cvs/gnome/glade3/src/glade-project-window.c,v
retrieving revision 1.167
diff -u -u -p -r1.167 glade-project-window.c
--- src/glade-project-window.c	1 Oct 2006 02:31:40 -0000	1.167
+++ src/glade-project-window.c	17 Oct 2006 17:12:22 -0000
@@ -34,6 +34,8 @@
 
 #include "glade-project-window.h"
 
+#include "glade-binding.h"
+
 #define CONFIG_RECENT_PROJECTS     "Recent Projects"
 #define CONFIG_RECENT_PROJECTS_MAX "max_recent_projects"
 
@@ -64,9 +66,9 @@ struct _GladeProjectWindowPriv {
 
 	GtkWindow *palette_window;     /* The window that will contain the palette */
 	GtkWindow *editor_window;      /* The window that will contain the editor */
+	GtkWindow *console;
 	GtkWidget *expand;             /* Expand/Collapse the treeview */
 	GtkWidget *collapse;
-
 };
 
 
@@ -935,9 +937,9 @@ gpw_redo_cb (GtkAction *action, GladePro
 }
 
 static gboolean
-gpw_hide_palette_on_delete (GtkWidget *palette, gpointer not_used, GtkUIManager *ui)
+gpw_hide_window_on_delete (GtkWidget *window, gpointer not_used, GtkUIManager *ui)
 {
-	glade_util_hide_window (GTK_WINDOW (palette));
+	glade_util_hide_window (GTK_WINDOW (window));
 	return TRUE;
 }
 
@@ -960,7 +962,7 @@ gpw_create_palette (GladeProjectWindow *
 
 	/* Delete event, don't destroy it */
 	g_signal_connect (G_OBJECT (gpw->priv->palette_window), "delete_event",
-			  G_CALLBACK (gpw_hide_palette_on_delete), gpw->priv->ui);
+			  G_CALLBACK (gpw_hide_window_on_delete), gpw->priv->ui);
 }
 
 static void
@@ -977,12 +979,59 @@ gpw_show_palette (GladeProjectWindow *gp
 		gtk_window_present (gpw->priv->palette_window);
 }
 
-static gboolean
-gpw_hide_editor_on_delete (GtkWidget *editor, gpointer not_used,
-		GtkUIManager *ui)
+static void
+gpw_create_console (GladeProjectWindow *gpw)
 {
-	glade_util_hide_window (GTK_WINDOW (editor));
-	return TRUE;
+	GtkWidget *console, *notebook;
+	GList *list, *l;
+	
+	g_return_if_fail (gpw != NULL);
+
+	gpw->priv->console = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
+
+	gtk_window_set_title (gpw->priv->console, _("Glade's Script-do Console"));
+	gtk_window_set_resizable (gpw->priv->console, TRUE);
+
+	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))
+	{
+		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);
+		}
+	}
+
+	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 (G_OBJECT (gpw->priv->console), "delete_event",
+			  G_CALLBACK (gpw_hide_window_on_delete), gpw->priv->ui);
+}
+
+static void
+gpw_show_console (GladeProjectWindow *gpw, gboolean raise)
+{
+	g_return_if_fail (gpw != NULL);
+
+	if (gpw->priv->console == NULL)
+		gpw_create_console (gpw);
+
+	gtk_widget_show (GTK_WIDGET (gpw->priv->console));
+
+	if (raise)
+		gtk_window_present (gpw->priv->console);
 }
 
 static gint
@@ -1030,7 +1079,7 @@ gpw_create_editor (GladeProjectWindow *g
 
 	/* Delete event, don't destroy it */
 	g_signal_connect (G_OBJECT (gpw->priv->editor_window), "delete_event",
-			  G_CALLBACK (gpw_hide_editor_on_delete), gpw->priv->ui);
+			  G_CALLBACK (gpw_hide_window_on_delete), gpw->priv->ui);
 
 	g_signal_connect (G_OBJECT (gpw->priv->editor_window), "key-press-event",
 			  G_CALLBACK (gpw_hijack_editor_key_press), gpw);
@@ -1112,14 +1161,6 @@ gpw_create_widget_tree_contents (GladePr
 	return vbox;
 }
 
-static gboolean
-gpw_hide_clipboard_view_on_delete (GtkWidget *clipboard_view, gpointer not_used,
-				   GtkUIManager *ui)
-{
-	glade_util_hide_window (GTK_WINDOW (clipboard_view));
-	return TRUE;
-}
-
 static void 
 gpw_create_clipboard_view (GladeProjectWindow *gpw)
 {
@@ -1128,7 +1169,7 @@ gpw_create_clipboard_view (GladeProjectW
 	view = glade_app_get_clipboard_view ();
 
 	g_signal_connect (G_OBJECT (view), "delete_event",
-			  G_CALLBACK (gpw_hide_clipboard_view_on_delete),
+			  G_CALLBACK (gpw_hide_window_on_delete),
 			  gpw->priv->ui);
 }
 
@@ -1179,6 +1220,12 @@ gpw_show_palette_cb (GtkAction *action, 
 }
 
 static void
+gpw_show_console_cb (GtkAction *action, GladeProjectWindow *gpw)
+{
+	gpw_show_console (gpw, TRUE);
+}
+
+static void
 gpw_show_editor_cb (GtkAction *action, GladeProjectWindow *gpw)
 {
 	gpw_show_editor (GLADE_APP (gpw), TRUE);
@@ -1361,6 +1408,7 @@ static const gchar *ui_info =
 "      <menuitem action='PropertyEditor'/>\n"
 "      <menuitem action='Clipboard'/>\n"
 "      <menuitem action='Palette'/>\n"
+"      <menuitem action='Console'/>\n"
 "      <separator/>\n"
 "      <menu action='PaletteAppearance'>\n"
 "        <menuitem action='IconsAndLabels'/>\n"
@@ -1470,7 +1518,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_prev_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	17 Oct 2006 17:12:23 -0000
@@ -0,0 +1,309 @@
+/* -*- 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 <glade.h>
+#include <glade-binding.h>
+#include <pygobject.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));
+
+	glade_app_update_ui ();
+	
+	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;
+
+		glade_app_update_ui ();
+	}
+	
+	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 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, "Execute redo command."},
+    {"project_open",  glade_python_project_open, METH_VARARGS, "Execute redo command."},
+    {"project_save",  glade_python_project_save, METH_VARARGS, "Execute redo command."},
+    {NULL, NULL, 0, NULL}
+};
+
+/* 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);
+	}
+	
+	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.97
diff -u -u -p -r1.97 glade-utils.c
--- src/glade-utils.c	28 Aug 2006 21:46:05 -0000	1.97
+++ src/glade-utils.c	17 Oct 2006 17:12:23 -0000
@@ -138,8 +138,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)
@@ -150,17 +151,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.h
===================================================================
RCS file: /cvs/gnome/glade3/src/glade.h,v
retrieving revision 1.75
diff -u -u -p -r1.75 glade.h
--- src/glade.h	29 Sep 2006 18:02:02 -0000	1.75
+++ src/glade.h	17 Oct 2006 17:12:24 -0000
@@ -83,6 +83,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"
@@ -152,9 +153,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;
 
Index: src/main.c
===================================================================
RCS file: /cvs/gnome/glade3/src/main.c,v
retrieving revision 1.55
diff -u -u -p -r1.55 main.c
--- src/main.c	19 Aug 2006 18:48:55 -0000	1.55
+++ src/main.c	17 Oct 2006 17:12:24 -0000
@@ -142,6 +142,7 @@ main (int argc, char *argv[])
 	
 	glade_setup_log_handlers ();
 	
+	glade_binding_load_all ();
 	
 	project_window = glade_project_window_new ();
