summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--plugins/pychrysalide/gui/Makefile.am5
-rw-r--r--plugins/pychrysalide/gui/module.c4
-rw-r--r--plugins/pychrysalide/gui/panel.c90
-rw-r--r--plugins/pychrysalide/gui/panels/Makefile.am19
-rw-r--r--plugins/pychrysalide/gui/panels/module.c101
-rw-r--r--plugins/pychrysalide/gui/panels/module.h42
-rw-r--r--plugins/pychrysalide/gui/panels/updating.c734
-rw-r--r--plugins/pychrysalide/gui/panels/updating.h45
-rw-r--r--plugins/pychrysalide/helpers.c46
-rw-r--r--src/gui/panels/bintree.c23
-rw-r--r--src/gui/panels/errors.c15
-rw-r--r--src/gui/panels/strings.c19
-rw-r--r--src/gui/panels/symbols.c19
-rw-r--r--src/gui/panels/symbols.ui93
-rw-r--r--src/gui/panels/updating-int.h4
-rw-r--r--src/gui/panels/updating.c56
-rw-r--r--src/gui/panels/updating.h4
18 files changed, 1217 insertions, 103 deletions
diff --git a/configure.ac b/configure.ac
index 3837315..e57fbb6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -488,6 +488,7 @@ AC_CONFIG_FILES([Makefile
plugins/pychrysalide/gtkext/graph/Makefile
plugins/pychrysalide/gui/Makefile
plugins/pychrysalide/gui/core/Makefile
+ plugins/pychrysalide/gui/panels/Makefile
plugins/pychrysalide/mangling/Makefile
plugins/python/Makefile
plugins/python/abackup/Makefile
diff --git a/plugins/pychrysalide/gui/Makefile.am b/plugins/pychrysalide/gui/Makefile.am
index ca6bee5..cd8f05d 100644
--- a/plugins/pychrysalide/gui/Makefile.am
+++ b/plugins/pychrysalide/gui/Makefile.am
@@ -9,7 +9,8 @@ libpychrysagui_la_SOURCES = \
panel.h panel.c
libpychrysagui_la_LIBADD = \
- core/libpychrysaguicore.la
+ core/libpychrysaguicore.la \
+ panels/libpychrysaguipanels.la
libpychrysagui_la_LDFLAGS =
@@ -24,4 +25,4 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJE
AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-SUBDIRS = core
+SUBDIRS = core panels
diff --git a/plugins/pychrysalide/gui/module.c b/plugins/pychrysalide/gui/module.c
index 1ff7b1b..365cab6 100644
--- a/plugins/pychrysalide/gui/module.c
+++ b/plugins/pychrysalide/gui/module.c
@@ -28,11 +28,11 @@
#include <assert.h>
-
#include "item.h"
#include "menubar.h"
#include "panel.h"
#include "core/module.h"
+#include "panels/module.h"
#include "../helpers.h"
@@ -74,6 +74,7 @@ bool add_gui_module(PyObject *super)
result = (module != NULL);
if (result) result = add_gui_core_module(module);
+ if (result) result = add_gui_panels_module(module);
if (!result)
Py_XDECREF(module);
@@ -106,6 +107,7 @@ bool populate_gui_module(void)
if (result) result = ensure_python_panel_item_is_registered();
if (result) result = populate_gui_core_module();
+ if (result) result = populate_gui_panels_module();
assert(result);
diff --git a/plugins/pychrysalide/gui/panel.c b/plugins/pychrysalide/gui/panel.c
index 160a7a3..2afb2a1 100644
--- a/plugins/pychrysalide/gui/panel.c
+++ b/plugins/pychrysalide/gui/panel.c
@@ -82,6 +82,12 @@ static PyObject *py_panel_item_dock(PyObject *, PyObject *);
/* Supprime un panneau de l'ensemble affiché. */
static PyObject *py_panel_item_undock(PyObject *, PyObject *);
+/* Bascule l'affichage d'un panneau après sa mise à jour. */
+static PyObject *py_panel_item_switch_to_updated_content(PyObject *, PyObject *);
+
+/* Bascule l'affichage d'un panneau avant sa mise à jour. */
+static PyObject *py_panel_item_switch_to_updating_mask(PyObject *, PyObject *);
+
/* Fournit une indication sur la personnalité du panneau. */
static PyObject *py_panel_item_get_personality(PyObject *, void *);
@@ -670,6 +676,88 @@ static PyObject *py_panel_item_undock(PyObject *self, PyObject *args)
/******************************************************************************
* *
+* Paramètres : self = panneau ciblé par une mise à jour. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Bascule l'affichage d'un panneau avant sa mise à jour. *
+* *
+* Retour : Py_None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_panel_item_switch_to_updating_mask(PyObject *self, PyObject *args)
+{
+ GPanelItem *item; /* Panneau à manipuler */
+
+#define PANEL_ITEM_SWITCH_TO_UPDATING_MASK_METHOD PYTHON_METHOD_DEF \
+( \
+ switch_to_updating_mask, "$self, /", \
+ METH_NOARGS, py_panel_item, \
+ "Switch the panel content display before its update." \
+ "\n" \
+ "The *Gtk.Builder* helper linked to the panel has to define the" \
+ " following widgets:\n" \
+ "* 'stack': a *Gtk.Stack* instance containing the other widget;\n" \
+ "* 'content': the main *Gtk.Widget* used to show the main panel" \
+ " content;\n" \
+ "* 'mask': a widget displayed during computing, like a" \
+ " *Gtk.Spinner* instance." \
+)
+
+ item = G_PANEL_ITEM(pygobject_get(self));
+
+ g_panel_item_switch_to_updating_mask(item);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = panneau ciblé par une mise à jour. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Bascule l'affichage d'un panneau après sa mise à jour. *
+* *
+* Retour : Py_None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_panel_item_switch_to_updated_content(PyObject *self, PyObject *args)
+{
+ GPanelItem *item; /* Panneau à manipuler */
+
+#define PANEL_ITEM_SWITCH_TO_UPDATED_CONTENT_METHOD PYTHON_METHOD_DEF \
+( \
+ switch_to_updated_content, "$self, /", \
+ METH_NOARGS, py_panel_item, \
+ "Switch the panel content display after its update." \
+ "\n" \
+ "The *Gtk.Builder* helper linked to the panel has to define the" \
+ " following widgets:\n" \
+ "* 'stack': a *Gtk.Stack* instance containing the other widget;\n" \
+ "* 'content': the main *Gtk.Widget* used to show the main panel" \
+ " content;\n" \
+ "* 'mask': a widget displayed during computing, like a" \
+ " *Gtk.Spinner* instance." \
+)
+
+ item = G_PANEL_ITEM(pygobject_get(self));
+
+ g_panel_item_switch_to_updated_content(item);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = objet Python concerné par l'appel. *
* closure = non utilisé ici. *
* *
@@ -1023,6 +1111,8 @@ PyTypeObject *get_python_panel_item_type(void)
static PyMethodDef py_panel_item_methods[] = {
PANEL_ITEM_DOCK_METHOD,
PANEL_ITEM_UNDOCK_METHOD,
+ PANEL_ITEM_SWITCH_TO_UPDATING_MASK_METHOD,
+ PANEL_ITEM_SWITCH_TO_UPDATED_CONTENT_METHOD,
{ NULL }
};
diff --git a/plugins/pychrysalide/gui/panels/Makefile.am b/plugins/pychrysalide/gui/panels/Makefile.am
new file mode 100644
index 0000000..a6e3635
--- /dev/null
+++ b/plugins/pychrysalide/gui/panels/Makefile.am
@@ -0,0 +1,19 @@
+
+noinst_LTLIBRARIES = libpychrysaguipanels.la
+
+libpychrysaguipanels_la_SOURCES = \
+ module.h module.c \
+ updating.h updating.c
+
+libpychrysaguipanels_la_LDFLAGS =
+
+
+devdir = $(includedir)/chrysalide-$(subdir)
+
+dev_HEADERS = $(libpychrysaguipanels_la_SOURCES:%c=)
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBPYTHON_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \
+ -I$(top_srcdir)/src
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
diff --git a/plugins/pychrysalide/gui/panels/module.c b/plugins/pychrysalide/gui/panels/module.c
new file mode 100644
index 0000000..f904188
--- /dev/null
+++ b/plugins/pychrysalide/gui/panels/module.c
@@ -0,0 +1,101 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.c - intégration du répertoire panels en tant que module
+ *
+ * Copyright (C) 2020 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 "module.h"
+
+
+#include <assert.h>
+
+
+#include "updating.h"
+#include "../../helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : super = module dont la définition est à compléter. *
+* *
+* Description : Ajoute le module 'gui.panels' à un module Python. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool add_gui_panels_module(PyObject *super)
+{
+ bool result; /* Bilan à retourner */
+ PyObject *module; /* Sous-module mis en place */
+
+#define PYCHRYSALIDE_GUI_PANELS_DOC \
+ "This module defines all the core panels and their helper class" \
+ " pychrysalide.gui.panels.UpdatablePanel as well."
+
+ static PyModuleDef py_chrysalide_gui_panels_module = {
+
+ .m_base = PyModuleDef_HEAD_INIT,
+
+ .m_name = "pychrysalide.gui.panels",
+ .m_doc = PYCHRYSALIDE_GUI_PANELS_DOC,
+
+ .m_size = -1,
+
+ };
+
+ module = build_python_module(super, &py_chrysalide_gui_panels_module);
+
+ result = (module != NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Intègre les objets du module 'gui.panels'. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool populate_gui_panels_module(void)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (result) result = ensure_python_updatable_panel_is_registered();
+
+ assert(result);
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/gui/panels/module.h b/plugins/pychrysalide/gui/panels/module.h
new file mode 100644
index 0000000..e926107
--- /dev/null
+++ b/plugins/pychrysalide/gui/panels/module.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * module.h - prototypes pour l'intégration du répertoire panels en tant que module
+ *
+ * Copyright (C) 2020 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_PANELS_MODULE_H
+#define _PLUGINS_PYCHRYSALIDE_GUI_PANELS_MODULE_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Ajoute le module 'gui.panels' à un module Python. */
+bool add_gui_panels_module(PyObject *);
+
+/* Intègre les objets du module 'gui.panels'. */
+bool populate_gui_panels_module(void);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_GUI_PANELS_MODULE_H */
diff --git a/plugins/pychrysalide/gui/panels/updating.c b/plugins/pychrysalide/gui/panels/updating.c
new file mode 100644
index 0000000..5898575
--- /dev/null
+++ b/plugins/pychrysalide/gui/panels/updating.c
@@ -0,0 +1,734 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * updating.c - équivalent Python du fichier "gui/panels/updating.h"
+ *
+ * Copyright (C) 2020 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 "updating.h"
+
+
+#include <pygobject.h>
+
+
+#include <core/queue.h>
+#include <gui/panels/updating-int.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_updatable_panel_interface_init(GUpdatablePanelIface *, gpointer *);
+
+/* Prépare une opération de mise à jour de panneau. */
+static bool py_updatable_panel_setup_wrapper(const GUpdatablePanel *, unsigned int, size_t *, void **, char **);
+
+/* Obtient le groupe de travail dédié à une mise à jour. */
+static wgroup_id_t py_updatable_panel_get_group_wrapper(const GUpdatablePanel *);
+
+/* Bascule l'affichage d'un panneau avant mise à jour. */
+static void py_updatable_panel_introduce_wrapper(const GUpdatablePanel *, unsigned int, void *);
+
+/* Réalise une opération de mise à jour de panneau. */
+static void py_updatable_panel_process_wrapper(const GUpdatablePanel *, unsigned int, GtkStatusStack *, activity_id_t, void *);
+
+/* Bascule l'affichage d'un panneau après mise à jour. */
+static void py_updatable_panel_conclude_wrapper(GUpdatablePanel *, unsigned int, void *);
+
+/* Supprime les données dynamiques utilisées à la mise à jour. */
+static void py_updatable_panel_clean_data_wrapper(const GUpdatablePanel *, unsigned int, void *);
+
+
+
+/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
+
+
+/* Prépare et lance l'actualisation d'un panneau. */
+static PyObject *py_updatable_panel_run_update(PyObject *, PyObject *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* unused = adresse non utilisée ici. *
+* *
+* Description : Procède à l'initialisation de l'interface de génération. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_updatable_panel_interface_init(GUpdatablePanelIface *iface, gpointer *unused)
+{
+
+#define UPDATABLE_PANEL_DOC \
+ "UpdatablePanel defines an interface as helper for panels updates." \
+ " Panels contents can thus get hidden then restored easily once data" \
+ " is fully processed.\n" \
+ "\n" \
+ "A typical class declaration for a new implementation looks like:\n" \
+ "\n" \
+ " class NewImplem(GObject.Object, UpdatablePanel):\n" \
+ " ...\n" \
+ "\n" \
+ "The following methods have to be defined for new implementations:\n" \
+ "* pychrysalide.gui.panels.UpdatablePanel._setup();\n" \
+ "* pychrysalide.gui.panels.UpdatablePanel._introduce();\n" \
+ "* pychrysalide.gui.panels.UpdatablePanel._process();\n" \
+ "* pychrysalide.gui.panels.UpdatablePanel._conclude();\n" \
+ "* pychrysalide.gui.panels.UpdatablePanel._clean_data().\n" \
+ "\n" \
+ "The following attribute has to be defined for new implementations:\n" \
+ "* pychrysalide.gui.panels.UpdatablePanel._working_group_id.\n" \
+
+ iface->setup = py_updatable_panel_setup_wrapper;
+ iface->get_group = py_updatable_panel_get_group_wrapper;
+ iface->introduce = py_updatable_panel_introduce_wrapper;
+ iface->process = py_updatable_panel_process_wrapper;
+ iface->conclude = py_updatable_panel_conclude_wrapper;
+ iface->clean = py_updatable_panel_clean_data_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau ciblé par une mise à jour. *
+* uid = identifiant de la phase de traitement. *
+* count = nombre d'étapes à prévoir dans le traitement. [OUT] *
+* data = données sur lesquelles s'appuyer ensuite. [OUT] *
+* msg = description du message d'information. [OUT] *
+* *
+* Description : Prépare une opération de mise à jour de panneau. *
+* *
+* Retour : Bilan de la préparation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_updatable_panel_setup_wrapper(const GUpdatablePanel *panel, unsigned int uid, size_t *count, void **data, char **msg)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+ PyObject *item; /* Elément obtenu */
+
+#define UPDATABLE_PANEL_SETUP_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _setup, "$self, uid, /", \
+ METH_VARARGS, \
+ "Abstract method used to prepare an update process for a panel.\n" \
+ "\n" \
+ "The *uid* identifier is an arbitrary number identifying the update" \
+ " process.\n" \
+ "\n" \
+ "The expected result is a tuple containing three items:\n" \
+ "* the number of items to be processed, in order to synchronize with" \
+ " the progress shown in the status bar;\n" \
+ "* an optional object used to store final result (or None);\n" \
+ "* a text message to display as the name of the update operation." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(panel));
+
+ if (has_python_method(pyobj, "_setup"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(uid));
+
+ pyret = run_python_method(pyobj, "_setup", args);
+
+ if (!PyTuple_Check(pyret) || PyTuple_Size(pyret) != 3)
+ {
+ PyErr_SetString(PyExc_ValueError, "the provided quantity has to be a tuple with three items");
+ goto exit;
+ }
+
+ item = PyTuple_GetItem(pyret, 0);
+ if (!PyLong_Check(item)) goto exit;
+
+ *count = PyLong_AsUnsignedLongLong(item);
+
+ item = PyTuple_GetItem(pyret, 1);
+
+ Py_INCREF(item);
+ *data = item;
+
+ item = PyTuple_GetItem(pyret, 2);
+ if (!PyUnicode_Check(item))
+ {
+ Py_DECREF(item);
+ *data = NULL;
+ goto exit;
+ }
+
+ *msg = strdup(PyUnicode_AsUTF8(item));
+
+ result = true;
+
+ exit:
+
+ Py_XDECREF(pyret);
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau ciblé par une mise à jour. *
+* *
+* Description : Obtient le groupe de travail dédié à une mise à jour. *
+* *
+* Retour : Identifiant de groupe de travail. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static wgroup_id_t py_updatable_panel_get_group_wrapper(const GUpdatablePanel *panel)
+{
+ wgroup_id_t result; /* Identifiant à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyattr; /* Attribut de l'objet Python */
+ int ret; /* Bilan d'une conversion */
+
+#define UPDATABLE_PANEL_WORKING_GROUP_ID_ATTRIB_WRAPPER PYTHON_GETTER_WRAPPER_DEF \
+( \
+ _working_group_id, \
+ "Identifier of a dedicated working group processing panel update jobs.\n" \
+ "\n" \
+ "The result has to be an integer." \
+)
+
+ result = DEFAULT_WORK_GROUP;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(panel));
+
+ if (PyObject_HasAttrString(pyobj, "_working_group_id"))
+ {
+ pyattr = PyObject_GetAttrString(pyobj, "_working_group_id");
+
+ if (pyattr != NULL)
+ {
+ ret = PyLong_Check(pyattr);
+
+ if (ret)
+ result = PyLong_AsUnsignedLongLong(pyattr);
+
+ Py_DECREF(pyattr);
+
+ }
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau ciblé par une mise à jour. *
+* uid = identifiant de la phase de traitement. *
+* data = données préparées par l'appelant. *
+* *
+* Description : Bascule l'affichage d'un panneau avant mise à jour. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_updatable_panel_introduce_wrapper(const GUpdatablePanel *panel, unsigned int uid, void *data)
+{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pydata; /* Données au format Python */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define UPDATABLE_PANEL_INTRODUCE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _introduce, "$self, uid, data, /", \
+ METH_VARARGS, \
+ "Abstract method used to introduce the update process; display switch" \
+ " is here an option.\n" \
+ "\n" \
+ "The *uid* identifier is the same identifier provided for a previous" \
+ " call to pychrysalide.gui.panels.UpdatablePanel._setup(), and *data*" \
+ " is an optional object instance." \
+)
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(panel));
+ pydata = (PyObject *)data;
+
+ if (has_python_method(pyobj, "_introduce"))
+ {
+ Py_INCREF(pydata);
+
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(uid));
+ PyTuple_SetItem(args, 1, pydata);
+
+ pyret = run_python_method(pyobj, "_introduce", args);
+
+ Py_XDECREF(pyret);
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau ciblé par une mise à jour. *
+* uid = identifiant de la phase de traitement. *
+* status = barre de statut à tenir informée. *
+* id = identifiant pour le suivi de la progression. *
+* data = données préparées par l'appelant. *
+* *
+* Description : Réalise une opération de mise à jour de panneau. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_updatable_panel_process_wrapper(const GUpdatablePanel *panel, unsigned int uid, GtkStatusStack *status, activity_id_t id, void *data)
+{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pydata; /* Données au format Python */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define UPDATABLE_PANEL_PROCESS_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _process, "$self, uid, status, id, data, /", \
+ METH_VARARGS, \
+ "Abstract method used to perform the computing of data to render.\n" \
+ "\n" \
+ "The *uid* identifier is the same identifier provided for a previous" \
+ " call to pychrysalide.gui.panels.UpdatablePanel._setup(), *status* is" \
+ " a pychrysalide.gtkext.StatusStack instance, *id* refers to the" \
+ " identifier for message display inside the status bar and *data* is" \
+ " an optional object instance.\n" \
+ "\n" \
+ "The method is called from a dedicated processing thread." \
+)
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(panel));
+ pydata = (PyObject *)data;
+
+ if (has_python_method(pyobj, "_process"))
+ {
+ Py_INCREF(pydata);
+
+ args = PyTuple_New(4);
+ PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(uid));
+ PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(status)));
+ PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(id));
+ PyTuple_SetItem(args, 3, pydata);
+
+ pyret = run_python_method(pyobj, "_process", args);
+
+ Py_XDECREF(pyret);
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau ciblé par une mise à jour. *
+* uid = identifiant de la phase de traitement. *
+* data = données préparées par l'appelant. *
+* *
+* Description : Bascule l'affichage d'un panneau après mise à jour. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_updatable_panel_conclude_wrapper(GUpdatablePanel *panel, unsigned int uid, void *data)
+{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pydata; /* Données au format Python */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define UPDATABLE_PANEL_CONCLUDE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _conclude, "$self, uid, data, /", \
+ METH_VARARGS, \
+ "Abstract method used to conclude the update process and to display" \
+ " the computed data.\n" \
+ "\n" \
+ "The *uid* identifier is the same identifier provided for a previous" \
+ " call to pychrysalide.gui.panels.UpdatablePanel._setup(), and *data*" \
+ " is an optional object instance." \
+)
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(panel));
+ pydata = (PyObject *)data;
+
+ if (has_python_method(pyobj, "_conclude"))
+ {
+ Py_INCREF(pydata);
+
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(uid));
+ PyTuple_SetItem(args, 1, pydata);
+
+ pyret = run_python_method(pyobj, "_conclude", args);
+
+ Py_XDECREF(pyret);
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau ciblé par une mise à jour. *
+* uid = identifiant de la phase de traitement. *
+* data = données en place à nettoyer avant suppression. *
+* *
+* Description : Supprime les données dynamiques utilisées à la mise à jour. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void py_updatable_panel_clean_data_wrapper(const GUpdatablePanel *panel, unsigned int uid, void *data)
+{
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pydata; /* Données au format Python */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define UPDATABLE_PANEL_CLEAN_DATA_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _clean_data, "$self, uid, data, /", \
+ METH_VARARGS, \
+ "Abstract method used to delete dynamically generated objects for the" \
+ " panel update.\n" \
+ "\n" \
+ "The *uid* identifier is the same identifier provided for a previous" \
+ " call to pychrysalide.gui.panels.UpdatablePanel._setup(), and *data*" \
+ " is an optional object instance.\n" \
+ "\n" \
+ "As the user *data* reference counter is decreased automatically after" \
+ " this wrapper is called (if existing), there should be no need to" \
+ " define such a wrapper, except if the panel needs some kind of" \
+ " notification at the end of the update or if it still owns a reference"\
+ " to this *data*." \
+)
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(panel));
+ pydata = (PyObject *)data;
+
+ if (has_python_method(pyobj, "_clean_data"))
+ {
+ Py_INCREF(pydata);
+
+ args = PyTuple_New(2);
+ PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(uid));
+ PyTuple_SetItem(args, 1, pydata);
+
+ pyret = run_python_method(pyobj, "_clean_data", args);
+
+ Py_XDECREF(pyret);
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pydata);
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONNEXION AVEC L'API DE PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : self = NULL car méthode statique. *
+* args = paramètres à transmettre à l'appel natif. *
+* *
+* Description : Prépare et lance l'actualisation d'un panneau. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_updatable_panel_run_update(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Désignation à retourner */
+ unsigned int uid; /* Identifiant de mise à jour */
+ int ret; /* Bilan de lecture des args. */
+ GUpdatablePanel *panel; /* Instance à manipuler */
+
+#define UPDATABLE_PANEL_RUN_UPDATE_METHOD PYTHON_METHOD_DEF \
+( \
+ run_update, "self, uid, /", \
+ METH_VARARGS, py_updatable_panel, \
+ "Prepare and run an update for the panel.\n" \
+ "\n" \
+ "The *uid* argument is an arbitrary integer provided" \
+ " as internal identifier for the caller." \
+)
+
+ ret = PyArg_ParseTuple(args, "I", &uid);
+ if (!ret) return NULL;
+
+ panel = G_UPDATABLE_PANEL(pygobject_get(self));
+
+ run_panel_update(panel, uid);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Fournit un accès à une définition de type à diffuser. *
+* *
+* Retour : Définition d'objet pour Python. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PyTypeObject *get_python_updatable_panel_type(void)
+{
+ static PyMethodDef py_updatable_panel_methods[] = {
+ UPDATABLE_PANEL_SETUP_WRAPPER,
+ UPDATABLE_PANEL_INTRODUCE_WRAPPER,
+ UPDATABLE_PANEL_PROCESS_WRAPPER,
+ UPDATABLE_PANEL_CONCLUDE_WRAPPER,
+ UPDATABLE_PANEL_CLEAN_DATA_WRAPPER,
+ UPDATABLE_PANEL_RUN_UPDATE_METHOD,
+ { NULL }
+ };
+
+ static PyGetSetDef py_updatable_panel_getseters[] = {
+ UPDATABLE_PANEL_WORKING_GROUP_ID_ATTRIB_WRAPPER,
+ { NULL }
+ };
+
+ static PyTypeObject py_updatable_panel_type = {
+
+ PyVarObject_HEAD_INIT(NULL, 0)
+
+ .tp_name = "pychrysalide.gui.panels.UpdatablePanel",
+ .tp_basicsize = sizeof(PyObject),
+
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+
+ .tp_doc = UPDATABLE_PANEL_DOC,
+
+ .tp_methods = py_updatable_panel_methods,
+ .tp_getset = py_updatable_panel_getseters,
+
+ };
+
+ return &py_updatable_panel_type;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : module = module dont la définition est à compléter. *
+* *
+* Description : Prend en charge l'objet 'pychrysalide.gui....UpdatablePanel'.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_python_updatable_panel_is_registered(void)
+{
+ PyTypeObject *type; /* Type Python 'LineGenerator' */
+ PyObject *module; /* Module à recompléter */
+ PyObject *dict; /* Dictionnaire du module */
+
+ static GInterfaceInfo info = { /* Paramètres d'inscription */
+
+ .interface_init = (GInterfaceInitFunc)py_updatable_panel_interface_init,
+ .interface_finalize = NULL,
+ .interface_data = NULL,
+
+ };
+
+ type = get_python_updatable_panel_type();
+
+ if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ {
+ module = get_access_to_python_module("pychrysalide.gui.panels");
+
+ dict = PyModule_GetDict(module);
+
+ if (!register_interface_for_pygobject(dict, G_TYPE_UPDATABLE_PANEL, type, &info))
+ return false;
+
+ }
+
+ 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 mécanisme de mise à jour de panneau. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_updatable_panel(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_updatable_panel_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 updatable panel");
+ break;
+
+ case 1:
+ *((GUpdatablePanel **)dst) = G_UPDATABLE_PANEL(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
diff --git a/plugins/pychrysalide/gui/panels/updating.h b/plugins/pychrysalide/gui/panels/updating.h
new file mode 100644
index 0000000..a9e5799
--- /dev/null
+++ b/plugins/pychrysalide/gui/panels/updating.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * updating.h - prototypes pour l'équivalent Python du fichier "gui/panels/updating.h"
+ *
+ * Copyright (C) 2020 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_PANELS_UPDATING_H
+#define _PLUGINS_PYCHRYSALIDE_GUI_PANELS_UPDATING_H
+
+
+#include <Python.h>
+#include <stdbool.h>
+
+
+
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_updatable_panel_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.gui.panels.UpdatablePanel'. */
+bool ensure_python_updatable_panel_is_registered(void);
+
+/* Tente de convertir en générateur de lignes. */
+int convert_to_updatable_panel(PyObject *, void *);
+
+
+
+#endif /* _PLUGINS_PYCHRYSALIDE_GUI_PANELS_UPDATING_H */
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index f811ad3..b2ecbec 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -977,6 +977,11 @@ bool register_class_for_dynamic_pygobject(GType gtype, PyTypeObject *type, PyTyp
PyObject *modname; /* Nom du module du type */
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire dudit module */
+ Py_ssize_t i; /* Boucle de parcours */
+ PyObject *mro_base; /* Base finale effective */
+ GType itype; /* Type d'interface implémentée*/
+ GQuark pyginterface_info_key; /* Clef d'accès non déclarée */
+ const GInterfaceInfo *iinfo; /* Informations associées */
/**
* Lors de l'appel à pygobject_register_class(), PyGObject remplace systématiquement
@@ -1023,6 +1028,47 @@ bool register_class_for_dynamic_pygobject(GType gtype, PyTypeObject *type, PyTyp
Py_TYPE(type) = legacy_parent;
+ /**
+ * Comme la mise en place dynamique de nouveau GType court-circuite les
+ * mécanismes internes de pygobject, les interfaces implémentées ne sont
+ * nominalement plus complétées.
+ *
+ * On reprend donc la logique copiée depuis le contenu de la fonction
+ * pyg_type_add_interfaces() du fichier "pygobject-3.22.0/gi/gobjectmodule.c".
+ */
+
+ for (i = 0; i < PyTuple_GET_SIZE(type->tp_mro); i++)
+ {
+ mro_base = PyTuple_GET_ITEM(type->tp_mro, i);
+
+ if (!PyType_Check(mro_base))
+ continue;
+
+ itype = pyg_type_from_object(mro_base);
+
+ if (itype == G_TYPE_INTERFACE)
+ continue;
+
+ if (!G_TYPE_IS_INTERFACE(itype))
+ continue;
+
+ if (!g_type_is_a(gtype, itype))
+ {
+ /**
+ * Reproduction de pyg_lookup_interface_info().
+ */
+
+ pyginterface_info_key = g_quark_from_static_string("PyGInterface::info");
+
+ iinfo = g_type_get_qdata(itype, pyginterface_info_key);
+ assert(iinfo != NULL);
+
+ g_type_add_interface_static(gtype, itype, iinfo);
+
+ }
+
+ }
+
return result;
}
diff --git a/src/gui/panels/bintree.c b/src/gui/panels/bintree.c
index db5e774..c31bd88 100644
--- a/src/gui/panels/bintree.c
+++ b/src/gui/panels/bintree.c
@@ -190,7 +190,7 @@ struct _bintree_update_data
static bool is_bintree_column_matching(const bintree_update_data *, GBinPortion *, gint, regmatch_t *);
/* Prépare une opération de mise à jour de panneau. */
-static const char *g_bintree_panel_setup(const GBintreePanel *, unsigned int, size_t *, bintree_update_data **);
+static bool g_bintree_panel_setup(const GBintreePanel *, unsigned int, size_t *, bintree_update_data **, char **);
/* Bascule l'affichage d'un panneau avant mise à jour. */
static void g_bintree_panel_introduce(const GBintreePanel *, unsigned int, bintree_update_data *);
@@ -202,7 +202,7 @@ static void g_bintree_panel_process(const GBintreePanel *, unsigned int, GtkStat
static void g_bintree_panel_conclude(GBintreePanel *, unsigned int, bintree_update_data *);
/* Supprime les données dynamiques utilisées à la mise à jour. */
-static void g_bintree_panel_clean_data(GUpdatablePanel *, unsigned int, bintree_update_data *);
+static void g_bintree_panel_clean_data(const GUpdatablePanel *, unsigned int, bintree_update_data *);
@@ -1132,24 +1132,27 @@ static bool is_bintree_column_matching(const bintree_update_data *data, GBinPort
* uid = identifiant de la phase de traitement. *
* count = nombre d'étapes à prévoir dans le traitement. [OUT] *
* data = données sur lesquelles s'appuyer ensuite. [OUT] *
+* msg = description du message d'information. [OUT] *
* *
* Description : Prépare une opération de mise à jour de panneau. *
* *
-* Retour : Description du message d'information. *
+* Retour : Bilan de la préparation. *
* *
* Remarques : - *
* *
******************************************************************************/
-static const char *g_bintree_panel_setup(const GBintreePanel *panel, unsigned int uid, size_t *count, bintree_update_data **data)
+static bool g_bintree_panel_setup(const GBintreePanel *panel, unsigned int uid, size_t *count, bintree_update_data **data, char **msg)
{
- const char *result; /* Message à retourner */
+ bool result; /* Bilan à retourner */
#ifndef NDEBUG
int ret; /* Bilan de mise en place */
#endif
GtkBuilder *builder; /* Constructeur utilisé */
GtkTreeView *treeview; /* Arborescence graphique */
+ result = true;
+
*data = malloc(sizeof(bintree_update_data));
switch (uid)
@@ -1159,7 +1162,7 @@ static const char *g_bintree_panel_setup(const GBintreePanel *panel, unsigned in
*count = 0;
(*data)->count = 0;
- result = _("Loading portions contained in the binary format...");
+ *msg = strdup(_("Loading portions contained in the binary format..."));
break;
@@ -1168,20 +1171,20 @@ static const char *g_bintree_panel_setup(const GBintreePanel *panel, unsigned in
*count = panel->count;
(*data)->count = panel->count;
- result = _("Filtering portions contained in the binary format...");
+ *msg = strdup(_("Filtering portions contained in the binary format..."));
break;
default: /* Pour GCC... */
assert(false);
- result = "";
+ result = false;
break;
}
if (G_PANEL_ITEM(panel)->filter != NULL)
{
- (*data)->filter = (regex_t *)malloc(sizeof(regex_t));
+ (*data)->filter = malloc(sizeof(regex_t));
#ifndef NDEBUG
ret = regcomp((*data)->filter, G_PANEL_ITEM(panel)->filter, REG_EXTENDED | REG_ICASE);
@@ -1375,7 +1378,7 @@ static void g_bintree_panel_conclude(GBintreePanel *panel, unsigned int uid, bin
* *
******************************************************************************/
-static void g_bintree_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, bintree_update_data *data)
+static void g_bintree_panel_clean_data(const GUpdatablePanel *panel, unsigned int uid, bintree_update_data *data)
{
size_t i; /* Boucle de parcours */
diff --git a/src/gui/panels/errors.c b/src/gui/panels/errors.c
index d567511..2b5353f 100644
--- a/src/gui/panels/errors.c
+++ b/src/gui/panels/errors.c
@@ -178,7 +178,7 @@ struct _error_update_data
/* Prépare une opération de mise à jour de panneau. */
-static const char *g_error_panel_setup(const GErrorPanel *, unsigned int, size_t *, error_update_data **);
+static bool g_error_panel_setup(const GErrorPanel *, unsigned int, size_t *, error_update_data **, char **);
/* Bascule l'affichage d'un panneau avant mise à jour. */
static void g_error_panel_introduce(const GErrorPanel *, unsigned int, error_update_data *);
@@ -1046,6 +1046,7 @@ static void on_error_selection_changed(GtkTreeSelection *selection, gpointer unu
* uid = identifiant de la phase de traitement. *
* count = nombre d'étapes à prévoir dans le traitement. [OUT] *
* data = données sur lesquelles s'appuyer ensuite. [OUT] *
+* msg = description du message d'information. [OUT] *
* *
* Description : Prépare une opération de mise à jour de panneau. *
* *
@@ -1055,14 +1056,16 @@ static void on_error_selection_changed(GtkTreeSelection *selection, gpointer unu
* *
******************************************************************************/
-static const char *g_error_panel_setup(const GErrorPanel *panel, unsigned int uid, size_t *count, error_update_data **data)
+static bool g_error_panel_setup(const GErrorPanel *panel, unsigned int uid, size_t *count, error_update_data **data, char **msg)
{
- const char *result; /* Message à retourner */
+ bool result; /* Bilan à retourner */
GBinFormat *format; /* Format du binaire */
size_t fcount; /* Quantité d'erreurs #1 */
GArchProcessor *proc; /* Architecture du binaire */
size_t pcount; /* Quantité d'erreurs #2 */
+ result = true;
+
*data = malloc(sizeof(error_update_data));
switch (uid)
@@ -1087,7 +1090,7 @@ static const char *g_error_panel_setup(const GErrorPanel *panel, unsigned int ui
*count = fcount + pcount;
- result = _("Loading errors occurred during the disassembling process...");
+ *msg = strdup(_("Loading errors occurred during the disassembling process..."));
(*data)->count = *count;
(*data)->kept = 0;
@@ -1098,7 +1101,7 @@ static const char *g_error_panel_setup(const GErrorPanel *panel, unsigned int ui
*count = panel->count;
- result = _("Filtering errors occurred during the disassembling process...");
+ *msg = strdup(_("Filtering errors occurred during the disassembling process..."));
(*data)->count = panel->count;
(*data)->kept = 0;
@@ -1107,7 +1110,7 @@ static const char *g_error_panel_setup(const GErrorPanel *panel, unsigned int ui
default: /* Pour GCC... */
assert(false);
- result = "";
+ result = false;
break;
}
diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c
index 33b715b..f9d6b00 100644
--- a/src/gui/panels/strings.c
+++ b/src/gui/panels/strings.c
@@ -211,7 +211,7 @@ static bool is_string_name_matching(const strings_update_data *, GtkTreeModel *,
static bool is_string_value_matching(const strings_update_data *, GtkTreeModel *, GtkTreeIter *, regmatch_t *);
/* Prépare une opération de mise à jour de panneau. */
-static const char *g_strings_panel_setup(const GStringsPanel *, unsigned int, size_t *, strings_update_data **);
+static bool g_strings_panel_setup(const GStringsPanel *, unsigned int, size_t *, strings_update_data **, char **);
/* Bascule l'affichage d'un panneau avant mise à jour. */
static void g_strings_panel_introduce(const GStringsPanel *, unsigned int, strings_update_data *);
@@ -223,7 +223,7 @@ static void g_strings_panel_process(const GStringsPanel *, unsigned int, GtkStat
static void g_strings_panel_conclude(GStringsPanel *, unsigned int, strings_update_data *);
/* Supprime les données dynamiques utilisées à la mise à jour. */
-static void g_strings_panel_clean_data(GUpdatablePanel *, unsigned int, strings_update_data *);
+static void g_strings_panel_clean_data(const GUpdatablePanel *, unsigned int, strings_update_data *);
@@ -1526,6 +1526,7 @@ static bool is_string_value_matching(const strings_update_data *data, GtkTreeMod
* uid = identifiant de la phase de traitement. *
* count = nombre d'étapes à prévoir dans le traitement. [OUT] *
* data = données sur lesquelles s'appuyer ensuite. [OUT] *
+* msg = description du message d'information. [OUT] *
* *
* Description : Prépare une opération de mise à jour de panneau. *
* *
@@ -1535,14 +1536,16 @@ static bool is_string_value_matching(const strings_update_data *data, GtkTreeMod
* *
******************************************************************************/
-static const char *g_strings_panel_setup(const GStringsPanel *panel, unsigned int uid, size_t *count, strings_update_data **data)
+static bool g_strings_panel_setup(const GStringsPanel *panel, unsigned int uid, size_t *count, strings_update_data **data, char **msg)
{
- const char *result; /* Message à retourner */
+ bool result; /* Bilan à retourner */
GBinFormat *format; /* Format du binaire */
#ifndef NDEBUG
int ret; /* Bilan de mise en place */
#endif
+ result = true;
+
*data = malloc(sizeof(strings_update_data));
switch (uid)
@@ -1559,7 +1562,7 @@ static const char *g_strings_panel_setup(const GStringsPanel *panel, unsigned in
(*data)->count = 0;
- result = _("Loading strings available in the binary format...");
+ *msg = strdup(_("Loading strings available in the binary format..."));
break;
@@ -1568,13 +1571,13 @@ static const char *g_strings_panel_setup(const GStringsPanel *panel, unsigned in
*count = panel->count;
(*data)->count = panel->count;
- result = _("Filtering strings available in the binary format...");
+ *msg = strdup(_("Filtering strings available in the binary format..."));
break;
default: /* Pour GCC... */
assert(false);
- result = "";
+ result = false;
break;
}
@@ -1735,7 +1738,7 @@ static void g_strings_panel_conclude(GStringsPanel *panel, unsigned int uid, str
* *
******************************************************************************/
-static void g_strings_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, strings_update_data *data)
+static void g_strings_panel_clean_data(const GUpdatablePanel *panel, unsigned int uid, strings_update_data *data)
{
if (data->filter != NULL)
{
diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c
index 152d705..ab7a414 100644
--- a/src/gui/panels/symbols.c
+++ b/src/gui/panels/symbols.c
@@ -218,7 +218,7 @@ struct _symbols_update_data
static bool is_symbol_matching(const symbols_update_data *, const GBinSymbol *, regmatch_t *);
/* Prépare une opération de mise à jour de panneau. */
-static const char *g_symbols_panel_setup(const GSymbolsPanel *, unsigned int, size_t *, symbols_update_data **);
+static bool g_symbols_panel_setup(const GSymbolsPanel *, unsigned int, size_t *, symbols_update_data **, char **);
/* Bascule l'affichage d'un panneau avant mise à jour. */
static void g_symbols_panel_introduce(const GSymbolsPanel *, unsigned int, symbols_update_data *);
@@ -230,7 +230,7 @@ static void g_symbols_panel_process(const GSymbolsPanel *, unsigned int, GtkStat
static void g_symbols_panel_conclude(GSymbolsPanel *, unsigned int, symbols_update_data *);
/* Supprime les données dynamiques utilisées à la mise à jour. */
-static void g_symbols_panel_clean_data(GUpdatablePanel *, unsigned int, symbols_update_data *);
+static void g_symbols_panel_clean_data(const GUpdatablePanel *, unsigned int, symbols_update_data *);
@@ -1614,6 +1614,7 @@ static bool is_symbol_matching(const symbols_update_data *data, const GBinSymbol
* uid = identifiant de la phase de traitement. *
* count = nombre d'étapes à prévoir dans le traitement. [OUT] *
* data = données sur lesquelles s'appuyer ensuite. [OUT] *
+* msg = description du message d'information. [OUT] *
* *
* Description : Prépare une opération de mise à jour de panneau. *
* *
@@ -1623,9 +1624,9 @@ static bool is_symbol_matching(const symbols_update_data *data, const GBinSymbol
* *
******************************************************************************/
-static const char *g_symbols_panel_setup(const GSymbolsPanel *panel, unsigned int uid, size_t *count, symbols_update_data **data)
+static bool g_symbols_panel_setup(const GSymbolsPanel *panel, unsigned int uid, size_t *count, symbols_update_data **data, char **msg)
{
- const char *result; /* Message à retourner */
+ bool result; /* Bilan à retourner */
GBinFormat *format; /* Format du binaire */
#ifndef NDEBUG
int ret; /* Bilan de mise en place */
@@ -1633,6 +1634,8 @@ static const char *g_symbols_panel_setup(const GSymbolsPanel *panel, unsigned in
GtkBuilder *builder; /* Constructeur utilisé */
GtkTreeView *treeview; /* Arborescence graphique */
+ result = true;
+
*data = malloc(sizeof(symbols_update_data));
switch (uid)
@@ -1649,7 +1652,7 @@ static const char *g_symbols_panel_setup(const GSymbolsPanel *panel, unsigned in
(*data)->count = 0;
- result = _("Loading symbols registered for the binary format...");
+ *msg = strdup(_("Loading symbols registered for the binary format..."));
break;
@@ -1658,13 +1661,13 @@ static const char *g_symbols_panel_setup(const GSymbolsPanel *panel, unsigned in
*count = panel->count;
(*data)->count = panel->count;
- result = _("Filtering symbols registered for the binary format...");
+ *msg = strdup(_("Filtering symbols registered for the binary format..."));
break;
default: /* Pour GCC... */
assert(false);
- result = "";
+ result = false;
break;
}
@@ -1873,7 +1876,7 @@ static void g_symbols_panel_conclude(GSymbolsPanel *panel, unsigned int uid, sym
* *
******************************************************************************/
-static void g_symbols_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, symbols_update_data *data)
+static void g_symbols_panel_clean_data(const GUpdatablePanel *panel, unsigned int uid, symbols_update_data *data)
{
size_t i; /* Boucle de parcours */
diff --git a/src/gui/panels/symbols.ui b/src/gui/panels/symbols.ui
index 3c34a29..8e54656 100644
--- a/src/gui/panels/symbols.ui
+++ b/src/gui/panels/symbols.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.21.0 -->
+<!-- Generated with glade 3.37.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkTreeStore" id="store">
@@ -28,51 +28,51 @@
<property name="model">store</property>
</object>
<object class="GtkTreeModelFilter" id="filter">
- <property name="child_model">sorter</property>
+ <property name="child-model">sorter</property>
</object>
<object class="GtkImage" id="symbol_class_classic.png">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="resource">/org/chrysalide/gui/panels/../../../pixmaps/symbol_class_classic.png</property>
</object>
<object class="GtkImage" id="tbutton_collapse.png">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="resource">/org/chrysalide/gui/panels/../../../pixmaps/tbutton_collapse.png</property>
</object>
<object class="GtkImage" id="tbutton_expand.png">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="resource">/org/chrysalide/gui/panels/../../../pixmaps/tbutton_expand.png</property>
</object>
<object class="GtkImage" id="tbutton_list_view.png">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="resource">/org/chrysalide/gui/panels/../../../pixmaps/tbutton_list_view.png</property>
</object>
<object class="GtkImage" id="tbutton_tree_view.png">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="resource">/org/chrysalide/gui/panels/../../../pixmaps/tbutton_tree_view.png</property>
</object>
<object class="GtkOffscreenWindow">
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<child>
<object class="GtkBox" id="box">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<child>
<object class="GtkRadioToolButton" id="list_display">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="tooltip_text" translatable="yes">Show symbols using a list view</property>
- <property name="use_underline">True</property>
- <property name="icon_widget">tbutton_list_view.png</property>
+ <property name="can-focus">False</property>
+ <property name="tooltip-text" translatable="yes">Show symbols using a list view</property>
+ <property name="use-underline">True</property>
+ <property name="icon-widget">tbutton_list_view.png</property>
<property name="active">True</property>
<property name="group">tree_display</property>
<signal name="toggled" handler="on_symbols_list_display_toggle" swapped="no"/>
@@ -85,10 +85,10 @@
<child>
<object class="GtkRadioToolButton" id="tree_display">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="tooltip_text" translatable="yes">Show symbols using a tree view</property>
- <property name="use_underline">True</property>
- <property name="icon_widget">tbutton_tree_view.png</property>
+ <property name="can-focus">False</property>
+ <property name="tooltip-text" translatable="yes">Show symbols using a tree view</property>
+ <property name="use-underline">True</property>
+ <property name="icon-widget">tbutton_tree_view.png</property>
<signal name="toggled" handler="on_symbols_tree_display_toggle" swapped="no"/>
</object>
<packing>
@@ -99,7 +99,7 @@
<child>
<object class="GtkSeparatorToolItem">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
</object>
<packing>
<property name="expand">False</property>
@@ -109,10 +109,10 @@
<child>
<object class="GtkToolButton" id="collapse">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="tooltip_text" translatable="yes">Collapse all symbol nodes in the tree view</property>
- <property name="use_underline">True</property>
- <property name="icon_widget">tbutton_collapse.png</property>
+ <property name="can-focus">False</property>
+ <property name="tooltip-text" translatable="yes">Collapse all symbol nodes in the tree view</property>
+ <property name="use-underline">True</property>
+ <property name="icon-widget">tbutton_collapse.png</property>
<signal name="clicked" handler="reorganize_symbols_tree_view" swapped="no"/>
</object>
<packing>
@@ -123,10 +123,10 @@
<child>
<object class="GtkToolButton" id="expand">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="tooltip_text" translatable="yes">Expand all symbol nodes in the tree view</property>
- <property name="use_underline">True</property>
- <property name="icon_widget">tbutton_expand.png</property>
+ <property name="can-focus">False</property>
+ <property name="tooltip-text" translatable="yes">Expand all symbol nodes in the tree view</property>
+ <property name="use-underline">True</property>
+ <property name="icon-widget">tbutton_expand.png</property>
<signal name="clicked" handler="reorganize_symbols_tree_view" swapped="no"/>
</object>
<packing>
@@ -137,10 +137,10 @@
<child>
<object class="GtkToolButton" id="classes">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="tooltip_text" translatable="yes">Show all classes in the tree view</property>
- <property name="use_underline">True</property>
- <property name="icon_widget">symbol_class_classic.png</property>
+ <property name="can-focus">False</property>
+ <property name="tooltip-text" translatable="yes">Show all classes in the tree view</property>
+ <property name="use-underline">True</property>
+ <property name="icon-widget">symbol_class_classic.png</property>
<signal name="clicked" handler="reorganize_symbols_tree_view" swapped="no"/>
</object>
<packing>
@@ -151,7 +151,7 @@
<child>
<object class="GtkSeparatorToolItem">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
</object>
<packing>
<property name="expand">False</property>
@@ -161,15 +161,15 @@
<child>
<object class="GtkToolItem">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<child>
<object class="GtkSearchEntry">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip_text" translatable="yes">Filter symbols using POSIX extended regular expressions</property>
- <property name="primary_icon_name">edit-find-symbolic</property>
- <property name="primary_icon_activatable">False</property>
- <property name="primary_icon_sensitive">False</property>
+ <property name="can-focus">True</property>
+ <property name="tooltip-text" translatable="yes">Filter symbols using POSIX extended regular expressions</property>
+ <property name="primary-icon-name">edit-find-symbolic</property>
+ <property name="primary-icon-activatable">False</property>
+ <property name="primary-icon-sensitive">False</property>
<signal name="focus-in-event" handler="track_focus_change_in_text_area" swapped="no"/>
<signal name="focus-out-event" handler="track_focus_change_in_text_area" swapped="no"/>
<signal name="search-changed" handler="on_symbols_filter_changed" swapped="no"/>
@@ -191,20 +191,20 @@
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<child>
<object class="GtkScrolledWindow" id="content">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">in</property>
+ <property name="can-focus">True</property>
+ <property name="shadow-type">in</property>
<child>
<object class="GtkTreeView" id="treeview">
<property name="name">treeview</property>
<property name="visible">True</property>
- <property name="can_focus">True</property>
+ <property name="can-focus">True</property>
<property name="model">filter</property>
- <property name="headers_visible">False</property>
- <property name="search_column">2</property>
+ <property name="headers-visible">False</property>
+ <property name="search-column">2</property>
<child internal-child="selection">
<object class="GtkTreeSelection">
<signal name="changed" handler="on_symbols_selection_change" swapped="no"/>
@@ -221,7 +221,7 @@
<child>
<object class="GtkSpinner" id="mask">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can-focus">False</property>
<property name="active">True</property>
</object>
<packing>
@@ -239,8 +239,5 @@
</child>
</object>
</child>
- <child type="titlebar">
- <placeholder/>
- </child>
</object>
</interface>
diff --git a/src/gui/panels/updating-int.h b/src/gui/panels/updating-int.h
index f8d0760..1b742e8 100644
--- a/src/gui/panels/updating-int.h
+++ b/src/gui/panels/updating-int.h
@@ -30,7 +30,7 @@
/* Prépare une opération de mise à jour de panneau. */
-typedef const char * (* setup_updatable_cb) (const GUpdatablePanel *, unsigned int, size_t *, void **);
+typedef bool (* setup_updatable_cb) (const GUpdatablePanel *, unsigned int, size_t *, void **, char **);
/* Obtient le groupe de travail dédié à une mise à jour. */
typedef wgroup_id_t (* get_updatable_group_cb) (const GUpdatablePanel *);
@@ -45,7 +45,7 @@ typedef void (* process_updatable_cb) (const GUpdatablePanel *, unsigned int, Gt
typedef void (* conclude_updatable_cb) (GUpdatablePanel *, unsigned int, void *);
/* Supprime les données dynamiques utilisées à la mise à jour. */
-typedef void (* clean_updatable_data_cb) (GUpdatablePanel *, unsigned int, void *);
+typedef void (* clean_updatable_data_cb) (const GUpdatablePanel *, unsigned int, void *);
/* Mécanisme de mise à jour d'un panneau (interface) */
diff --git a/src/gui/panels/updating.c b/src/gui/panels/updating.c
index 31f42c3..c5d59e7 100644
--- a/src/gui/panels/updating.c
+++ b/src/gui/panels/updating.c
@@ -55,7 +55,7 @@ struct _GPanelUpdate
size_t max; /* Marge de progression finale */
void *data; /* Données utiles au traitement*/
- const char *msg; /* Description d'activité */
+ char *msg; /* Description d'activité */
};
@@ -120,24 +120,30 @@ static void g_updatable_panel_default_init(GUpdatablePanelInterface *iface)
* uid = identifiant de la phase de traitement. *
* count = nombre d'étapes à prévoir dans le traitement. [OUT] *
* data = données sur lesquelles s'appuyer ensuite. [OUT] *
+* msg = description du message d'information. [OUT] *
* *
* Description : Prépare une opération de mise à jour de panneau. *
* *
-* Retour : Description du message d'information. *
+* Retour : Bilan de la préparation. *
* *
* Remarques : - *
* *
******************************************************************************/
-const char *g_updatable_panel_setup(const GUpdatablePanel *panel, unsigned int uid, size_t *count, void **data)
+bool g_updatable_panel_setup(const GUpdatablePanel *panel, unsigned int uid, size_t *count, void **data, char **msg)
{
+ bool result; /* Bilan à retourner */
GUpdatablePanelIface *iface; /* Interface utilisée */
iface = G_UPDATABLE_PANEL_GET_IFACE(panel);
+ *count = 0;
*data = NULL;
+ *msg = NULL;
- return iface->setup(panel, uid, count, data);
+ result = iface->setup(panel, uid, count, data, msg);
+
+ return result;
}
@@ -148,7 +154,7 @@ const char *g_updatable_panel_setup(const GUpdatablePanel *panel, unsigned int u
* *
* Description : Obtient le groupe de travail dédié à une mise à jour. *
* *
-* Retour : - *
+* Retour : Identifiant de groupe de travail. *
* *
* Remarques : - *
* *
@@ -259,7 +265,7 @@ void g_updatable_panel_conclude(GUpdatablePanel *panel, unsigned int uid, void *
* *
******************************************************************************/
-void g_updatable_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, void *data)
+void g_updatable_panel_clean_data(const GUpdatablePanel *panel, unsigned int uid, void *data)
{
GUpdatablePanelIface *iface; /* Interface utilisée */
@@ -324,6 +330,12 @@ static void g_panel_update_class_init(GPanelUpdateClass *klass)
static void g_panel_update_init(GPanelUpdate *update)
{
+ update->panel = NULL;
+ update->uid = -1;
+
+ update->max = 0;
+ update->data = NULL;
+ update->msg = NULL;
}
@@ -342,7 +354,10 @@ static void g_panel_update_init(GPanelUpdate *update)
static void g_panel_update_dispose(GPanelUpdate *update)
{
- g_object_unref(G_OBJECT(update->panel));
+ if (update->panel != NULL)
+ g_updatable_panel_clean_data(update->panel, update->uid, update->data);
+
+ g_clear_object(&update->panel);
G_OBJECT_CLASS(g_panel_update_parent_class)->dispose(G_OBJECT(update));
@@ -363,11 +378,12 @@ static void g_panel_update_dispose(GPanelUpdate *update)
static void g_panel_update_finalize(GPanelUpdate *update)
{
- g_updatable_panel_clean_data(update->panel, update->uid, update->data);
-
if (update->data != NULL)
free(update->data);
+ if (update->msg != NULL)
+ free(update->msg);
+
G_OBJECT_CLASS(g_panel_update_parent_class)->finalize(G_OBJECT(update));
}
@@ -389,6 +405,7 @@ static void g_panel_update_finalize(GPanelUpdate *update)
GPanelUpdate *g_panel_update_new(GUpdatablePanel *panel, unsigned int uid)
{
GPanelUpdate *result; /* Tâche à retourner */
+ bool status; /* Bilan de la préparation */
result = g_object_new(G_TYPE_PANEL_UPDATE, NULL);
@@ -397,7 +414,10 @@ GPanelUpdate *g_panel_update_new(GUpdatablePanel *panel, unsigned int uid)
result->uid = uid;
- result->msg = g_updatable_panel_setup(panel, uid, &result->max, &result->data);
+ status = g_updatable_panel_setup(panel, uid, &result->max, &result->data, &result->msg);
+
+ if (!status)
+ g_clear_object(&result);
return result;
@@ -477,15 +497,19 @@ void run_panel_update(GUpdatablePanel *panel, unsigned int uid)
update = g_panel_update_new(panel, uid);
- g_signal_connect_to_main(update, "work-completed", G_CALLBACK(conclude_panel_update), panel,
- g_cclosure_marshal_VOID__VOID);
+ if (update != NULL)
+ {
+ g_signal_connect_to_main(update, "work-completed", G_CALLBACK(conclude_panel_update), panel,
+ g_cclosure_marshal_VOID__VOID);
+
+ g_updatable_panel_introduce(panel, uid, update->data);
- g_updatable_panel_introduce(panel, uid, update->data);
+ queue = get_work_queue();
- queue = get_work_queue();
+ gid = g_updatable_panel_get_group(panel);
- gid = g_updatable_panel_get_group(panel);
+ g_work_queue_schedule_work(queue, G_DELAYED_WORK(update), gid);
- g_work_queue_schedule_work(queue, G_DELAYED_WORK(update), gid);
+ }
}
diff --git a/src/gui/panels/updating.h b/src/gui/panels/updating.h
index 8c44795..2293a02 100644
--- a/src/gui/panels/updating.h
+++ b/src/gui/panels/updating.h
@@ -56,7 +56,7 @@ typedef struct _GUpdatablePanelIface GUpdatablePanelIface;
GType g_updatable_panel_get_type(void) G_GNUC_CONST;
/* Prépare une opération de mise à jour de panneau. */
-const char *g_updatable_panel_setup(const GUpdatablePanel *, unsigned int, size_t *, void **);
+bool g_updatable_panel_setup(const GUpdatablePanel *, unsigned int, size_t *, void **, char **);
/* Obtient le groupe de travail dédié à une mise à jour. */
wgroup_id_t g_updatable_panel_get_group(const GUpdatablePanel *);
@@ -71,7 +71,7 @@ void g_updatable_panel_process(const GUpdatablePanel *, unsigned int, GtkStatusS
void g_updatable_panel_conclude(GUpdatablePanel *, unsigned int, void *);
/* Supprime les données dynamiques utilisées à la mise à jour. */
-void g_updatable_panel_clean_data(GUpdatablePanel *, unsigned int, void *);
+void g_updatable_panel_clean_data(const GUpdatablePanel *, unsigned int, void *);