From 333e68541e376a7b86703fad8e917f71c0f243d0 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 5 Dec 2020 11:28:15 +0100 Subject: Extended the plugin API to include some panel events. --- plugins/pychrysalide/constants.c | 3 + plugins/pychrysalide/plugin.c | 139 +++++++++++++++++++++++++++++++++++++++ src/gui/panel.c | 7 ++ src/plugins/pglist.h | 8 +++ src/plugins/plugin-def.h | 11 ++++ src/plugins/plugin-int.h | 8 +++ src/plugins/plugin.c | 95 ++++++++++++++++++++++++++ src/plugins/plugin.h | 7 ++ 8 files changed, 278 insertions(+) diff --git a/plugins/pychrysalide/constants.c b/plugins/pychrysalide/constants.c index e31a8fe..ded25c3 100644 --- a/plugins/pychrysalide/constants.c +++ b/plugins/pychrysalide/constants.c @@ -57,7 +57,10 @@ bool define_plugin_module_constants(PyTypeObject *type) if (result) result = add_const_to_group(values, "PLUGIN_INIT", PGA_PLUGIN_INIT); if (result) result = add_const_to_group(values, "PLUGIN_EXIT", PGA_PLUGIN_EXIT); if (result) result = add_const_to_group(values, "NATIVE_LOADED", PGA_NATIVE_LOADED); + if (result) result = add_const_to_group(values, "TYPE_BUILDING", PGA_TYPE_BUILDING); if (result) result = add_const_to_group(values, "GUI_THEME", PGA_GUI_THEME); + if (result) result = add_const_to_group(values, "PANEL_CREATION", PGA_PANEL_CREATION); + if (result) result = add_const_to_group(values, "PANEL_DOCKING", PGA_PANEL_DOCKING); if (result) result = add_const_to_group(values, "CONTENT_EXPLORER", PGA_CONTENT_EXPLORER); if (result) result = add_const_to_group(values, "CONTENT_RESOLVER", PGA_CONTENT_RESOLVER); if (result) result = add_const_to_group(values, "CONTENT_ANALYZED", PGA_CONTENT_ANALYZED); diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c index a552aaa..b3bcce5 100644 --- a/plugins/pychrysalide/plugin.c +++ b/plugins/pychrysalide/plugin.c @@ -63,6 +63,12 @@ static void py_plugin_module_notify_native_loaded_wrapper(GPluginModule *, Plugi /* Complète une liste de resources pour thème. */ static void py_plugin_module_include_theme_wrapper(const GPluginModule *, PluginAction, gboolean, char ***, size_t *); +/* Rend compte de la création d'un panneau. */ +static void py_plugin_module_notify_panel_creation_wrapper(const GPluginModule *, PluginAction, GPanelItem *); + +/* Rend compte d'un affichage ou d'un retrait de panneau. */ +static void py_plugin_module_notify_panel_docking_wrapper(const GPluginModule *, PluginAction, GPanelItem *, bool); + /* Procède à une opération liée à un contenu binaire. */ static void py_plugin_module_handle_binary_content_wrapper(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *); @@ -228,6 +234,8 @@ static void py_plugin_module_init_gclass(GPluginModuleClass *class, gpointer unu class->native_loaded = py_plugin_module_notify_native_loaded_wrapper; class->include_theme = py_plugin_module_include_theme_wrapper; + class->notify_panel = py_plugin_module_notify_panel_creation_wrapper; + class->notify_docking = py_plugin_module_notify_panel_docking_wrapper; class->handle_content = py_plugin_module_handle_binary_content_wrapper; class->handle_loaded = py_plugin_module_handle_loaded_content_wrapper; @@ -287,6 +295,8 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds) " have to be defined for new classes:\n" \ "* pychrysalide.PluginModule._notify_native_loaded();\n" \ "* pychrysalide.PluginModule._include_theme();\n" \ + "* pychrysalide.PluginModule._on_panel_creation;\n" \ + "* pychrysalide.PluginModule._on_panel_docking();\n" \ "* pychrysalide.PluginModule._handle_binary_content();\n" \ "* pychrysalide.PluginModule._handle_loaded_content();\n" \ "* pychrysalide.PluginModule._handle_format_analysis();\n" \ @@ -530,6 +540,133 @@ static void py_plugin_module_include_theme_wrapper(const GPluginModule *plugin, /****************************************************************************** * * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* item = nouveau panneau créé. * +* * +* Description : Rend compte de la création d'un panneau. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_plugin_module_notify_panel_creation_wrapper(const GPluginModule *plugin, PluginAction action, GPanelItem *item) +{ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan d'exécution */ + +#define PLUGIN_MODULE_ON_PANEL_CREATION_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _on_panel_creation, "$self, action, item, /", \ + METH_VARARGS, \ + "Abstract method called when a new instance of panel is created.\n" \ + "\n" \ + "The expected *action* is a pychrysalide.PluginModule.PluginAction" \ + " value and the *item* is a pychrysalide.gui.PanelItem instance.\n" \ + "\n" \ + "This method has to be defined in order to handle action such as" \ + " *PANEL_CREATION*." \ +) + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(plugin)); + + if (has_python_method(pyobj, "_on_panel_creation")) + { + args = PyTuple_New(2); + + PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(item))); + + pyret = run_python_method(pyobj, "_on_panel_creation", args); + + Py_XDECREF(pyret); + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* item = panneau marqué par un changement d'affichage. * +* dock = indique une accroche et non un décrochage. * +* * +* Description : Rend compte d'un affichage ou d'un retrait de panneau. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_plugin_module_notify_panel_docking_wrapper(const GPluginModule *plugin, PluginAction action, GPanelItem *item, bool dock) +{ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pydock; /* Valeur booléenne à joindre */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan d'exécution */ + +#define PLUGIN_MODULE_ON_PANEL_DOCKING_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _on_panel_docking, "$self, action, item, dock, /", \ + METH_VARARGS, \ + "Abstract method called when a panel is docked or undocked into" \ + " the Chrysalide main graphical interface.\n" \ + "\n" \ + "The expected *action* is a pychrysalide.PluginModule.PluginAction" \ + " value, the *item* is a pychrysalide.gui.PanelItem instance and" \ + " the *dock* parameter indicates if the panel request a docking" \ + " operation or an undocking one.\n" \ + "\n" \ + "This method has to be defined in order to handle action such as" \ + " *PANEL_DOCKING*." \ +) + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(plugin)); + + if (has_python_method(pyobj, "_on_panel_docking")) + { + args = PyTuple_New(3); + + pydock = (dock ? Py_True : Py_False); + Py_INCREF(pydock); + + PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(action)); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(item))); + PyTuple_SetItem(args, 2, pydock); + + pyret = run_python_method(pyobj, "_on_panel_docking", args); + + Py_XDECREF(pyret); + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + +} + + +/****************************************************************************** +* * * Paramètres : plugin = greffon à manipuler. * * action = type d'action attendue. * * content = contenu binaire à traiter. * @@ -1494,6 +1631,8 @@ PyTypeObject *get_python_plugin_module_type(void) static PyMethodDef py_plugin_module_methods[] = { PLUGIN_MODULE_NOTIFY_NATIVE_LOADED_WRAPPER, PLUGIN_MODULE_INCLUDE_THEME_WRAPPER, + PLUGIN_MODULE_ON_PANEL_CREATION_WRAPPER, + PLUGIN_MODULE_ON_PANEL_DOCKING_WRAPPER, PLUGIN_MODULE_HANDLE_BINARY_CONTENT_WRAPPER, PLUGIN_MODULE_HANDLE_LOADED_CONTENT_WRAPPER, PLUGIN_MODULE_HANDLE_BINARY_FORMAT_ANALYSIS_WRAPPER, diff --git a/src/gui/panel.c b/src/gui/panel.c index a509f40..976a2d7 100644 --- a/src/gui/panel.c +++ b/src/gui/panel.c @@ -38,6 +38,7 @@ #include "../gtkext/gtkdockable-int.h" #include "../gtkext/named.h" #include "../plugins/dt.h" +#include "../plugins/pglist.h" @@ -601,6 +602,8 @@ GPanelItem *g_panel_item_new(GType type, const char *path) register_editor_item(G_EDITOR_ITEM(result)); + notify_panel_creation(result); + singleton: if (path != NULL) @@ -818,6 +821,8 @@ void g_panel_item_dock(GPanelItem *item) if (G_PANEL_ITEM_GET_CLASS(item)->ack_dock != NULL) G_PANEL_ITEM_GET_CLASS(item)->ack_dock(item); + notify_panel_docking(item, true); + } @@ -895,6 +900,8 @@ void g_panel_item_undock(GPanelItem *item) if (G_PANEL_ITEM_GET_CLASS(item)->ack_undock != NULL) G_PANEL_ITEM_GET_CLASS(item)->ack_undock(item); + notify_panel_docking(item, false); + personality = gtk_panel_item_class_get_personality(G_PANEL_ITEM_GET_CLASS(item)); if (personality != PIP_PERSISTENT_SINGLETON) diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h index fd8e30a..ccf854f 100644 --- a/src/plugins/pglist.h +++ b/src/plugins/pglist.h @@ -118,6 +118,14 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); #define include_plugin_theme(d, r, c) \ process_all_plugins_for(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c) +/* DPS_RUNNING */ + +#define notify_panel_creation(i) \ + process_all_plugins_for(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i) + +#define notify_panel_docking(i, d) \ + process_all_plugins_for(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d) + /* DPS_CONTENT */ #define handle_binary_content(a, c, i, s) \ diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index 5a2dc54..e99d7b1 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -79,6 +79,7 @@ typedef uint32_t plugin_action_t; /* DPC_GUI */ #define DPS_SETUP DEFINE_PLUGIN_SUB_CATEGORY(0) +#define DPS_RUNNING DEFINE_PLUGIN_SUB_CATEGORY(1) /* DPC_BINARY_PROCESSING */ @@ -133,6 +134,16 @@ typedef enum _PluginAction PGA_GUI_THEME = DPC_GUI | DPS_SETUP | DEFINE_PLUGIN_ACTION(0), /** + * DPC_GUI | DPS_RUNNING + */ + + /* Accrochage / décrochage de panneaux */ + PGA_PANEL_CREATION = DPC_GUI | DPS_RUNNING | DEFINE_PLUGIN_ACTION(0), + + /* Accrochage / décrochage de panneaux */ + PGA_PANEL_DOCKING = DPC_GUI | DPS_RUNNING | DEFINE_PLUGIN_ACTION(1), + + /** * DPC_BINARY_PROCESSING | DPS_CONTENT */ diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index 129e155..9dd9173 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -60,6 +60,12 @@ typedef void (* pg_handle_loaded_fc) (const GPluginModule *, PluginAction, GLoad /* Complète une liste de resources pour thème. */ typedef void (* pg_include_theme_fc) (const GPluginModule *, PluginAction, gboolean, char ***, size_t *); +/* Rend compte de la création d'un panneau. */ +typedef void (* pg_notify_panel_fc) (const GPluginModule *, PluginAction, GPanelItem *); + +/* Rend compte d'un affichage ou d'un retrait de panneau. */ +typedef void (* pg_notify_docking_fc) (const GPluginModule *, PluginAction, GPanelItem *, bool); + /* Assure l'interprétation d'un format en différé. */ typedef bool (* pg_handle_format_analysis_fc) (const GPluginModule *, PluginAction, GKnownFormat *, wgroup_id_t, GtkStatusStack *); @@ -107,6 +113,8 @@ struct _GPluginModuleClass pg_get_modname_fc get_modname; /* Fourniture du nom brut */ pg_include_theme_fc include_theme; /* Extension d'un thème */ + pg_notify_panel_fc notify_panel; /* Création de panneau */ + pg_notify_docking_fc notify_docking; /* Affichage ou retrait */ pg_handle_content_fc handle_content; /* Explorations ou résolutions */ pg_handle_loaded_fc handle_loaded; /* Traitement de contenu chargé*/ diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index df593ea..8b3654e 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -373,6 +373,28 @@ GPluginModule *g_plugin_module_new(const gchar *filename) break; + case DPS_RUNNING: + + switch (action) + { + case PGA_PANEL_CREATION: + valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_creation"); + break; + + case PGA_PANEL_DOCKING: + valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_docking"); + break; + + default: + log_variadic_message(LMT_WARNING, + _("Unknown action '0x%02x' in plugin '%s'..."), + interface->actions[i], filename); + break; + + } + + break; + default: log_variadic_message(LMT_WARNING, _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); @@ -640,6 +662,28 @@ static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *modu break; + case DPS_RUNNING: + + switch (action) + { + case PGA_PANEL_CREATION: + load_plugin_symbol(module, "chrysalide_plugin_on_panel_creation", + &class->notify_panel); + break; + + case PGA_PANEL_DOCKING: + load_plugin_symbol(module, "chrysalide_plugin_on_panel_docking", + &class->notify_docking); + break; + + default: + assert(false); + break; + + } + + break; + default: assert(false); break; @@ -1270,6 +1314,57 @@ void g_plugin_module_include_theme(const GPluginModule *plugin, PluginAction act /****************************************************************************** * * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* item = nouveau panneau créé. * +* * +* Description : Rend compte de la création d'un panneau. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_plugin_module_notify_panel_creation(const GPluginModule *plugin, PluginAction action, GPanelItem *item) +{ + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + class->notify_panel(plugin, action, item); + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * +* item = panneau marqué par un changement d'affichage. * +* dock = indique une accroche et non un décrochage. * +* * +* Description : Rend compte d'un affichage ou d'un retrait de panneau. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_plugin_module_notify_panel_docking(const GPluginModule *plugin, PluginAction action, GPanelItem *item, bool dock) +{ + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + class->notify_docking(plugin, action, item, dock); + +} + + +/****************************************************************************** +* * * Paramètres : plugin = greffon à manipuler. * * action = type d'action attendue. * * content = contenu binaire à traiter. * diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index f65d0eb..3e8d9c1 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -36,6 +36,7 @@ #include "../format/known.h" #include "../format/preload.h" #include "../gtkext/gtkstatusstack.h" +#include "../gui/panel.h" @@ -114,6 +115,12 @@ gpointer g_plugin_module_build_type_instance(GPluginModule *, PluginAction, GTyp /* Complète une liste de resources pour thème. */ void g_plugin_module_include_theme(const GPluginModule *, PluginAction, gboolean, char ***, size_t *); +/* Rend compte de la création d'un panneau. */ +void g_plugin_module_notify_panel_creation(const GPluginModule *, PluginAction, GPanelItem *); + +/* Rend compte d'un affichage ou d'un retrait de panneau. */ +void g_plugin_module_notify_panel_docking(const GPluginModule *, PluginAction, GPanelItem *, bool); + /* Procède à une opération liée à un contenu binaire. */ void g_plugin_module_handle_binary_content(const GPluginModule *, PluginAction, GBinContent *, wgroup_id_t, GtkStatusStack *); -- cgit v0.11.2-87-g4458