diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-12-14 16:38:10 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-12-14 16:38:10 (GMT) |
commit | 97fa09113c7988e4b4639190ba9bc51f9ced4d33 (patch) | |
tree | 1b4fe85843b4cdbf685e5116a96c4f387a865561 /plugins/pychrysalide/gui/panels | |
parent | e526727b94444030a3ae4dc6d4431cb72aea31e0 (diff) |
Extended the Python API to build custom GUI panels.
Diffstat (limited to 'plugins/pychrysalide/gui/panels')
-rw-r--r-- | plugins/pychrysalide/gui/panels/panel.c | 213 | ||||
-rw-r--r-- | plugins/pychrysalide/gui/panels/panel.h | 3 |
2 files changed, 201 insertions, 15 deletions
diff --git a/plugins/pychrysalide/gui/panels/panel.c b/plugins/pychrysalide/gui/panels/panel.c index 37b682f..1df0670 100644 --- a/plugins/pychrysalide/gui/panels/panel.c +++ b/plugins/pychrysalide/gui/panels/panel.c @@ -28,21 +28,37 @@ #include <pygobject.h> +#include <i18n.h> #include <core/params.h> #include <gui/core/panels.h> -#include <gui/panels/panel.h> +#include <gui/panels/panel-int.h> #include "../editem.h" #include "../../access.h" +#include "../../dt.h" #include "../../helpers.h" #include "../../gtkext/dockable.h" +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_panel_item_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise la classe des panneaux pour l'interface graphique. */ +static void py_panel_item_init_gclass(GPanelItemClass *, gpointer); + /* Initialise une instance sur la base du dérivé de GObject. */ static int py_panel_item_init(PyObject *self, PyObject *args, PyObject *kwds); + + +/* -------------------------- FONCTIONNALITES D'UN PANNEAU -------------------------- */ + + /* Place un panneau dans l'ensemble affiché. */ static PyObject *py_panel_item_dock(PyObject *, PyObject *); @@ -51,6 +67,102 @@ static bool py_panel_item_define_constants(PyTypeObject *); +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_panel_item_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + bool abstract; /* Validation du type parent */ + GType gtype; /* Nouveau type de processeur */ + PyObject *sys_mod_dict; /* Dictionnaire des modules */ + PyObject *modname; /* Nom du module du type */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire dudit module */ + + /* Validations diverses */ + + abstract = (type == get_python_panel_item_type()); + + if (abstract) + { + result = NULL; + PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name); + goto exit; + } + + /* Mise en place d'un type dédié */ + + gtype = built_dynamic_type(G_TYPE_PANEL_ITEM, type->tp_name, + (GClassInitFunc)py_panel_item_init_gclass); + + /* Enregistrement du nouveau GType dans Python */ + + sys_mod_dict = PyImport_GetModuleDict(); + + modname = PyDict_GetItemString(type->tp_dict, "__module__"); + + module = PyObject_GetItem(sys_mod_dict, modname); + + dict = PyModule_GetDict(module); + + if (!_register_class_for_pygobject(dict, gtype, type, + &PyGObject_Type, get_python_panel_item_type(), NULL)) + { + result = NULL; + goto exit; + } + + Py_DECREF(module); + Py_DECREF(modname); + + /* On créé, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* unused = données non utilisées ici. * +* * +* Description : Initialise la classe des panneaux pour l'interface graphique.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_panel_item_init_gclass(GPanelItemClass *class, gpointer unused) +{ + py_editor_item_init_gclass(G_EDITOR_ITEM_CLASS(class), NULL); + +} + + /****************************************************************************** * * * Paramètres : self = objet à initialiser (théoriquement). * @@ -74,16 +186,41 @@ static int py_panel_item_init(PyObject *self, PyObject *args, PyObject *kwds) int startup; /* Recommandation au démarrage */ const char *path; /* Placement à l'affichage */ int ret; /* Bilan de lecture des args. */ - GPanelItem *item; /* Elément de l'éditeur */ + PyObject *new_kwds; /* Nouveau dictionnaire épuré */ + GPanelItem *panel; /* Panneau à manipuler */ + GEditorItem *item; /* Version basique d'instance */ + + static char *kwlist[] = { "name", "widget", "personality", "lname", "dock", "path", NULL }; + + /* Récupération des paramètres */ - ret = PyArg_ParseTuple(args, "kssOps", &personality, &name, &lname, &widget, &startup, &path); + ret = PyArg_ParseTupleAndKeywords(args, kwds, "sOksps", kwlist, + &name, &widget, &personality, &lname, &startup, &path); if (!ret) return -1; - item = g_panel_item_new(personality, name, lname, - GTK_WIDGET(pygobject_get(widget)), startup, path); + /* Initialisation d'un objet GLib */ - /* FIXME ? Est-ce à l'utilisateur de s'enregistrer ? */ - register_panel_item(item, get_main_configuration()); + new_kwds = PyDict_New(); + + ret = PyGObject_Type.tp_init(self, args, new_kwds); + + Py_DECREF(new_kwds); + + if (ret == -1) return -1; + + /* Eléments de base */ + + panel = G_PANEL_ITEM(pygobject_get(self)); + + item = G_EDITOR_ITEM(panel); + + item->name = strdup(name);; + item->widget = GTK_WIDGET(pygobject_get(widget)); + + panel->personality = personality; + panel->lname = strdup(lname); + panel->dock_at_startup = startup; + panel->path = strdup(path); /** * Si Python ne voit plus la variable représentant le panneau utilisée, @@ -92,18 +229,17 @@ static int py_panel_item_init(PyObject *self, PyObject *args, PyObject *kwds) * On sera donc en situation de Use-After-Free, dont les conséquences * arrivent très vite. */ - g_object_ref(GTK_WIDGET(pygobject_get(widget))); - Py_INCREF(self); + g_object_ref(G_OBJECT(item->widget)); - /* Enregistrement auprès de PyGObject */ + return 0; - ((PyGObject *)self)->obj = G_OBJECT(item); +} - pygobject_register_wrapper(self); - return 0; -} +/* ---------------------------------------------------------------------------------- */ +/* FONCTIONNALITES D'UN PANNEAU */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -172,7 +308,9 @@ PyTypeObject *get_python_panel_item_type(void) .tp_methods = py_panel_item_methods, .tp_getset = py_panel_item_getseters, - .tp_init = (initproc)py_panel_item_init + + .tp_init = py_panel_item_init, + .tp_new = py_panel_item_new, }; @@ -256,3 +394,48 @@ bool ensure_python_panel_item_is_registered(void) return true; } + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en panneau pour GUI. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_panel_item(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_panel_item_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to executable format"); + break; + + case 1: + *((GPanelItem **)dst) = G_PANEL_ITEM(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/gui/panels/panel.h b/plugins/pychrysalide/gui/panels/panel.h index 7fb473b..907c650 100644 --- a/plugins/pychrysalide/gui/panels/panel.h +++ b/plugins/pychrysalide/gui/panels/panel.h @@ -37,6 +37,9 @@ PyTypeObject *get_python_panel_item_type(void); /* Prend en charge l'objet 'pychrysalide.gui.panels.PanelItem'. */ bool ensure_python_panel_item_is_registered(void); +/* Tente de convertir en panneau pour GUI. */ +int convert_to_panel_item(PyObject *, void *); + #endif /* _PLUGINS_PYCHRYSALIDE_GUI_PANELS_PANEL_H */ |