From 6c751d40ab1b84a6979c143ed47702207edebed8 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 14 Jul 2020 15:06:20 +0200 Subject: Updated the Python bindings for the loaded panel interface. --- plugins/pychrysalide/analysis/storage/serialize.c | 1 - plugins/pychrysalide/glibext/constants.c | 135 +++++++++++++-- plugins/pychrysalide/glibext/constants.h | 14 +- plugins/pychrysalide/glibext/loadedpanel.c | 191 +++++++++++++++++----- 4 files changed, 277 insertions(+), 64 deletions(-) diff --git a/plugins/pychrysalide/analysis/storage/serialize.c b/plugins/pychrysalide/analysis/storage/serialize.c index 3e94271..eeab8f5 100644 --- a/plugins/pychrysalide/analysis/storage/serialize.c +++ b/plugins/pychrysalide/analysis/storage/serialize.c @@ -56,7 +56,6 @@ static bool py_serializable_object_store_wrapper(const GSerializableObject *, GO /* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ - /* Charge un objet depuis une mémoire tampon. */ static bool py_serializable_object_load(PyObject *, PyObject *); diff --git a/plugins/pychrysalide/glibext/constants.c b/plugins/pychrysalide/glibext/constants.c index 47bd00d..a7938cb 100644 --- a/plugins/pychrysalide/glibext/constants.c +++ b/plugins/pychrysalide/glibext/constants.c @@ -25,9 +25,11 @@ #include "constants.h" +#include #include #include #include +#include #include "../helpers.h" @@ -148,6 +150,105 @@ int convert_to_portion_access_rights(PyObject *arg, void *dst) * * * Paramètres : type = type dont le dictionnaire est à compléter. * * * +* Description : Définit les constantes relatives aux lignes de tampon. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_buffer_line_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + values = PyDict_New(); + + result = add_const_to_group(values, "NONE", BLF_NONE); + if (result) result = add_const_to_group(values, "HAS_CODE", BLF_HAS_CODE); + if (result) result = add_const_to_group(values, "IS_LABEL", BLF_IS_LABEL); + if (result) result = add_const_to_group(values, "ENTRYPOINT", BLF_ENTRYPOINT); + if (result) result = add_const_to_group(values, "BOOKMARK", BLF_BOOKMARK); + if (result) result = add_const_to_group(values, "WIDTH_MANAGER", BLF_WIDTH_MANAGER); + if (result) result = add_const_to_group(values, "ALL", BLF_ALL); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, true, "BufferLineFlags", values, + "Optional flags linked to a rendering line."); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* 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 constante BufferLineFlags. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_buffer_line_flags(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + unsigned long value; /* Valeur transcrite */ + + result = PyObject_IsInstance(arg, (PyObject *)&PyLong_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 BufferLineFlags"); + break; + + case 1: + value = PyLong_AsUnsignedLong(arg); + + if ((value & BLF_ALL) != value) + { + PyErr_SetString(PyExc_TypeError, "invalid value for BufferLineFlags"); + result = 0; + } + + else + *((BufferLineFlags *)dst) = value; + + break; + + default: + assert(false); + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * * Description : Définit les constantes relatives aux segments de ligne. * * * * Retour : true en cas de succès de l'opération, false sinon. * @@ -258,7 +359,7 @@ int convert_to_rendering_tag_type(PyObject *arg, void *dst) * * * Paramètres : type = type dont le dictionnaire est à compléter. * * * -* Description : Définit les constantes relatives aux lignes de tampon. * +* Description : Définit les constantes relatives aux panneaux de chargement. * * * * Retour : true en cas de succès de l'opération, false sinon. * * * @@ -266,20 +367,17 @@ int convert_to_rendering_tag_type(PyObject *arg, void *dst) * * ******************************************************************************/ -bool define_buffer_line_constants(PyTypeObject *type) +bool define_loaded_panel_constants(PyTypeObject *type) { bool result; /* Bilan à retourner */ PyObject *values; /* Groupe de valeurs à établir */ values = PyDict_New(); - result = add_const_to_group(values, "NONE", BLF_NONE); - if (result) result = add_const_to_group(values, "HAS_CODE", BLF_HAS_CODE); - if (result) result = add_const_to_group(values, "IS_LABEL", BLF_IS_LABEL); - if (result) result = add_const_to_group(values, "ENTRYPOINT", BLF_ENTRYPOINT); - if (result) result = add_const_to_group(values, "BOOKMARK", BLF_BOOKMARK); - if (result) result = add_const_to_group(values, "WIDTH_MANAGER", BLF_WIDTH_MANAGER); - if (result) result = add_const_to_group(values, "ALL", BLF_ALL); + result = add_const_to_group(values, "RAW", SPT_RAW); + if (result) result = add_const_to_group(values, "TOP", SPT_TOP); + if (result) result = add_const_to_group(values, "CENTER", SPT_CENTER); + if (result) result = add_const_to_group(values, "BOTTOM", SPT_BOTTOM); if (!result) { @@ -287,8 +385,8 @@ bool define_buffer_line_constants(PyTypeObject *type) goto exit; } - result = attach_constants_group_to_type(type, true, "BufferLineFlags", values, - "Optional flags linked to a rendering line."); + result = attach_constants_group_to_type(type, false, "ScrollPositionTweak", values, + "Details for adjusting the displayed position while scrolling."); exit: @@ -302,7 +400,7 @@ bool define_buffer_line_constants(PyTypeObject *type) * 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 constante BufferLineFlags. * +* Description : Tente de convertir en constante ScrollPositionTweak. * * * * Retour : Bilan de l'opération, voire indications supplémentaires. * * * @@ -310,10 +408,10 @@ bool define_buffer_line_constants(PyTypeObject *type) * * ******************************************************************************/ -int convert_to_buffer_line_flags(PyObject *arg, void *dst) +int convert_to_scroll_position_tweak(PyObject *arg, void *dst) { int result; /* Bilan à retourner */ - unsigned long value; /* Valeur transcrite */ + unsigned long value; /* Valeur récupérée */ result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type); @@ -325,20 +423,21 @@ int convert_to_buffer_line_flags(PyObject *arg, void *dst) break; case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to BufferLineFlags"); + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ScrollPositionTweak"); break; case 1: + value = PyLong_AsUnsignedLong(arg); - if ((value & BLF_ALL) != value) + if (!IS_VALID_STP(value)) { - PyErr_SetString(PyExc_TypeError, "invalid value for BufferLineFlags"); result = 0; + PyErr_SetString(PyExc_ValueError, _("invalid position tweak")); } else - *((BufferLineFlags *)dst) = value; + *((ScrollPositionTweak *)dst) = value; break; diff --git a/plugins/pychrysalide/glibext/constants.h b/plugins/pychrysalide/glibext/constants.h index b815586..f509866 100644 --- a/plugins/pychrysalide/glibext/constants.h +++ b/plugins/pychrysalide/glibext/constants.h @@ -37,17 +37,23 @@ bool define_binary_portion_constants(PyTypeObject *); /* Tente de convertir en constante PortionAccessRights. */ int convert_to_portion_access_rights(PyObject *, void *); +/* Définit les constantes relatives aux lignes de tampon. */ +bool define_buffer_line_constants(PyTypeObject *); + +/* Tente de convertir en constante BufferLineFlags. */ +int convert_to_buffer_line_flags(PyObject *, void *); + /* Définit les constantes relatives aux segments de ligne. */ bool define_line_segment_constants(PyTypeObject *); /* Tente de convertir en constante RenderingTagType. */ int convert_to_rendering_tag_type(PyObject *, void *); -/* Définit les constantes relatives aux lignes de tampon. */ -bool define_buffer_line_constants(PyTypeObject *); +/* Définit les constantes relatives aux panneaux de chargement. */ +bool define_loaded_panel_constants(PyTypeObject *); -/* Tente de convertir en constante BufferLineFlags. */ -int convert_to_buffer_line_flags(PyObject *, void *); +/* Tente de convertir en constante ScrollPositionTweak. */ +int convert_to_scroll_position_tweak(PyObject *, void *); diff --git a/plugins/pychrysalide/glibext/loadedpanel.c b/plugins/pychrysalide/glibext/loadedpanel.c index d6b743b..6e87cde 100644 --- a/plugins/pychrysalide/glibext/loadedpanel.c +++ b/plugins/pychrysalide/glibext/loadedpanel.c @@ -30,29 +30,46 @@ #include -#include +#include +#include "constants.h" #include "linecursor.h" #include "../access.h" #include "../helpers.h" +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Procède à l'initialisation de l'interface de génération. */ +static void py_loaded_panel_interface_init(GLoadedPanelIface *, gpointer *); + +/* S'assure qu'un emplacement donné est visible à l'écran. */ +static void py_loaded_panel_scroll_to_cursor_wrapper(GLoadedPanel *, const GLineCursor *, ScrollPositionTweak, bool); + + + +/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ + + /* S'assure qu'un emplacement donné est visible à l'écran. */ static PyObject *py_loaded_panel_scroll_to_cursor(PyObject *, PyObject *); -/* Définit les constantes pour l'affichage des contenus chargés. */ -static bool py_loaded_panel_define_constants(PyTypeObject *); +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + /****************************************************************************** * * -* Paramètres : self = classe représentant un tampon de code. * -* args = arguments fournis à l'appel. * +* Paramètres : iface = interface GLib à initialiser. * +* unused = adresse non utilisée ici. * * * -* Description : S'assure qu'un emplacement donné est visible à l'écran. * +* Description : Procède à l'initialisation de l'interface de génération. * * * * Retour : - * * * @@ -60,56 +77,143 @@ static bool py_loaded_panel_define_constants(PyTypeObject *); * * ******************************************************************************/ -static PyObject *py_loaded_panel_scroll_to_cursor(PyObject *self, PyObject *args) +static void py_loaded_panel_interface_init(GLoadedPanelIface *iface, gpointer *unused) { - GLineCursor *cursor; /* Emplacement à cibler */ - unsigned long tweak; /* Adapation à effectuer */ - int move; /* Déplacement à l'écran ? */ - int ret; /* Bilan de lecture des args. */ - GLoadedPanel *panel; /* Panneau à manipuler */ - ret = PyArg_ParseTuple(args, "O&kp", convert_to_line_cursor, &cursor, &tweak, &move); - if (!ret) return NULL; +#define LOADED_PANEL_DOC \ + "LoadPanel defines an interface for all panels which can be included" \ + " inside the main graphical window.\n" \ + "\n" \ + "A typical class declaration for a new implementation looks like:\n" \ + "\n" \ + " class NewImplem(GObject.Object, LoadedPanel():\n" \ + " ...\n" \ + "\n" \ + "The following methods have to be defined for new implementations:\n" \ + "* pychrysalide.glibext.LoadedPanel._scroll_to_cursor();\n" + + iface->scroll = py_loaded_panel_scroll_to_cursor_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à manipuler. * +* cursor = emplacement à présenter à l'écran. * +* tweak = adaptation finale à effectuer. * +* move = doit-on déplacer le curseur à l'adresse indiquée ? * +* * +* Description : S'assure qu'un emplacement donné est visible à l'écran. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - if (!IS_VALID_STP(tweak)) +static void py_loaded_panel_scroll_to_cursor_wrapper(GLoadedPanel *panel, const GLineCursor *cursor, ScrollPositionTweak tweak, bool move) +{ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *tweak_obj; /* Détails en versionPython */ + PyObject *move_obj; /* Consigne de déplacement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define LOADED_PANEL_SCROLL_TO_CURSOR_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _scroll_to_cursor, "$self, cursor, tweak, move, /", \ + METH_VARARGS, \ + "Abstract method used to ensure a given address is displayed in the view" \ + " panel.\n" \ + "\n" \ + "The *cursor* argument is a pychrysalide.glibext.LineCursor location. The" \ + " *tweak* parameter defines the final adjustment for new location and the" \ + " *move* order is a boolean value which implies a scroll operation if" \ + " requiered." \ +) + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(panel)); + + if (has_python_method(pyobj, "_scroll_to_cursor")) { - PyErr_SetString(PyExc_ValueError, _("invalid position tweak")); - return NULL; - } + tweak_obj = cast_with_constants_group_from_type(get_python_loaded_panel_type(), + "ScrollPositionTweak", tweak); - panel = G_LOADED_PANEL(pygobject_get(self)); + move_obj = (move ? Py_True : Py_False); + Py_INCREF(move_obj); - g_loaded_panel_scroll_to_cursor(panel, cursor, tweak, move); + args = PyTuple_New(3); + PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(cursor))); + PyTuple_SetItem(args, 1, tweak_obj); + PyTuple_SetItem(args, 2, move_obj); - Py_RETURN_NONE; + pyret = run_python_method(pyobj, "_scroll_to_cursor", args); + + Py_XDECREF(pyret); + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); } + +/* ---------------------------------------------------------------------------------- */ +/* CONNEXION AVEC L'API DE PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* Paramètres : self = classe représentant un tampon de code. * +* args = arguments fournis à l'appel. * * * -* Description : Définit les constantes pour l'affichage des contenus chargés.* +* Description : S'assure qu'un emplacement donné est visible à l'écran. * * * -* Retour : true en cas de succès de l'opération, false sinon. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool py_loaded_panel_define_constants(PyTypeObject *obj_type) +static PyObject *py_loaded_panel_scroll_to_cursor(PyObject *self, PyObject *args) { - bool result; /* Bilan à retourner */ + GLineCursor *cursor; /* Emplacement à cibler */ + ScrollPositionTweak tweak; /* Adapation à effectuer */ + int move; /* Déplacement à l'écran ? */ + int ret; /* Bilan de lecture des args. */ + GLoadedPanel *panel; /* Panneau à manipuler */ + +#define LOADED_PANEL_SCROLL_TO_CURSOR_METHOD PYTHON_METHOD_DEF \ +( \ + scroll_to_cursor, "$self, cursor, tweak, move, /", \ + METH_VARARGS, py_loaded_panel, \ + "Ensure a given address is displayed in the view panel.\n" \ + "\n" \ + "The *cursor* argument is a pychrysalide.glibext.LineCursor location. The" \ + " *tweak* parameter defines the final adjustment for new location and the" \ + " *move* order is a boolean value which implies a scroll operation if" \ + " requiered." \ +) + + ret = PyArg_ParseTuple(args, "O&O&p", convert_to_line_cursor, &cursor, + convert_to_scroll_position_tweak, &tweak, &move); + if (!ret) return NULL; - result = true; + panel = G_LOADED_PANEL(pygobject_get(self)); - result &= PyDict_AddULongMacro(obj_type, SPT_RAW); - result &= PyDict_AddULongMacro(obj_type, SPT_TOP); - result &= PyDict_AddULongMacro(obj_type, SPT_CENTER); - result &= PyDict_AddULongMacro(obj_type, SPT_BOTTOM); + g_loaded_panel_scroll_to_cursor(panel, cursor, tweak, move); - return result; + Py_RETURN_NONE; } @@ -129,11 +233,8 @@ static bool py_loaded_panel_define_constants(PyTypeObject *obj_type) PyTypeObject *get_python_loaded_panel_type(void) { static PyMethodDef py_loaded_panel_methods[] = { - { - "scroll_to_cursor", py_loaded_panel_scroll_to_cursor, - METH_VARARGS, - "scroll_to_cursor($self, cursor, tweak, move, /)\n--\n\nEnsure a given address is displayed in the view panel." - }, + LOADED_PANEL_SCROLL_TO_CURSOR_WRAPPER, + LOADED_PANEL_SCROLL_TO_CURSOR_METHOD, { NULL } }; @@ -146,11 +247,11 @@ PyTypeObject *get_python_loaded_panel_type(void) PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "pychrysalide.glibext.LoadedPanel", - //.tp_basicsize = sizeof(PyGObject), + .tp_basicsize = sizeof(PyObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = "PyChrysalide loaded panel", + .tp_doc = LOADED_PANEL_DOC, .tp_methods = py_loaded_panel_methods, .tp_getset = py_loaded_panel_getseters, @@ -180,6 +281,14 @@ bool ensure_python_loaded_panel_is_registered(void) PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ + static GInterfaceInfo info = { /* Paramètres d'inscription */ + + .interface_init = (GInterfaceInitFunc)py_loaded_panel_interface_init, + .interface_finalize = NULL, + .interface_data = NULL, + + }; + type = get_python_loaded_panel_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) @@ -188,10 +297,10 @@ bool ensure_python_loaded_panel_is_registered(void) dict = PyModule_GetDict(module); - if (!register_interface_for_pygobject(dict, G_TYPE_LOADED_PANEL, type)) + if (!register_interface_for_pygobject_2(dict, G_TYPE_LOADED_PANEL, type, &info)) return false; - if (!py_loaded_panel_define_constants(type)) + if (!define_loaded_panel_constants(type)) return false; } -- cgit v0.11.2-87-g4458