summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/gui
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-12-14 16:38:10 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-12-14 16:38:10 (GMT)
commit97fa09113c7988e4b4639190ba9bc51f9ced4d33 (patch)
tree1b4fe85843b4cdbf685e5116a96c4f387a865561 /plugins/pychrysalide/gui
parente526727b94444030a3ae4dc6d4431cb72aea31e0 (diff)
Extended the Python API to build custom GUI panels.
Diffstat (limited to 'plugins/pychrysalide/gui')
-rw-r--r--plugins/pychrysalide/gui/core/Makefile.am3
-rw-r--r--plugins/pychrysalide/gui/core/module.c2
-rw-r--r--plugins/pychrysalide/gui/core/panels.c122
-rw-r--r--plugins/pychrysalide/gui/core/panels.h39
-rw-r--r--plugins/pychrysalide/gui/editem.c296
-rw-r--r--plugins/pychrysalide/gui/editem.h14
-rw-r--r--plugins/pychrysalide/gui/panels/panel.c213
-rw-r--r--plugins/pychrysalide/gui/panels/panel.h3
8 files changed, 509 insertions, 183 deletions
diff --git a/plugins/pychrysalide/gui/core/Makefile.am b/plugins/pychrysalide/gui/core/Makefile.am
index 08e50f1..4f7e05b 100644
--- a/plugins/pychrysalide/gui/core/Makefile.am
+++ b/plugins/pychrysalide/gui/core/Makefile.am
@@ -3,7 +3,8 @@ noinst_LTLIBRARIES = libpychrysaguicore.la
libpychrysaguicore_la_SOURCES = \
items.h items.c \
- module.h module.c
+ module.h module.c \
+ panels.h panels.c
libpychrysaguicore_la_LDFLAGS =
diff --git a/plugins/pychrysalide/gui/core/module.c b/plugins/pychrysalide/gui/core/module.c
index f90c70c..8a28c08 100644
--- a/plugins/pychrysalide/gui/core/module.c
+++ b/plugins/pychrysalide/gui/core/module.c
@@ -29,6 +29,7 @@
#include "items.h"
+#include "panels.h"
#include "../../helpers.h"
@@ -89,6 +90,7 @@ bool populate_gui_core_module(void)
result = true;
if (result) result = ensure_python_items_is_registered();
+ if (result) result = populate_gui_core_module_with_panels();
assert(result);
diff --git a/plugins/pychrysalide/gui/core/panels.c b/plugins/pychrysalide/gui/core/panels.c
new file mode 100644
index 0000000..3b88b18
--- /dev/null
+++ b/plugins/pychrysalide/gui/core/panels.c
@@ -0,0 +1,122 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * panels.c - équivalent Python du fichier "gui/core/panels.c"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "panels.h"
+
+
+#include <pygobject.h>
+
+
+#include <core/params.h>
+#include <gui/core/panels.h>
+
+
+#include "../../access.h"
+#include "../../helpers.h"
+#include "../panels/panel.h"
+
+
+
+/* Enregistre un panneau comme partie intégrante de l'éditeur. */
+static PyObject *py_panels_register_item(PyObject *, PyObject *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Enregistre un panneau comme partie intégrante de l'éditeur. *
+* *
+* Retour : None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_panels_register_item(PyObject *self, PyObject *args)
+{
+ GPanelItem *item; /* Panneau à traiter */
+ GGenConfig *config; /* Configuration à consulter */
+ int ret; /* Bilan de lecture des args. */
+
+ config = NULL;
+
+ ret = PyArg_ParseTuple(args, "O&", convert_to_panel_item, &item);
+ if (!ret) return NULL;
+
+ if (config == NULL)
+ config = get_main_configuration();
+
+ register_panel_item(item, config);
+
+ /**
+ * Si Python ne voit plus la variable représentant le panneau utilisée,
+ * il va la supprimer, ce qui va supprimer le composant GTK.
+ *
+ * On sera donc en situation de Use-After-Free, dont les conséquences
+ * arrivent très vite.
+ */
+ pygobject_new(G_OBJECT(item));
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Définit une extension du module 'gui.core' à compléter. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_gui_core_module_with_panels(void)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Module à recompléter */
+
+ static PyMethodDef py_panels_methods[] = {
+
+ { "register_panel", py_panels_register_item,
+ METH_VARARGS,
+ "register_panel(item, config, /)\n--\n\nRegister a panel for the GUI."
+ },
+ { NULL }
+
+ };
+
+ module = get_access_to_python_module("pychrysalide.gui.core");
+
+ result = register_python_module_methods(module, py_panels_methods);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/gui/core/panels.h b/plugins/pychrysalide/gui/core/panels.h
new file mode 100644
index 0000000..fd17908
--- /dev/null
+++ b/plugins/pychrysalide/gui/core/panels.h
@@ -0,0 +1,39 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * panels.h - prototypes pour l'équivalent Python du fichier "gui/core/panels.h"
+ *
+ * Copyright (C) 2018 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_PYCHRYSALIDE_GUI_CORE_PANELS_H
+#define _PLUGINS_PYCHRYSALIDE_GUI_CORE_PANELS_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Définit une extension du module 'gui.core' à compléter. */
+bool populate_gui_core_module_with_panels(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_GUI_CORE_PANELS_H */
diff --git a/plugins/pychrysalide/gui/editem.c b/plugins/pychrysalide/gui/editem.c
index c60d678..986d1cb 100644
--- a/plugins/pychrysalide/gui/editem.c
+++ b/plugins/pychrysalide/gui/editem.c
@@ -33,41 +33,40 @@
#include "../access.h"
#include "../helpers.h"
+#include "../pychrysa.h"
#include "../analysis/binary.h"
#include "../gtkext/displaypanel.h"
-/* Réagit à un changement du binaire courant. */
-static void _change_editor_item_content_python_wrapper(GEditorItem *, GLoadedContent *, GLoadedContent *);
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
-/* Réagit à un changement de vue. */
-static void _change_editor_item_view_python_wrapper(GEditorItem *, GLoadedPanel *, GLoadedPanel *);
-/* Réagit à un changement de contenu. */
-static void _update_editor_item_view_python_wrapper(GEditorItem *, GLoadedPanel *);
+/* Réagit à un changement de contenu chargé en cours d'analyse. */
+static void py_editor_item_change_content_wrapper(GEditorItem *, GLoadedContent *, GLoadedContent *);
/* Réagit à un changement de contenu chargé en cours d'analyse. */
-static PyObject *py_editor_item_change_content(PyObject *, PyObject *);
+static void py_editor_item_change_content_wrapper(GEditorItem *, GLoadedContent *, GLoadedContent *);
/* Réagit à un changement de vue du contenu en cours d'analyse. */
-static PyObject *py_editor_item_change_view(PyObject *, PyObject *);
+static void py_editor_item_change_view_wrapper(GEditorItem *, GLoadedPanel *, GLoadedPanel *);
/* Réagit à une modification de la vue du contenu analysé. */
-static PyObject *py_editor_item_update_view(PyObject *, PyObject *);
+static void py_editor_item_update_view_wrapper(GEditorItem *, GLoadedPanel *);
+
-/* Procède à l'enregistrement d'un élément reactif de l'éditeur. */
-static PyObject *py_editor_item_register(PyObject *, PyObject *);
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
-* Paramètres : item = élément à actualiser. *
-* old = ancien contenu chargé analysé. *
-* new = nouveau contenu chargé à analyser. *
+* Paramètres : class = classe à initialiser. *
+* unused = données non utilisées ici. *
* *
-* Description : Réagit à un changement du binaire courant. *
+* Description : Initialise la classe des éléménts pour l'interface graphique.*
* *
* Retour : - *
* *
@@ -75,43 +74,22 @@ static PyObject *py_editor_item_register(PyObject *, PyObject *);
* *
******************************************************************************/
-static void _change_editor_item_content_python_wrapper(GEditorItem *item, GLoadedContent *old, GLoadedContent *new)
+void py_editor_item_init_gclass(GEditorItemClass *class, gpointer unused)
{
- PyObject *target; /* Version Python de l'élément */
- PyObject *args; /* Arguments pour l'appel */
- PyObject *value; /* Retour obtenu */
-
- /**
- * Normalement, l'objet Python est enregistré dans la liste de Chrysalide
- * des éléments d'éditeur, via py_editor_item_register(), donc son compteur
- * de références doit le maintenir en vie.
- *
- * On peut donc le récupérer directement depuis l'instance GLib, sans passer
- * par la procédure de pygobject, qui obligerait à connaître le type précis
- * de l'instance GLib manipulée.
- */
- target = pygobject_new(G_OBJECT(item));
-
- args = PyTuple_New(2);
- PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(old)));
- PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(new)));
-
- value = run_python_method(target, "change_content", args);
-
- Py_XDECREF(value);
- Py_DECREF(args);
- Py_DECREF(target);
+ class->change_content = py_editor_item_change_content_wrapper;
+ class->change_view = py_editor_item_change_view_wrapper;
+ class->update_view = py_editor_item_update_view_wrapper;
}
/******************************************************************************
* *
-* Paramètres : item = élément à actualiser. *
-* old = ancienne vue du contenu chargé analysé. *
-* new = nouvelle vue du contenu chargé analysé. *
+* Paramètres : item = instance à consulter. *
+* old = ancien contenu chargé analysé. *
+* new = nouveau contenu chargé à analyser. *
* *
-* Description : Réagit à un changement de vue. *
+* Description : Réagit à un changement de contenu chargé en cours d'analyse. *
* *
* Retour : - *
* *
@@ -119,42 +97,64 @@ static void _change_editor_item_content_python_wrapper(GEditorItem *item, GLoade
* *
******************************************************************************/
-static void _change_editor_item_view_python_wrapper(GEditorItem *item, GLoadedPanel *old, GLoadedPanel *new)
+static void py_editor_item_change_content_wrapper(GEditorItem *item, GLoadedContent *old, GLoadedContent *new)
{
- PyObject *target; /* Version Python de l'élément */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyThreadState *tstate; /* Contexte d'environnement */
+ PyObject *pyold; /* Conversion ou None */
+ PyObject *pynew; /* Conversion ou None */
PyObject *args; /* Arguments pour l'appel */
- PyObject *value; /* Retour obtenu */
+ PyObject *pyret; /* Retour de Python */
+
+ pyobj = pygobject_new(G_OBJECT(item));
+
+ tstate = get_pychrysalide_main_tstate();
+
+ if (tstate != NULL)
+ PyEval_RestoreThread(tstate);
+
+ if (has_python_method(pyobj, "_change_content"))
+ {
+ if (old != NULL)
+ pyold = pygobject_new(G_OBJECT(old));
+ else
+ {
+ pyold = Py_None;
+ Py_INCREF(pyold);
+ }
- /**
- * Normalement, l'objet Python est enregistré dans la liste de Chrysalide
- * des éléments d'éditeur, via py_editor_item_register(), donc son compteur
- * de références doit le maintenir en vie.
- *
- * On peut donc le récupérer directement depuis l'instane GLib, sans passer
- * par la procédure de pygobject, qui obligerait à connaître le type précis
- * de l'instance GLib manipulée.
- */
- target = pygobject_new(G_OBJECT(item));
+ if (new != NULL)
+ pynew = pygobject_new(G_OBJECT(new));
+ else
+ {
+ pynew = Py_None;
+ Py_INCREF(pynew);
+ }
+
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pyold);
+ PyTuple_SetItem(args, 1, pynew);
- args = PyTuple_New(2);
- PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(old)));
- PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(new)));
+ pyret = run_python_method(pyobj, "_change_content", args);
- value = run_python_method(target, "change_view", args);
+ Py_DECREF(args);
+ Py_DECREF(pyret);
- Py_XDECREF(value);
- Py_DECREF(args);
- Py_DECREF(target);
+ }
+
+ if (tstate != NULL)
+ PyEval_SaveThread();
}
/******************************************************************************
* *
-* Paramètres : item = élément à actualiser. *
-* panel = vue du contenu chargé analysé modifiée. *
+* Paramètres : item = instance à consulter. *
+* old = ancienne vue du contenu chargé analysé. *
+* new = nouvelle vue du contenu chargé analysé. *
* *
-* Description : Réagit à un changement de contenu. *
+* Description : Réagit à un changement de vue du contenu en cours d'analyse. *
* *
* Retour : - *
* *
@@ -162,79 +162,61 @@ static void _change_editor_item_view_python_wrapper(GEditorItem *item, GLoadedPa
* *
******************************************************************************/
-static void _update_editor_item_view_python_wrapper(GEditorItem *item, GLoadedPanel *panel)
+static void py_editor_item_change_view_wrapper(GEditorItem *item, GLoadedPanel *old, GLoadedPanel *new)
{
- PyObject *target; /* Version Python de l'élément */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyThreadState *tstate; /* Contexte d'environnement */
+ PyObject *pyold; /* Conversion ou None */
+ PyObject *pynew; /* Conversion ou None */
PyObject *args; /* Arguments pour l'appel */
- PyObject *value; /* Retour obtenu */
-
- /**
- * Normalement, l'objet Python est enregistré dans la liste de Chrysalide
- * des éléments d'éditeur, via py_editor_item_register(), donc son compteur
- * de références doit le maintenir en vie.
- *
- * On peut donc le récupérer directement depuis l'instane GLib, sans passer
- * par la procédure de pygobject, qui obligerait à connaître le type précis
- * de l'instance GLib manipulée.
- */
- target = pygobject_new(G_OBJECT(item));
-
- args = PyTuple_New(1);
- PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(panel)));
+ PyObject *pyret; /* Retour de Python */
- value = run_python_method(target, "update_view", args);
+ pyobj = pygobject_new(G_OBJECT(item));
- Py_XDECREF(value);
- Py_DECREF(args);
- Py_DECREF(target);
+ tstate = get_pychrysalide_main_tstate();
-}
+ if (tstate != NULL)
+ PyEval_RestoreThread(tstate);
+ if (has_python_method(pyobj, "_change_view"))
+ {
+ if (old != NULL)
+ pyold = pygobject_new(G_OBJECT(old));
+ else
+ {
+ pyold = Py_None;
+ Py_INCREF(pyold);
+ }
-/******************************************************************************
-* *
-* Paramètres : self = classe représentant un binaire. *
-* args = arguments fournis à l'appel. *
-* *
-* Description : Réagit à un changement de contenu chargé en cours d'analyse. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (new != NULL)
+ pynew = pygobject_new(G_OBJECT(new));
+ else
+ {
+ pynew = Py_None;
+ Py_INCREF(pynew);
+ }
-static PyObject *py_editor_item_change_content(PyObject *self, PyObject *args)
-{
- Py_RETURN_NONE;
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, pyold);
+ PyTuple_SetItem(args, 1, pynew);
-}
+ pyret = run_python_method(pyobj, "_change_view", args);
+ Py_DECREF(args);
+ Py_DECREF(pyret);
-/******************************************************************************
-* *
-* Paramètres : self = classe représentant un binaire. *
-* args = arguments fournis à l'appel. *
-* *
-* Description : Réagit à un changement de vue du contenu en cours d'analyse. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ }
-static PyObject *py_editor_item_change_view(PyObject *self, PyObject *args)
-{
- Py_RETURN_NONE;
+ if (tstate != NULL)
+ PyEval_SaveThread();
}
/******************************************************************************
* *
-* Paramètres : self = classe représentant un binaire. *
-* args = arguments fournis à l'appel. *
+* Paramètres : item = instance à consulter. *
+* panel = vue du contenu chargé analysé modifiée. *
* *
* Description : Réagit à une modification de la vue du contenu analysé. *
* *
@@ -244,44 +226,44 @@ static PyObject *py_editor_item_change_view(PyObject *self, PyObject *args)
* *
******************************************************************************/
-static PyObject *py_editor_item_update_view(PyObject *self, PyObject *args)
+static void py_editor_item_update_view_wrapper(GEditorItem *item, GLoadedPanel *panel)
{
- Py_RETURN_NONE;
+ PyObject *pyobj; /* Objet Python concerné */
+ PyThreadState *tstate; /* Contexte d'environnement */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Retour de Python */
-}
+ pyobj = pygobject_new(G_OBJECT(item));
+ tstate = get_pychrysalide_main_tstate();
-/******************************************************************************
-* *
-* Paramètres : self = classe représentant un binaire. *
-* args = arguments fournis à l'appel. *
-* *
-* Description : Procède à l'enregistrement d'un élément reactif de l'éditeur.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (tstate != NULL)
+ PyEval_RestoreThread(tstate);
-static PyObject *py_editor_item_register(PyObject *self, PyObject *args)
-{
- //GEditorItem *item; /* Version GLib de l'élément */
+ if (has_python_method(pyobj, "_update_view"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(panel)));
- //item = G_EDITOR_ITEM(pygobject_get(self));
+ pyret = run_python_method(pyobj, "_update_view", args);
- //item->update_binary = _change_editor_item_content_python_wrapper;
- //item->update_view = _change_editor_item_view_python_wrapper;
- //item->update_content = _update_editor_item_view_python_wrapper;
+ Py_DECREF(args);
+ Py_DECREF(pyret);
- Py_INCREF(self);
- //register_editor_item(item);
+ }
- Py_RETURN_NONE;
+ if (tstate != NULL)
+ PyEval_SaveThread();
}
+
+/* ---------------------------------------------------------------------------------- */
+/* FONCTIONNALITES D'UN ELEMENT */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
* Paramètres : - *
@@ -297,26 +279,6 @@ static PyObject *py_editor_item_register(PyObject *self, PyObject *args)
PyTypeObject *get_python_editor_item_type(void)
{
static PyMethodDef py_editor_item_methods[] = {
- {
- "change_content", py_editor_item_change_content,
- METH_VARARGS,
- "change_content($self, /)\n--\n\nCalled by Chrysalide on each content change, if the item is registered."
- },
- {
- "change_view", py_editor_item_change_view,
- METH_VARARGS,
- "change_view($self, /)\n--\n\nCalled by Chrysalide on each view change, if the item is registered."
- },
- {
- "update_view", py_editor_item_update_view,
- METH_VARARGS,
- "update_view($self, /)\n--\n\nCalled by Chrysalide on each view content change, if the item is registered."
- },
- {
- "register", py_editor_item_register,
- METH_NOARGS,
- "register($self, /)\n--\n\nregister($self, /)\n--\n\nRegister the item as editor item."
- },
{ NULL }
};
diff --git a/plugins/pychrysalide/gui/editem.h b/plugins/pychrysalide/gui/editem.h
index 9baebee..c272d76 100644
--- a/plugins/pychrysalide/gui/editem.h
+++ b/plugins/pychrysalide/gui/editem.h
@@ -30,6 +30,20 @@
#include <stdbool.h>
+#include <gui/editem.h>
+
+
+
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Initialise la classe des éléments pour l'interface graphique. */
+void py_editor_item_init_gclass(GEditorItemClass *, gpointer);
+
+
+
+/* -------------------------- FONCTIONNALITES D'UN ELEMENT -------------------------- */
+
/* Fournit un accès à une définition de type à diffuser. */
PyTypeObject *get_python_editor_item_type(void);
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 */