Commit e29d9b0f authored by Juan Pablo Ugarte's avatar Juan Pablo Ugarte
Browse files

Added python/pygtk checks.

* configure.in: Added python/pygtk checks.

* src/Makefile.am: added glade-binding.[ch] and BUILD_PYTHON rules

* src/glade-app.c:
  o added glade_scripts_dir and glade_bindings_dir globals
  o loading / unloading bindings.

* src/glade-binding.[ch]: GladeBinding support this is the glue code
  between glade core and bindings modules.

* src/glade-catalog.c: support for loading catalogs supported by
  bindings, added language member to GladeCatalog.

* src/glade-marshallers.list: added new marshallers BOOLEAN:STRING and
  BOOLEAN:OBJECT,STRING

* src/glade-paths.sh.in: added GLADE_BINDINGSDIR and GLADE_SCRIPTSDIR.

* src/glade-popup.c: added support for GWAAction
  (shows context actions as menu items)

* src/glade-project-window.c: added window which a console for each
  GladeBinding that provide a console.

* glade-python-gwa.c: GladeWidgetAdaptor python wrapper.

* glade-python-gwa.[defs override]: files used by pygtk-codegen-2.0
  to create glade-python-gwa.c

* glade-python.c: GladeBinding plugin for python language.

* src/glade-widget-adaptor.[ch]:
  o added GWAAction support.
  o added "action-activated" signal
  o added glade_create_reason_get_type() so the enum can be exposed in
    bindings as a GEnum.
  o added "adaptor" property to glade-widget-class this way non C catalog
    plugins can define the GladeWidgetAdaptor derived class.
    <glade-widget-class name="Custom" adaptor="CustomAdaptor"/>
  o setup binding scripts as actions.
  o added glade_widget_adaptor_emit_action_activated()
    (used in glade-popup.c)

* src/glade-widget.[ch]: added "action-activated" signal.

* src/glade.h: added GLADE_TAG_LANGUAGE, GLADE_TAG_ACTION_GROUP,
  GLADE_TAG_ACTION, GLADE_TAG_STOCK, glade_scripts_dir and
  glade_bindings_dir.
parent e6484fc8
2006-11-21 Juan Pablo Ugarte <juanpablougarte@gmail.com>
* configure.in: Added python/pygtk checks.
* src/Makefile.am: added glade-binding.[ch] and BUILD_PYTHON rules
* src/glade-app.c:
o added glade_scripts_dir and glade_bindings_dir globals
o loading / unloading bindings.
* src/glade-binding.[ch]: GladeBinding support this is the glue code
between glade core and bindings modules.
* src/glade-catalog.c: support for loading catalogs supported by
bindings, added language member to GladeCatalog.
* src/glade-marshallers.list: added new marshallers BOOLEAN:STRING and
BOOLEAN:OBJECT,STRING
* src/glade-paths.sh.in: added GLADE_BINDINGSDIR and GLADE_SCRIPTSDIR.
* src/glade-popup.c: added support for GWAAction
(shows context actions as menu items)
* src/glade-project-window.c: added window which a console for each
GladeBinding that provide a console.
* glade-python-gwa.c: GladeWidgetAdaptor python wrapper.
* glade-python-gwa.[defs override]: files used by pygtk-codegen-2.0
to create glade-python-gwa.c
* glade-python.c: GladeBinding plugin for python language.
* src/glade-widget-adaptor.[ch]:
o added GWAAction support.
o added "action-activated" signal
o added glade_create_reason_get_type() so the enum can be exposed in
bindings as a GEnum.
o added "adaptor" property to glade-widget-class this way non C catalog
plugins can define the GladeWidgetAdaptor derived class.
<glade-widget-class name="Custom" adaptor="CustomAdaptor"/>
o setup binding scripts as actions.
o added glade_widget_adaptor_emit_action_activated()
(used in glade-popup.c)
* src/glade-widget.[ch]: added "action-activated" signal.
* src/glade.h: added GLADE_TAG_LANGUAGE, GLADE_TAG_ACTION_GROUP,
GLADE_TAG_ACTION, GLADE_TAG_STOCK, glade_scripts_dir and
glade_bindings_dir.
2006-11-20 Tristan Van Berkom <tvb@gnome.org>
* src/glade-property.c:
......
......@@ -73,6 +73,31 @@ 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
AC_PATH_PROGS([PYTHON], [python])
PKG_CHECK_MODULES(PYGTK, pygtk-2.0 >= 2.10.0, [have_pygtk=yes], [have_pygtk=no])
if test -f $PYTHON -a "$have_pygtk" = "yes"; then
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
else
have_python=no
fi
else
have_python=no
fi
AM_CONDITIONAL(BUILD_PYTHON, test x"$have_python" = "xyes")
dnl ================================================================
dnl Check for windows
dnl ================================================================
......@@ -92,7 +117,7 @@ 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_scriptsdir='${glade_datadir}/scripts'
glade_modulesdir='${glade_libdir}/modules'
glade_pluginsdir='${glade_libdir}/plugins'
glade_bindingsdir='${glade_libdir}/bindings'
......@@ -132,5 +157,5 @@ Configuration:
Source code location: ${srcdir}
Compiler: ${CC}
GnomeUI Catalog: ${have_gnome}
Python Binding: ${have_python}
"
......@@ -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 = \
......@@ -138,6 +139,7 @@ libgladeuiinclude_HEADERS = \
glade-app.h \
glade-builtins.h \
glade-fixed.h \
glade-binding.h \
glade-base-editor.h \
fixed_bg.xpm \
atk.xpm
......@@ -145,6 +147,16 @@ 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 glade-python-gwa.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)
......@@ -162,6 +174,10 @@ if BUILD_GNOME
libgladegnome_la_LDFLAGS += -no-undefined
endif
if BUILD_PYTHON
libgladepython_la_LDFLAGS += -no-undefined
endif
endif
#
......
......@@ -36,6 +36,7 @@
#include "glade-catalog.h"
#include "glade-paths.h"
#include "glade-fixed.h"
#include "glade-binding.h"
#include <gdk/gdkkeysyms.h>
#include <gtk/gtkstock.h>
......@@ -81,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;
......@@ -151,11 +154,16 @@ 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);
......@@ -308,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);
......
/* -*- 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>
/*
GladeBindings are glade's modules to add support for others languages.
The principal objective is to be able to support widgets written in other
language than C.
The bindings modules provides this functionality to the core trought a couple
of obligatory functions.
GladeBindingInitFunc glade_binding_init() to initialize the binding and
GladeBindingLibraryLoadFunc glade_binding_library_load() to load a library
written in language supported by the binding.
You can add Scripting capability to the core by providing
GladeBindingRunScriptFunc glade_binding_run_script() and/or
GladeBindingConsoleNewFunc glade_binding_console_new()
The core will search for script in two different directories,
datadir/package/scripts/ and g_get_user_config_dir()/package/scripts/
The hierarchy in those directories should be binding_name/gtype_name/ *
For example if you want to add a python script to GtkContainers you can do it by
installing the script file in
g_get_user_config_dir()/glade3/scripts/python/GtkContainer/Delete_Children.py
This will add a context menu item for any GtkContainer called "Delete Children"
that will trigger GtkContainer's widget adaptor "action-activated::Delete_Children" signal.
*/
static GHashTable *bindings = NULL;
static GList*
glade_binding_script_add (GList *list, GladeBinding *binding, gchar *path)
{
GladeBindingScript *script = g_new0 (GladeBindingScript, 1);
gchar *tmp;
script->binding = binding;
script->path = path;
script->name = g_path_get_basename (path);
if ((tmp = strrchr (script->name, '.'))) *tmp = '\0';
return g_list_prepend (list, script);
}
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 *path = g_build_filename (directory, filename, NULL);
if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
list = glade_binding_script_add (list, binding, path);
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_script_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->context_scripts,
type);
g_datalist_id_remove_no_notify (&binding->context_scripts, type);
list = g_list_concat (old_list, list);
g_datalist_id_set_data_full (&binding->context_scripts, type, list,
glade_binding_classes_destroy);
}
else if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
binding->scripts = glade_binding_script_add (binding->scripts, binding, path);
else
g_free (path);
}
}
/**
* glade_binding_load_all:
*
* Loads and initialize every binding plugin.
*
*/
void
glade_binding_load_all (void)
{
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)))
{
GladeBindingInitFunc init;
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;
if (g_module_symbol (module, "glade_binding_init",
(gpointer)&init) &&
init (&binding->ctrl) && binding->ctrl.name)
{
g_hash_table_insert (bindings, binding->ctrl.name, binding);
if (binding->ctrl.run_script)
{
gchar *rootdir;
g_datalist_init (&binding->context_scripts);
rootdir = g_build_filename (glade_scripts_dir,
binding->ctrl.name, NULL);
glade_binding_script_load (binding, rootdir);
g_free (rootdir);
rootdir = g_build_filename (g_get_user_config_dir (),
PACKAGE_NAME, GLADE_BINDING_SCRIPT_DIR,
binding->ctrl.name, NULL);
glade_binding_script_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->ctrl.finalize) binding->ctrl.finalize (&binding->ctrl);
g_module_close (binding->module);
if (binding->scripts)
glade_binding_classes_destroy (binding->scripts);
if (binding->context_scripts)
g_datalist_clear (&binding->context_scripts);
g_free (binding);
}
/**
* glade_binding_unload_all:
*
* Finalize and unload every binding plugin.
*
*/
void
glade_binding_unload_all (void)
{
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 (const gchar *name)
{
g_return_val_if_fail (name != NULL, NULL);
return g_hash_table_lookup (bindings, name);
}
/**
* glade_binding_get_name:
*
* @binding: the binding
*
* Returns the binding name.
*
*/
const gchar *
glade_binding_get_name (GladeBinding *binding)
{
g_return_val_if_fail (binding != NULL, NULL);
return binding->ctrl.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 (void)
{
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, const gchar *library)
{
g_return_if_fail (binding != NULL && library != NULL);
if (binding->ctrl.library_load)
binding->ctrl.library_load (library);
}
/**
* 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);
if (binding->ctrl.console_new)
return binding->ctrl.console_new ();
else
return NULL;
}
/**
* glade_binding_run_script:
*
* @binding: a GladeBinding.
* @path: the library init function name.
*
* Run a script file.
*
*/
gint
glade_binding_run_script (GladeBinding *binding,
const gchar *path,
gchar **argv)
{
g_return_val_if_fail (binding != NULL && path != NULL, -1);
if (binding->ctrl.run_script)
return binding->ctrl.run_script (path, argv);
else
return -1;
}
/* -*- 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 "scripts"
typedef struct _GladeBindingCtrl GladeBindingCtrl;
/**
* GladeBindingInitFunc:
*
* This function is called after loading the binding plugin.
*
* With interpreted language this would initialize the language's interpreter.
*
* Returns: whether or not the plugin was successfully initialized.
*
*/
typedef gboolean (*GladeBindingInitFunc) (GladeBindingCtrl *ctrl);
/**
* GladeBindingFinalizeFunc:
*
* This function is called after unloading the binding plugin.
* It should freed everuthing allocated by the init function.
*
*/
typedef void (*GladeBindingFinalizeFunc) (GladeBindingCtrl *ctrl);
/**
* GladeBindingLibraryLoadFunc:
*
* @str: the library name to load.
*
* This function is used to load a library written in the language that is
* supported by the binding.
*
* For example if I had a custom widget library writen in python, this function
* will provide the core a way to load "glademywidgets" python module.
*
* <glade-catalog name="mywidgets" library="glademywidgets" language="python">
*
*/
typedef void