/* * pluma-plugin-python.c * This file is part of pluma * * Copyright (C) 2005 Raphael Slinckx * Copyright (C) 2008 Jesse van den Kieboom * * 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 St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include "pluma-plugin-python.h" #include #include #include #include #define PLUMA_PLUGIN_PYTHON_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), PLUMA_TYPE_PLUGIN_PYTHON, PlumaPluginPythonPrivate)) static GObjectClass *parent_class; struct _PlumaPluginPythonPrivate { PyObject *instance; }; static void pluma_plugin_python_class_init (PlumaPluginPythonClass *klass); static void pluma_plugin_python_init (PlumaPluginPython *plugin); G_DEFINE_TYPE (PlumaPluginPython, pluma_plugin_python, PLUMA_TYPE_PLUGIN) static PyObject * call_python_method (PlumaPluginPythonPrivate *priv, PlumaWindow *window, gchar *method) { PyObject *py_ret = NULL; g_return_val_if_fail (PyObject_HasAttrString (priv->instance, method), NULL); if (window == NULL) { py_ret = PyObject_CallMethod (priv->instance, method, NULL); } else { py_ret = PyObject_CallMethod (priv->instance, method, "(N)", pygobject_new (G_OBJECT (window))); } if (!py_ret) PyErr_Print (); return py_ret; } static gboolean check_py_object_is_gtk_widget (PyObject *py_obj) { static PyTypeObject *_PyGtkWidget_Type = NULL; if (_PyGtkWidget_Type == NULL) { PyObject *module; if ((module = PyImport_ImportModule ("gtk"))) { PyObject *moddict = PyModule_GetDict (module); _PyGtkWidget_Type = (PyTypeObject *) PyDict_GetItemString (moddict, "Widget"); } if (_PyGtkWidget_Type == NULL) { PyErr_SetString(PyExc_TypeError, "could not find Python gtk widget type"); PyErr_Print(); return FALSE; } } return PyObject_TypeCheck (py_obj, _PyGtkWidget_Type) ? TRUE : FALSE; } static void impl_update_ui (PlumaPlugin *plugin, PlumaWindow *window) { PyGILState_STATE state = pyg_gil_state_ensure (); PlumaPluginPythonPrivate *priv = PLUMA_PLUGIN_PYTHON(plugin)->priv; if (PyObject_HasAttrString (priv->instance, "update_ui")) { PyObject *py_ret = call_python_method (priv, window, "update_ui"); if (py_ret) { Py_XDECREF (py_ret); } } else PLUMA_PLUGIN_CLASS (parent_class)->update_ui (plugin, window); pyg_gil_state_release (state); } static void impl_deactivate (PlumaPlugin *plugin, PlumaWindow *window) { PyGILState_STATE state = pyg_gil_state_ensure (); PlumaPluginPythonPrivate *priv = PLUMA_PLUGIN_PYTHON(plugin)->priv; if (PyObject_HasAttrString (priv->instance, "deactivate")) { PyObject *py_ret = call_python_method (priv, window, "deactivate"); if (py_ret) { Py_XDECREF (py_ret); } } else PLUMA_PLUGIN_CLASS (parent_class)->deactivate (plugin, window); pyg_gil_state_release (state); } static void impl_activate (PlumaPlugin *plugin, PlumaWindow *window) { PyGILState_STATE state = pyg_gil_state_ensure (); PlumaPluginPythonPrivate *priv = PLUMA_PLUGIN_PYTHON(plugin)->priv; if (PyObject_HasAttrString (priv->instance, "activate")) { PyObject *py_ret = call_python_method (priv, window, "activate"); if (py_ret) { Py_XDECREF (py_ret); } } else PLUMA_PLUGIN_CLASS (parent_class)->activate (plugin, window); pyg_gil_state_release (state); } static GtkWidget * impl_create_configure_dialog (PlumaPlugin *plugin) { PyGILState_STATE state = pyg_gil_state_ensure (); PlumaPluginPythonPrivate *priv = PLUMA_PLUGIN_PYTHON(plugin)->priv; GtkWidget *ret = NULL; if (PyObject_HasAttrString (priv->instance, "create_configure_dialog")) { PyObject *py_ret = call_python_method (priv, NULL, "create_configure_dialog"); if (py_ret) { if (check_py_object_is_gtk_widget (py_ret)) { ret = GTK_WIDGET (pygobject_get (py_ret)); g_object_ref (ret); } else { PyErr_SetString(PyExc_TypeError, "return value for create_configure_dialog is not a GtkWidget"); PyErr_Print(); } Py_DECREF (py_ret); } } else ret = PLUMA_PLUGIN_CLASS (parent_class)->create_configure_dialog (plugin); pyg_gil_state_release (state); return ret; } static gboolean impl_is_configurable (PlumaPlugin *plugin) { PyGILState_STATE state = pyg_gil_state_ensure (); PlumaPluginPythonPrivate *priv = PLUMA_PLUGIN_PYTHON(plugin)->priv; PyObject *dict = priv->instance->ob_type->tp_dict; gboolean result; if (dict == NULL) result = FALSE; else if (!PyDict_Check(dict)) result = FALSE; else result = PyDict_GetItemString(dict, "create_configure_dialog") != NULL; pyg_gil_state_release (state); return result; } void _pluma_plugin_python_set_instance (PlumaPluginPython *plugin, PyObject *instance) { PyGILState_STATE state = pyg_gil_state_ensure (); /* we don't increment the instance here because we are the instance, when it dies, we also die */ plugin->priv->instance = instance; pyg_gil_state_release (state); } PyObject * _pluma_plugin_python_get_instance (PlumaPluginPython *plugin) { return plugin->priv->instance; } static void pluma_plugin_python_init (PlumaPluginPython *plugin) { plugin->priv = PLUMA_PLUGIN_PYTHON_GET_PRIVATE(plugin); pluma_debug_message (DEBUG_PLUGINS, "Creating Python plugin instance"); plugin->priv->instance = 0; } static void pluma_plugin_python_finalize (GObject *object) { PyGILState_STATE state; pluma_debug_message (DEBUG_PLUGINS, "Finalizing Python plugin instance"); state = pyg_gil_state_ensure (); Py_XDECREF (PLUMA_PLUGIN_PYTHON(object)->priv->instance); pyg_gil_state_release (state); G_OBJECT_CLASS (parent_class)->finalize (object); } static void pluma_plugin_python_class_init (PlumaPluginPythonClass *klass) { PlumaPluginClass *plugin_class = PLUMA_PLUGIN_CLASS (klass); parent_class = g_type_class_peek_parent (klass); g_type_class_add_private (klass, sizeof (PlumaPluginPythonPrivate)); G_OBJECT_CLASS (klass)->finalize = pluma_plugin_python_finalize; plugin_class->activate = impl_activate; plugin_class->deactivate = impl_deactivate; plugin_class->update_ui = impl_update_ui; plugin_class->create_configure_dialog = impl_create_configure_dialog; plugin_class->is_configurable = impl_is_configurable; }