planner-python-plugin.c 4.95 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2004 Xavier Ordoquy <xordoquy@wanadoo.fr>
 *
 * 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
Josué Abarca's avatar
Josué Abarca committed
17 18
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
19 20 21
 */

#include <config.h>
22
#include <Python.h>
23
#include <glib.h>
24
#include <gtk/gtk.h>
25
#include <glib/gi18n.h>
26
#include <pygobject.h>
27 28 29 30
#include "planner-window.h"
#include "planner-plugin.h"

struct _PlannerPluginPriv {
31
	GHashTable    *scripts;
32 33
};

34 35 36 37
typedef struct {
	gchar    *filename;
	PyObject *globals;
} PlannerPythonEnv;
38

39 40 41 42 43
static PlannerPythonEnv *planner_python_env_new  (const gchar      *name);
static void              planner_python_env_free (PlannerPythonEnv *env);
static void              python_plugin_execute   (const gchar      *filename,
						  PlannerWindow    *window,
						  GHashTable       *scripts);
44
void                     plugin_init             (PlannerPlugin    *plugin);
45
void                     plugin_exit             (PlannerPlugin    *plugin);
46

47 48


49
static PlannerPythonEnv *
50
planner_python_env_new (const gchar *filename)
51 52 53 54 55
{
	PlannerPythonEnv *env;
	PyObject         *pDict, *pMain;

	env = g_new0 (PlannerPythonEnv,1);
56
	env->filename = g_strdup (filename);
57 58 59 60 61 62 63 64 65 66 67 68

	pDict = PyImport_GetModuleDict ();
	pMain = PyDict_GetItemString (pDict, "__main__");
	pDict = PyModule_GetDict (pMain);
	env->globals = PyDict_Copy (pDict);

	return env;
}

static void
planner_python_env_free (PlannerPythonEnv *env)
{
69
	g_free (env->filename);
70 71 72 73 74
	PyDict_Clear (env->globals);
	Py_DECREF (env->globals);
	g_free (env);
}

75
static void
76 77 78
python_plugin_execute (const gchar   *filename,
		       PlannerWindow *window,
		       GHashTable    *scripts)
79
{
80 81 82 83
	PlannerPythonEnv *env;
	FILE             *fp;
	PyObject         *pModule;
	PyObject         *py_object;
84 85 86 87 88

	env = planner_python_env_new (filename);

	pModule = PyRun_String ("import pygtk\n"
				"pygtk.require('2.0')\n"
89
				"import gtk\n"
90
				"import planner\n",
91
				Py_file_input, env->globals, env->globals);
92
	if (!pModule) {
93 94 95 96 97
		PyErr_Print ();
		planner_python_env_free (env);
		return;
	}

98 99
	pModule = PyImport_ImportModuleEx ("plannerui", env->globals, env->globals, Py_None);
	if (!pModule) {
100 101 102 103 104
		PyErr_Print ();
		planner_python_env_free (env);
		return;
	}

105 106 107 108 109 110 111
	py_object = pygobject_new (G_OBJECT (window));
	PyDict_SetItemString (env->globals, "window", py_object);
	Py_DECREF (py_object);

	py_object = pygobject_new (G_OBJECT (planner_window_get_application (window)));
	PyDict_SetItemString (env->globals, "application", py_object);
	Py_DECREF (py_object);
112 113

	fp = fopen (filename,"r");
114 115
	if (fp) {
		if (PyRun_File (fp, (gchar *) filename, Py_file_input, env->globals, env->globals) == NULL) {
116 117 118
			PyErr_Print ();
		}
		fclose (fp);
119
		g_hash_table_insert (scripts, env->filename, env);
120
	} else {
121 122
		planner_python_env_free (env);

123
		/* FIXME: do the free */
124
		g_warning ("Could not open python script: %s", filename);
125
	}
126 127
}

128 129
static void
plugin_execute_scripts(PlannerPlugin *plugin, const gchar *dirname)
130
{
131
	GDir              *dir;
132
	gchar             *full_filename;
133
	const gchar       *filename;
134

135
	dir = g_dir_open (dirname, 0, NULL);
136 137 138
	if (dir == NULL) {
		return;
	}
139

140
	filename = g_dir_read_name (dir);
141
	while (filename != NULL) {
142 143
		if (g_str_has_suffix (filename, ".py")) {
			full_filename = g_build_filename (dirname, filename, NULL);
144
			python_plugin_execute (full_filename, plugin->main_window, plugin->priv->scripts);
145 146
			g_free (full_filename);
		}
147

148
		filename = g_dir_read_name (dir);
149
	}
150

151
	g_free ((gpointer) dirname);
152
	g_dir_close (dir);
153 154
}

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
G_MODULE_EXPORT void
plugin_init (PlannerPlugin *plugin)
{
	PlannerPluginPriv *priv;
	gchar             *dirname;

	priv = g_new0 (PlannerPluginPriv, 1);
	plugin->priv = priv;

	priv->scripts = g_hash_table_new (g_str_hash, g_str_equal);

	Py_Initialize ();

	/* Look in $XDG_DATA_HOME/planner/python/  and run the scripts that we find */
	dirname = g_build_filename (g_get_user_data_dir(), "planner", "python", NULL);
	plugin_execute_scripts(plugin, dirname);
	g_free (dirname);


	/* Look in ~/.gnome2/planner/python/  and run the scripts that we find */
	dirname = g_build_filename (g_get_home_dir(), ".gnome2", "planner", "python", NULL);
	plugin_execute_scripts(plugin, dirname);
	g_free (dirname);
}

180 181
G_MODULE_EXPORT void
plugin_exit (PlannerPlugin *plugin)
182
{
183 184 185 186 187 188
	PlannerPluginPriv *priv;

	priv = plugin->priv;

	/* FIXME: free everything in the hash table */

189
	Py_Finalize ();
190 191

	g_free (priv);
192
}