summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2018-02-20 23:02:44 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2018-02-20 23:02:44 (GMT)
commit0769fafb253b846b58cd97c4a1df98ca7417ae1c (patch)
treec6b397d82740a26059c02b56d7b3182e5fe08927 /src
parent738daf23eec2c114d456d13e88c51029f891fbc2 (diff)
Replaced the old symbol panel by a new improved one.
Diffstat (limited to 'src')
-rw-r--r--src/gtkext/tmgt.c2
-rw-r--r--src/gui/panels/Makefile.am1
-rw-r--r--src/gui/panels/errors.c2
-rw-r--r--src/gui/panels/gresource.xml4
-rw-r--r--src/gui/panels/symbols.c1088
-rw-r--r--src/gui/panels/symbols.ui244
-rw-r--r--src/gui/panels/updating-int.h4
-rw-r--r--src/gui/panels/updating.c28
-rw-r--r--src/gui/panels/updating.h3
9 files changed, 1142 insertions, 234 deletions
diff --git a/src/gtkext/tmgt.c b/src/gtkext/tmgt.c
index fa1e2b8..3b06d4c 100644
--- a/src/gtkext/tmgt.c
+++ b/src/gtkext/tmgt.c
@@ -103,7 +103,7 @@ bool is_content_matching(const regex_t *filter, const char *content, regmatch_t
bool result; /* Bilan à retourner */
int ret; /* Bilan du filtrage */
- memset( match, 0, sizeof(regmatch_t));
+ memset(match, 0, sizeof(regmatch_t));
if (filter == NULL)
result = true;
diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am
index a943380..0c7210f 100644
--- a/src/gui/panels/Makefile.am
+++ b/src/gui/panels/Makefile.am
@@ -6,6 +6,7 @@ noinst_LTLIBRARIES = libguipanels.la
UI_FILES = \
bintree.ui \
errors.ui \
+ symbols.ui \
welcome.ui
libguipanels_la_SOURCES = \
diff --git a/src/gui/panels/errors.c b/src/gui/panels/errors.c
index 2bfe250..afe0283 100644
--- a/src/gui/panels/errors.c
+++ b/src/gui/panels/errors.c
@@ -190,7 +190,7 @@ static void g_error_panel_conclude(GErrorPanel *, unsigned int, error_update_dat
/* Indique le type défini pour un panneau d'affichage des erreurs. */
G_DEFINE_TYPE_WITH_CODE(GErrorPanel, g_error_panel, G_TYPE_PANEL_ITEM,
- G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_error_panel_interface_init))
+ G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_error_panel_interface_init));
/******************************************************************************
diff --git a/src/gui/panels/gresource.xml b/src/gui/panels/gresource.xml
index 64a6036..214e546 100644
--- a/src/gui/panels/gresource.xml
+++ b/src/gui/panels/gresource.xml
@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/chrysalide/gui/panels">
+ <file compressed="true">../../../pixmaps/tbutton_list_view.png</file>
+ <file compressed="true">../../../pixmaps/tbutton_tree_view.png</file>
<file compressed="true">../../../pixmaps/tbutton_collapse.png</file>
<file compressed="true">../../../pixmaps/tbutton_expand.png</file>
+ <file compressed="true">../../../pixmaps/symbol_class_classic.png</file>
<file compressed="true">bintree.ui</file>
<file compressed="true">errors.ui</file>
+ <file compressed="true">symbols.ui</file>
<file compressed="true">welcome.ui</file>
</gresource>
</gresources>
diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c
index dee03b5..6b0b999 100644
--- a/src/gui/panels/symbols.c
+++ b/src/gui/panels/symbols.c
@@ -37,6 +37,7 @@
#include "panel-int.h"
+#include "updating-int.h"
#include "../core/global.h"
#include "../../format/format.h"
#include "../../format/symiter.h"
@@ -54,11 +55,10 @@ struct _GSymbolsPanel
{
GPanelItem parent; /* A laisser en premier */
- GtkTreeView *treeview; /* Composant d'affichage */
- GtkTreeStore *store; /* Modèle de gestion */
-
GLoadedBinary *binary; /* Binaire à prendre en compte */
+ size_t count; /* Quantité de symboles utiles */
+
regex_t *filter; /* Filtre appliqué ou NULL */
};
@@ -69,6 +69,7 @@ struct _GSymbolsPanelClass
GPanelItemClass parent; /* A laisser en premier */
cairo_surface_t *routine_img; /* Image pour les routines */
+ cairo_surface_t *object_img; /* Image pour les objets */
cairo_surface_t *package_img; /* Image pour les paquets */
cairo_surface_t *class_img; /* Image pour les classes */
@@ -87,26 +88,37 @@ typedef enum _SymbolsColumn
SBC_SECTION, /* Section d'appartenance */
SBC_EXPAND, /* Affichage des classes */
-
- SBC_COUNT /* Nombre de colonnes */
+ SBC_MATCHED, /* Correspondance établie ? */
+ SBC_MATCH_POINTS /* Nombre de demandeurs */
} SymbolsColumn;
+
+/* Données utiles à la mise à jour */
+typedef struct _symbols_update_data symbols_update_data;
+
+
/* Initialise la classe des panneaux d'affichage des symboles. */
static void g_symbols_panel_class_init(GSymbolsPanelClass *);
/* Initialise une instance de panneau d'affichage des symboles. */
static void g_symbols_panel_init(GSymbolsPanel *);
+/* Procède à l'initialisation de l'interface de mise à jour. */
+static void g_symbols_panel_interface_init(GUpdatablePanelInterface *);
+
/* Supprime toutes les références externes. */
static void g_symbols_panel_dispose(GSymbolsPanel *);
/* Procède à la libération totale de la mémoire. */
static void g_symbols_panel_finalize(GSymbolsPanel *);
-/* Réagit au changement d'affichage des symboles. */
-static void on_symbols_display_change(GtkToggleToolButton *, GSymbolsPanel *);
+/* Bascule d'affichage des symboles en liste. */
+static void on_symbols_list_display_toggle(GtkToggleToolButton *, GSymbolsPanel *);
+
+/* Bascule l'affichage des symboles en arborescence. */
+static void on_symbols_tree_display_toggle(GtkToggleToolButton *, GSymbolsPanel *);
/* Réagit au changement de sélection des symboles. */
static void on_symbols_selection_change(GtkTreeSelection *, gpointer);
@@ -114,13 +126,19 @@ static void on_symbols_selection_change(GtkTreeSelection *, gpointer);
/* Réagit à un changement d'affichage principal de contenu. */
static void change_symbols_panel_current_binary(GSymbolsPanel *, GLoadedBinary *);
+/* Réagit à un changement d'affichage principal de contenu. */
+static void reload_symbols_panel_content(const GSymbolsPanel *, GtkStatusStack *, activity_id_t, symbols_update_data *);
+
/* ------------------------- AFFICHAGE A L'AIDE D'UNE LISTE ------------------------- */
/* Réagit à un changement d'affichage principal de contenu. */
-static void reload_symbols_for_new_list_view(GSymbolsPanel *);
+static void reload_symbols_for_new_list_view(const GSymbolsPanel *, GtkStatusStack *, activity_id_t, symbols_update_data *);
+
+/* Met en surbrillance les éléments recherchés dans les noms. */
+static void update_symbol_name_in_list_view(GtkTreeStore *, GtkTreeIter *, const regmatch_t *);
@@ -128,21 +146,26 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *);
/* S'assure qu'un noeud donné existe bien. */
-
-static GtkTreeIter ensure_symbol_node_exist(GSymbolsPanel *, GtkTreeIter *, const char *, const regmatch_t *, size_t);
+static GtkTreeIter ensure_symbol_node_exist(const GSymbolsPanel *, GtkTreeIter *, const char *, const regmatch_t *, size_t);
/* Détermine le point d'insertion parent d'une routine. */
-static bool find_parent_for_symbol(GSymbolsPanel *, const GBinSymbol *, GtkTreeIter *, const regmatch_t *, size_t *);
+static bool find_parent_for_symbol(const GSymbolsPanel *, const GBinSymbol *, GtkTreeIter *, const regmatch_t *, size_t *);
/* Réagit à un changement d'affichage principal de contenu. */
-static void reload_symbols_for_new_tree_view(GSymbolsPanel *);
+static void reload_symbols_for_new_tree_view(const GSymbolsPanel *, GtkStatusStack *, activity_id_t, symbols_update_data *);
/* Réagit à une nouvelle demande de réorganisation. */
-static void reorganize_symbols_tree_view(GtkToolButton *, GObject *);
+static void reorganize_symbols_tree_view(GtkToolButton *, const GSymbolsPanel *);
/* Fait en sorte que toutes les classes soient affichées. */
static gboolean show_all_classes_in_tree_view(GtkTreeModel *, GtkTreePath *, GtkTreeIter *, GtkTreeView *);
+/* Actualise une partie d'un nom de symbole éclaté en noeuds. */
+static GtkTreeIter update_symbol_partial_name_in_tree_view(GtkTreeStore *, GtkTreeIter *, const char *, const regmatch_t *, size_t);
+
+/* Met en surbrillance les éléments recherchés dans les noms. */
+static void update_symbol_name_in_tree_view(GtkTreeStore *, const GBinSymbol *, const regmatch_t *);
+
/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */
@@ -151,11 +174,50 @@ static gboolean show_all_classes_in_tree_view(GtkTreeModel *, GtkTreePath *, Gtk
/* Démarre l'actualisation du filtrage des symboles. */
static void on_symbols_filter_changed(GtkSearchEntry *, GSymbolsPanel *);
+/* Met à jour l'affichage des noeuds en fonction des besoin. */
+static void update_symbol_visibility(GtkTreeStore *, GtkTreeIter *, bool);
+
/* Exécute un nouveau filtrage des symboles affichés. */
-static void do_filtering_on_symbols(GSymbolsPanel *);
+static void do_filtering_on_symbols(const GSymbolsPanel *, GtkStatusStack *, activity_id_t, symbols_update_data *);
/* Détermine si un nom de symbole doit être filtré ou non. */
-static bool is_symbol_matching(GSymbolsPanel *, const GBinSymbol *, regmatch_t *);
+static bool is_symbol_matching(const GSymbolsPanel *, const GBinSymbol *, regmatch_t *);
+
+
+/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */
+
+
+/* Données utiles à la mise à jour */
+struct _symbols_update_data
+{
+ GtkTreeModel *model; /* Source de données associée */
+
+ size_t count; /* Qté d'inscriptions réalisées*/
+
+ char **expanded; /* Chemins des noeuds ouverts */
+ size_t ecount; /* Nombre de ces chemins */
+ size_t eallocated; /* Espace alloué effectivement */
+
+};
+
+
+#define EXPAND_ALLOC_RANGE 10
+
+
+/* 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 **);
+
+/* Bascule l'affichage d'un panneau avant mise à jour. */
+static void g_symbols_panel_introduce(const GSymbolsPanel *, unsigned int, symbols_update_data *);
+
+/* Réalise une opération de mise à jour de panneau. */
+static void g_symbols_panel_process(const GSymbolsPanel *, unsigned int, GtkStatusStack *, activity_id_t, symbols_update_data *);
+
+/* Bascule l'affichage d'un panneau après mise à jour. */
+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 *);
@@ -165,7 +227,8 @@ static bool is_symbol_matching(GSymbolsPanel *, const GBinSymbol *, regmatch_t *
/* Indique le type définit pour un panneau d'affichage des symboles. */
-G_DEFINE_TYPE(GSymbolsPanel, g_symbols_panel, G_TYPE_PANEL_ITEM);
+G_DEFINE_TYPE_WITH_CODE(GSymbolsPanel, g_symbols_panel, G_TYPE_PANEL_ITEM,
+ G_IMPLEMENT_INTERFACE(G_TYPE_UPDATABLE_PANEL, g_symbols_panel_interface_init));
/******************************************************************************
@@ -203,6 +266,13 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *klass)
g_free(filename);
+ filename = find_pixmap_file("symbol_object_classic.png");
+ assert(filename != NULL);
+
+ klass->object_img = cairo_image_surface_create_from_png(filename);
+
+ g_free(filename);
+
filename = find_pixmap_file("symbol_package.png");
assert(filename != NULL);
@@ -241,17 +311,11 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
{
GEditorItem *base; /* Version basique d'instance */
GPanelItem *pitem; /* Version parente du panneau */
- GObject *ref; /* Espace de référencement */
- GtkWidget *box; /* Séparation horizontale */
- GtkWidget *toolbar; /* Barre d'outils */
- GtkWidget *button; /* Bouton de cette même barre */
- GtkWidget *separator; /* Barre de séparation vert. */
- GtkWidget *search; /* Zone de recherche */
- GtkWidget *scrollwnd; /* Support défilant */
- GtkWidget *treeview; /* Affichage de la liste */
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeView *treeview; /* Affichage de la liste */
+ GtkTreeModelFilter *filter; /* Filtre pour l'arborescence */
GtkCellRenderer *renderer; /* Moteur de rendu de colonne */
GtkTreeViewColumn *column; /* Colonne de la liste */
- GtkTreeSelection *select; /* Sélection dans la liste */
/* Eléments de base */
@@ -268,95 +332,15 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
/* Représentation graphique */
- base->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
- gtk_widget_show(base->widget);
-
- ref = G_OBJECT(base->widget);
- g_object_set_data(ref, "panel", panel);
-
- /* Barre d'outils supérieure */
-
- box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
- gtk_widget_show(box);
- gtk_box_pack_start(GTK_BOX(base->widget), box, FALSE, FALSE, 0);
-
- toolbar = gtk_toolbar_new();
- gtk_widget_show(toolbar);
- gtk_box_pack_start(GTK_BOX(box), toolbar, TRUE, TRUE, 0);
-
- button = qck_create_toggle_tool_button(ref, "list", _("List"), "tbutton_list_view.png",
- G_CALLBACK(on_symbols_display_change), panel);
- gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
- _("Show symbols using a list view"));
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
-
- button = qck_create_toggle_tool_button(ref, "tree", _("Tree"), "tbutton_tree_view.png",
- G_CALLBACK(on_symbols_display_change), panel);
- gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
- _("Show symbols using a tree view"));
- gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(button), TRUE);
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
-
- separator = qck_create_tool_separator(NULL, NULL);
- gtk_container_add(GTK_CONTAINER(toolbar), separator);
-
- button = qck_create_tool_button(ref, "collapse", _("Collapse"), "tbutton_collapse.png",
- G_CALLBACK(reorganize_symbols_tree_view), ref);
- gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
- _("Collapse all symbol nodes in the tree view"));
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
-
- button = qck_create_tool_button(ref, "expand", _("Expand"), "tbutton_expand.png",
- G_CALLBACK(reorganize_symbols_tree_view), ref);
- gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
- _("Expand all symbol nodes in the tree view"));
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
+ builder = g_panel_item_build(pitem, "symbols");
- button = qck_create_tool_button(ref, "classes", _("Classes"), "symbol_class_classic.png",
- G_CALLBACK(reorganize_symbols_tree_view), ref);
- gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button),
- _("Show all classes in the tree view"));
- gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
-
- separator = qck_create_tool_separator(NULL, NULL);
- gtk_container_add(GTK_CONTAINER(toolbar), separator);
-
- /* Espace de recherche */
-
- search = gtk_search_entry_new();
- gtk_widget_set_tooltip_text(search, _("Filter symbols using POSIX extended regular expressions"));
-
- g_signal_connect(search, "search-changed", G_CALLBACK(on_symbols_filter_changed), panel);
- gtk_widget_show(search);
- gtk_widget_set_hexpand(search, TRUE);
-
- gtk_box_pack_start(GTK_BOX(box), search, TRUE, TRUE, 0);
-
- /* Liste arborescente ou linéaire */
-
- scrollwnd = gtk_scrolled_window_new(NULL, NULL);
- gtk_widget_show(scrollwnd);
- gtk_box_pack_start(GTK_BOX(base->widget), scrollwnd, TRUE, TRUE, 0);
-
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwnd), GTK_SHADOW_IN);
-
- panel->store = gtk_tree_store_new(SBC_COUNT, G_TYPE_OBJECT, CAIRO_GOBJECT_TYPE_SURFACE, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
-
- treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(panel->store));
- gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
- gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(treeview), TRUE);
-
- panel->treeview = GTK_TREE_VIEW(treeview);
-
- gtk_widget_show(treeview);
- gtk_container_add(GTK_CONTAINER(scrollwnd), treeview);
-
- g_object_unref(G_OBJECT(panel->store));
+ filter = GTK_TREE_MODEL_FILTER(gtk_builder_get_object(builder, "filter"));
+ gtk_tree_model_filter_set_visible_column(filter, SBC_MATCHED);
/* Cellules d'affichage */
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
column = gtk_tree_view_column_new();
renderer = gtk_cell_renderer_pixbuf_new();
@@ -385,11 +369,40 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
gtk_tree_view_column_set_sort_column_id(column, SBC_SECTION);
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
- /* Prise en compte de la sélection */
+ /* Connexion des signaux */
+
+ gtk_builder_add_callback_symbols(builder,
+ "on_symbols_list_display_toggle", G_CALLBACK(on_symbols_list_display_toggle),
+ "on_symbols_tree_display_toggle", G_CALLBACK(on_symbols_tree_display_toggle),
+ "reorganize_symbols_tree_view", G_CALLBACK(reorganize_symbols_tree_view),
+ "on_symbols_filter_changed", G_CALLBACK(on_symbols_filter_changed),
+ "on_symbols_selection_change", G_CALLBACK(on_symbols_selection_change),
+ NULL);
- select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
- gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
- g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(on_symbols_selection_change), NULL);
+ gtk_builder_connect_signals(builder, panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de mise à jour. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_symbols_panel_interface_init(GUpdatablePanelInterface *iface)
+{
+ iface->setup = (setup_updatable_cb)g_symbols_panel_setup;
+ iface->introduce = (introduce_updatable_cb)g_symbols_panel_introduce;
+ iface->process = (process_updatable_cb)g_symbols_panel_process;
+ iface->conclude = (conclude_updatable_cb)g_symbols_panel_conclude;
+ iface->clean = (clean_updatable_data_cb)g_symbols_panel_clean_data;
}
@@ -469,7 +482,7 @@ GPanelItem *g_symbols_panel_new(void)
* Paramètres : button = bouton de la barre activé. *
* panel = structure contenant les informations maîtresses. *
* *
-* Description : Réagit au changement d'affichage des symboles. *
+* Description : Bascule d'affichage des symboles en liste. *
* *
* Retour : - *
* *
@@ -477,54 +490,82 @@ GPanelItem *g_symbols_panel_new(void)
* *
******************************************************************************/
-static void on_symbols_display_change(GtkToggleToolButton *button, GSymbolsPanel *panel)
+static void on_symbols_list_display_toggle(GtkToggleToolButton *button, GSymbolsPanel *panel)
{
- GObject *ref; /* Espace de référencement */
- GtkToggleToolButton *list; /* Bouton pour les listes */
- GtkToggleToolButton *tree; /* Bouton pour l'arborescence */
- gboolean state; /* Etat du bouton courant */
- GtkToggleToolButton *other; /* Bouton à traiter */
- GtkWidget *option; /* Bouton dont l'accès change */
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkWidget *other; /* Autre bouton de la barre */
- ref = G_OBJECT(G_EDITOR_ITEM(panel)->widget);
+ if (gtk_toggle_tool_button_get_active(button))
+ {
+ /* Accès aux boutons complémentaires */
- list = GTK_TOGGLE_TOOL_BUTTON(g_object_get_data(ref, "list"));
- tree = GTK_TOGGLE_TOOL_BUTTON(g_object_get_data(ref, "tree"));
+ builder = G_PANEL_ITEM(panel)->builder;
- /* Désactivation de l'autre bouton */
+ other = GTK_WIDGET(gtk_builder_get_object(builder, "collapse"));
+ gtk_widget_set_sensitive(other, FALSE);
- state = gtk_toggle_tool_button_get_active(button);
+ other = GTK_WIDGET(gtk_builder_get_object(builder, "expand"));
+ gtk_widget_set_sensitive(other, FALSE);
- if (button == list) other = tree;
- else other = list;
+ other = GTK_WIDGET(gtk_builder_get_object(builder, "classes"));
+ gtk_widget_set_sensitive(other, FALSE);
- g_signal_handlers_disconnect_by_func(other, G_CALLBACK(on_symbols_display_change), panel);
- gtk_toggle_tool_button_set_active(other, !state);
- g_signal_connect(other, "toggled", G_CALLBACK(on_symbols_display_change), panel);
+ /* Actualisation de l'affichage */
- /* Définition des accès sur le reste de la barre */
+ if (panel->binary != NULL)
+ {
+ g_object_ref(G_OBJECT(panel->binary));
+ change_symbols_panel_current_binary(panel, panel->binary);
+ g_object_unref(G_OBJECT(panel->binary));
+ }
- state = gtk_toggle_tool_button_get_active(tree);
+ }
- option = GTK_WIDGET(g_object_get_data(ref, "collapse"));
- if (option != NULL)
- gtk_widget_set_sensitive(option, state);
+}
- option = GTK_WIDGET(g_object_get_data(ref, "expand"));
- if (option != NULL)
- gtk_widget_set_sensitive(option, state);
- option = GTK_WIDGET(g_object_get_data(ref, "classes"));
- if (option != NULL)
- gtk_widget_set_sensitive(option, state);
+/******************************************************************************
+* *
+* Paramètres : button = bouton de la barre activé. *
+* panel = structure contenant les informations maîtresses. *
+* *
+* Description : Bascule l'affichage des symboles en arborescence. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- /* Actualisation */
+static void on_symbols_tree_display_toggle(GtkToggleToolButton *button, GSymbolsPanel *panel)
+{
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkWidget *other; /* Autre bouton de la barre */
- if (panel->binary != NULL)
+ if (gtk_toggle_tool_button_get_active(button))
{
- g_object_ref(G_OBJECT(panel->binary));
- change_symbols_panel_current_binary(panel, panel->binary);
- g_object_unref(G_OBJECT(panel->binary));
+ /* Accès aux boutons complémentaires */
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ other = GTK_WIDGET(gtk_builder_get_object(builder, "collapse"));
+ gtk_widget_set_sensitive(other, TRUE);
+
+ other = GTK_WIDGET(gtk_builder_get_object(builder, "expand"));
+ gtk_widget_set_sensitive(other, TRUE);
+
+ other = GTK_WIDGET(gtk_builder_get_object(builder, "classes"));
+ gtk_widget_set_sensitive(other, TRUE);
+
+ /* Actualisation de l'affichage */
+
+ if (panel->binary != NULL)
+ {
+ g_object_ref(G_OBJECT(panel->binary));
+ change_symbols_panel_current_binary(panel, panel->binary);
+ g_object_unref(G_OBJECT(panel->binary));
+ }
+
}
}
@@ -590,8 +631,8 @@ static void on_symbols_selection_change(GtkTreeSelection *selection, gpointer un
static void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBinary *binary)
{
- GtkToggleToolButton *button; /* Mode de représentation */
- GtkRequisition req; /* Nouvelle taille idéale */
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeStore *store; /* Modèle de gestion */
/* Basculement du binaire utilisé */
@@ -603,29 +644,55 @@ static void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBin
if (panel->binary != NULL)
g_object_ref(G_OBJECT(panel->binary));
- gtk_tree_store_clear(panel->store);
+ /* Réinitialisation */
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
+
+ gtk_tree_store_clear(store);
- /* Si le panneau actif ne représente pas un binaire... */
+ /* Si le panneau actif représente un binaire, actualisation de l'affichage */
- if (binary == NULL) return;
+ if (binary != NULL)
+ run_panel_update(G_UPDATABLE_PANEL(panel), PUI_0);
- /* Actualisation de l'affichage */
+}
- button = g_object_get_data(G_OBJECT(G_EDITOR_ITEM(panel)->widget), "list");
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau à mettre à jour. *
+* status = barre de statut à tenir informée. *
+* id = identifiant pour le suivi de la progression. *
+* data = données complémentaire à manipuler. *
+* *
+* Description : Réagit à un changement d'affichage principal de contenu. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void reload_symbols_panel_content(const GSymbolsPanel *panel, GtkStatusStack *status, activity_id_t id, symbols_update_data *data)
+{
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkToggleToolButton *button; /* Mode de représentation */
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ button = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(builder, "list_display"));
if (gtk_toggle_tool_button_get_active(button))
- reload_symbols_for_new_list_view(panel);
+ reload_symbols_for_new_list_view(panel, status, id, data);
+
else
{
- reload_symbols_for_new_tree_view(panel);
- reorganize_symbols_tree_view(NULL, G_OBJECT(G_EDITOR_ITEM(panel)->widget));
+ reload_symbols_for_new_tree_view(panel, status, id, data);
+ reorganize_symbols_tree_view(NULL, panel);
}
- return; /* FIXME */
-
- gtk_widget_get_preferred_size(GTK_WIDGET(panel->treeview), NULL, &req);
- gtk_widget_set_size_request(GTK_WIDGET(panel->treeview), req.width, req.height);
-
}
@@ -638,6 +705,9 @@ static void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBin
/******************************************************************************
* *
* Paramètres : panel = panneau à mettre à jour. *
+* status = barre de statut à tenir informée. *
+* id = identifiant pour le suivi de la progression. *
+* data = données complémentaire à manipuler. *
* *
* Description : Réagit à un changement d'affichage principal de contenu. *
* *
@@ -647,21 +717,28 @@ static void change_symbols_panel_current_binary(GSymbolsPanel *panel, GLoadedBin
* *
******************************************************************************/
-static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
+static void reload_symbols_for_new_list_view(const GSymbolsPanel *panel, GtkStatusStack *status, activity_id_t id, symbols_update_data *data)
{
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeStore *store; /* Modèle de gestion */
GExeFormat *format; /* Format associé au binaire */
GArchProcessor *proc; /* Architecture utilisée */
MemoryDataSize size; /* Taille des localisations */
sym_iter_t *siter; /* Parcours des symboles */
GBinSymbol *symbol; /* Symbole manipulé */
- regmatch_t match; /* Récupération des trouvailles*/
cairo_surface_t *icon; /* Image associée au symbole */
+ regmatch_t match; /* Récupération des trouvailles*/
+ bool matched; /* Correspondance de sélection */
const char *original; /* Etiquette brute d'origine */
char *name; /* Etiquette mise en relief */
const vmpa2t *addr; /* Localisation d'un symbole */
char virt[VMPA_MAX_LEN]; /* Version humainement lisible */
GtkTreeIter iter; /* Point d'insertion */
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
+
format = g_loaded_binary_get_format(panel->binary);
proc = g_loaded_binary_get_processor(panel->binary);
@@ -674,9 +751,6 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
symbol != NULL;
symbol = get_symbol_iterator_next(siter))
{
- if (!is_symbol_matching(panel, symbol, &match))
- goto rsfnlv_next;
-
switch (g_binary_symbol_get_target_type(symbol))
{
case STP_ROUTINE:
@@ -684,29 +758,46 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
icon = G_SYMBOLS_PANEL_GET_CLASS(panel)->routine_img;
break;
case STP_OBJECT:
- icon = G_SYMBOLS_PANEL_GET_CLASS(panel)->routine_img; /* FIXME */
+ icon = G_SYMBOLS_PANEL_GET_CLASS(panel)->object_img;
break;
default:
- assert(false);
+ icon = NULL;
break;
}
+ if (icon == NULL)
+ goto rsfnlv_next;
+
+ matched = is_symbol_matching(panel, symbol, &match);
+
original = g_binary_symbol_get_label(symbol);
- name = build_highlighted_name(original, &match, 0);
+
+ if (matched)
+ name = build_highlighted_name(original, &match, 0);
+ else
+ name = NULL;
addr = get_mrange_addr(g_binary_symbol_get_range(symbol));
vmpa2_virt_to_string(addr, size, virt, NULL);
- gtk_tree_store_append(panel->store, &iter, NULL);
- gtk_tree_store_set(panel->store, &iter,
+ gtk_tree_store_append(store, &iter, NULL);
+ gtk_tree_store_set(store, &iter,
SBC_SYMBOL, symbol,
SBC_PICTURE, icon,
SBC_NAME, name,
SBC_ORIGINAL, original,
SBC_ADDRESS, virt,
+ SBC_MATCHED, false,
+ SBC_MATCH_POINTS, 0,
-1);
- free(name);
+ if (matched)
+ update_symbol_visibility(store, &iter, true);
+
+ data->count++;
+
+ if (name != NULL)
+ free(name);
rsfnlv_next:
@@ -721,6 +812,40 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
}
+/******************************************************************************
+* *
+* Paramètres : store = gestionnaire de données pour une arborescence. *
+* iter = position des données traitées. *
+* match = correspondance avec un objet recherché. *
+* *
+* Description : Met en surbrillance les éléments recherchés dans les noms. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void update_symbol_name_in_list_view(GtkTreeStore *store, GtkTreeIter *iter, const regmatch_t *match)
+{
+ GtkTreeModel *model; /* Autre vision du gestionnaire*/
+ char *original; /* Etiquette brute d'origine */
+ char *name; /* Etiquette mise en relief */
+
+ model = GTK_TREE_MODEL(store);
+
+ gtk_tree_model_get(model, iter, SBC_ORIGINAL, &original, -1);
+
+ name = build_highlighted_name(original, match, 0);
+
+ gtk_tree_store_set(store, iter, SBC_NAME, name, -1);
+
+ free(original);
+ free(name);
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* AFFICHAGE SOUS FORME D'ARBRE */
@@ -743,29 +868,35 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel)
* *
******************************************************************************/
-static GtkTreeIter ensure_symbol_node_exist(GSymbolsPanel *panel, GtkTreeIter *parent, const char *raw, const regmatch_t *match, size_t start)
+static GtkTreeIter ensure_symbol_node_exist(const GSymbolsPanel *panel, GtkTreeIter *parent, const char *raw, const regmatch_t *match, size_t start)
{
+ GtkBuilder *builder; /* Constructeur utilisé */
GtkTreeStore *store; /* Gestionnaire de données */
+ GtkTreeModel *model; /* Autre vision du gestionnaire*/
bool found; /* Bilan des recherches */
GtkTreeIter iter; /* Boucle de parcours */
gchar *string; /* Chaîne sélectionnée */
char *name; /* Etiquette mise en relief */
- store = panel->store;
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
+
+ model = GTK_TREE_MODEL(store);
found = false;
- if (gtk_tree_model_iter_children(GTK_TREE_MODEL(store), &iter, parent))
+ if (gtk_tree_model_iter_children(model, &iter, parent))
do
{
- gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, SBC_ORIGINAL, &string, -1);
+ gtk_tree_model_get(model, &iter, SBC_ORIGINAL, &string, -1);
found = (strcmp(string, raw) == 0);
g_free(string);
if (found) break;
}
- while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));
+ while (gtk_tree_model_iter_next(model, &iter));
if (!found)
{
@@ -776,6 +907,8 @@ static GtkTreeIter ensure_symbol_node_exist(GSymbolsPanel *panel, GtkTreeIter *p
SBC_PICTURE, G_SYMBOLS_PANEL_GET_CLASS(panel)->package_img,
SBC_NAME, name,
SBC_ORIGINAL, raw,
+ SBC_MATCHED, false,
+ SBC_MATCH_POINTS, 0,
-1);
free(name);
@@ -803,8 +936,9 @@ static GtkTreeIter ensure_symbol_node_exist(GSymbolsPanel *panel, GtkTreeIter *p
* *
******************************************************************************/
-static bool find_parent_for_symbol(GSymbolsPanel *panel, const GBinSymbol *symbol, GtkTreeIter *parent, const regmatch_t *match, size_t *last)
+static bool find_parent_for_symbol(const GSymbolsPanel *panel, const GBinSymbol *symbol, GtkTreeIter *parent, const regmatch_t *match, size_t *last)
{
+ bool result; /* Bilan à retourner */
const char *label; /* Etiquette immuable */
char *string; /* Etiquette modifiable */
const char *sep; /* Délimitateur à utiliser */
@@ -813,6 +947,8 @@ static bool find_parent_for_symbol(GSymbolsPanel *panel, const GBinSymbol *symbo
char *saveptr; /* Ctx. interne de découpage */
char *next; /* Prochaine partie à traiter */
+ result = false;
+
*last = 0;
label = g_binary_symbol_get_label(symbol);
@@ -833,18 +969,23 @@ static bool find_parent_for_symbol(GSymbolsPanel *panel, const GBinSymbol *symbo
*parent = ensure_symbol_node_exist(panel, (start == string ? NULL : parent), token, match, token - string);
+ result = true;
+
}
free(string);
- return true;
+ return result;
}
/******************************************************************************
* *
-* Paramètres : panel = panneau à mettre à jour. *
+* Paramètres : panel = panneau à mettre à jour. *
+* status = barre de statut à tenir informée. *
+* id = identifiant pour le suivi de la progression. *
+* data = données complémentaire à manipuler. *
* *
* Description : Réagit à un changement d'affichage principal de contenu. *
* *
@@ -854,23 +995,30 @@ static bool find_parent_for_symbol(GSymbolsPanel *panel, const GBinSymbol *symbo
* *
******************************************************************************/
-static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
+static void reload_symbols_for_new_tree_view(const GSymbolsPanel *panel, GtkStatusStack *status, activity_id_t id, symbols_update_data *data)
{
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeStore *store; /* Modèle de gestion */
GExeFormat *format; /* Format associé au binaire */
GArchProcessor *proc; /* Architecture utilisée */
MemoryDataSize size; /* Taille des localisations */
sym_iter_t *siter; /* Parcours des symboles */
GBinSymbol *symbol; /* Symbole manipulé */
+ cairo_surface_t *icon; /* Image associée au symbole */
regmatch_t match; /* Récupération des trouvailles*/
+ bool matched; /* Correspondance de sélection */
GtkTreeIter parent; /* Point d'insertion parent */
size_t last; /* Position du dernier élément */
- cairo_surface_t *icon; /* Image associée au symbole */
const char *original; /* Etiquette brute d'origine */
char *name; /* Etiquette mise en relief */
const vmpa2t *addr; /* Localisation d'un symbole */
char virt[VMPA_MAX_LEN]; /* Version humainement lisible */
GtkTreeIter iter; /* Point d'insertion */
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
+
format = g_loaded_binary_get_format(panel->binary);
proc = g_loaded_binary_get_processor(panel->binary);
@@ -883,22 +1031,6 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
symbol != NULL;
symbol = get_symbol_iterator_next(siter))
{
- if (!is_symbol_matching(panel, symbol, &match))
- goto rsfntv_next;
-
- if (find_parent_for_symbol(panel, symbol, &parent, &match, &last))
- {
- gtk_tree_store_set(panel->store, &parent,
- SBC_PICTURE, G_SYMBOLS_PANEL_GET_CLASS(panel)->class_img,
- SBC_EXPAND, TRUE,
- -1);
-
- gtk_tree_store_append(panel->store, &iter, &parent);
-
- }
- else
- gtk_tree_store_append(panel->store, &iter, NULL);
-
switch (g_binary_symbol_get_target_type(symbol))
{
case STP_ROUTINE:
@@ -906,28 +1038,58 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
icon = G_SYMBOLS_PANEL_GET_CLASS(panel)->routine_img;
break;
case STP_OBJECT:
- icon = G_SYMBOLS_PANEL_GET_CLASS(panel)->routine_img; /* FIXME */
+ icon = G_SYMBOLS_PANEL_GET_CLASS(panel)->object_img;
break;
default:
- assert(false);
+ icon = NULL;
break;
}
+ if (icon == NULL)
+ goto rsfntv_next;
+
+ matched = is_symbol_matching(panel, symbol, &match);
+
+ if (find_parent_for_symbol(panel, symbol, &parent, &match, &last))
+ {
+ gtk_tree_store_set(store, &parent,
+ SBC_PICTURE, G_SYMBOLS_PANEL_GET_CLASS(panel)->class_img,
+ SBC_EXPAND, TRUE,
+ -1);
+
+ gtk_tree_store_append(store, &iter, &parent);
+
+ }
+ else
+ gtk_tree_store_append(store, &iter, NULL);
+
original = g_binary_symbol_get_label(symbol);
- name = build_highlighted_name(original + last, &match, last);
+
+ if (matched)
+ name = build_highlighted_name(original + last, &match, last);
+ else
+ name = NULL;
addr = get_mrange_addr(g_binary_symbol_get_range(symbol));
vmpa2_virt_to_string(addr, size, virt, NULL);
- gtk_tree_store_set(panel->store, &iter,
+ gtk_tree_store_set(store, &iter,
SBC_SYMBOL, symbol,
SBC_PICTURE, icon,
SBC_NAME, name,
SBC_ORIGINAL, original + last,
SBC_ADDRESS, virt,
+ SBC_MATCHED, false,
+ SBC_MATCH_POINTS, 0,
-1);
- free(name);
+ if (matched)
+ update_symbol_visibility(store, &iter, true);
+
+ data->count++;
+
+ if (name != NULL)
+ free(name);
rsfntv_next:
@@ -945,7 +1107,7 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
/******************************************************************************
* *
* Paramètres : button = bouton concerné par l'action. *
-* ref = espace de référencement des composants. *
+* panel = panneau à mettre à jour. *
* *
* Description : Réagit à une nouvelle demande de réorganisation. *
* *
@@ -955,22 +1117,36 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel)
* *
******************************************************************************/
-static void reorganize_symbols_tree_view(GtkToolButton *button, GObject *ref)
+static void reorganize_symbols_tree_view(GtkToolButton *button, const GSymbolsPanel *panel)
{
- GSymbolsPanel *panel; /* Données du panneau */
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeView *treeview; /* Arborescence graphique */
+ GtkToolButton *ref_collapse; /* Bouton de référence #1 */
+ GtkToolButton *ref_expand; /* Bouton de référence #2 */
+ GtkTreeStore *store; /* Modèle de gestion */
+
+ builder = G_PANEL_ITEM(panel)->builder;
- panel = (GSymbolsPanel *)g_object_get_data(ref, "panel");
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
- if (g_object_get_data(ref, "collapse") == button)
- gtk_tree_view_collapse_all(panel->treeview);
+ ref_collapse = GTK_TOOL_BUTTON(gtk_builder_get_object(builder, "collapse"));
+ ref_expand = GTK_TOOL_BUTTON(gtk_builder_get_object(builder, "expand"));
- else if (g_object_get_data(ref, "expand") == button)
- gtk_tree_view_expand_all(panel->treeview);
+ if (button == ref_collapse)
+ gtk_tree_view_collapse_all(treeview);
+
+ else if (button == ref_expand)
+ gtk_tree_view_expand_all(treeview);
else
- gtk_tree_model_foreach(GTK_TREE_MODEL(panel->store),
+ {
+ store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
+
+ gtk_tree_model_foreach(GTK_TREE_MODEL(store),
(GtkTreeModelForeachFunc)show_all_classes_in_tree_view,
- panel->treeview);
+ treeview);
+
+ }
}
@@ -1013,6 +1189,107 @@ static gboolean show_all_classes_in_tree_view(GtkTreeModel *model, GtkTreePath *
}
+/******************************************************************************
+* *
+* Paramètres : store = gestionnaire de données en arborescence. *
+* parent = point d'insertion parent à retrouver. [OUT] *
+* raw = nom du noeud ciblé. *
+* match = portion de texte à mettre en évidence. *
+* start = position du texte brute dans l'étiquette complète. *
+* *
+* Description : Actualise une partie d'un nom de symbole éclaté en noeuds. *
+* *
+* Retour : Point de mise à jour prochain. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GtkTreeIter update_symbol_partial_name_in_tree_view(GtkTreeStore *store, GtkTreeIter *parent, const char *raw, const regmatch_t *match, size_t start)
+{
+ GtkTreeModel *model; /* Autre vision du gestionnaire*/
+ bool found; /* Bilan des recherches */
+ GtkTreeIter iter; /* Boucle de parcours */
+ gchar *string; /* Chaîne sélectionnée */
+ char *name; /* Etiquette mise en relief */
+
+ model = GTK_TREE_MODEL(store);
+
+ found = false;
+
+ if (gtk_tree_model_iter_children(model, &iter, parent))
+ do
+ {
+ gtk_tree_model_get(model, &iter, SBC_ORIGINAL, &string, -1);
+
+ found = (strcmp(string, raw) == 0);
+ g_free(string);
+
+ if (found) break;
+
+ }
+ while (gtk_tree_model_iter_next(model, &iter));
+
+ assert(found);
+
+ name = build_highlighted_name(raw, match, start);
+
+ gtk_tree_store_set(store, &iter, SBC_NAME, name, -1);
+
+ free(name);
+
+ return iter;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : store = gestionnaire de données en arborescence. *
+* symbol = routine ou objet à intégrer. *
+* match = portion de texte à mettre en évidence. *
+* *
+* Description : Met en surbrillance les éléments recherchés dans les noms. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void update_symbol_name_in_tree_view(GtkTreeStore *store, const GBinSymbol *symbol, const regmatch_t *match)
+{
+ const char *label; /* Etiquette immuable */
+ char *string; /* Etiquette modifiable */
+ const char *sep; /* Délimitateur à utiliser */
+ GtkTreeIter parent; /* Point d'analyse courant */
+ char *start; /* Début de boucle de parcours */
+ char *token; /* Partie de texte isolée */
+ char *saveptr; /* Ctx. interne de découpage */
+
+ label = g_binary_symbol_get_label(symbol);
+
+ if (label != NULL)
+ {
+ string = strdup(label);
+
+ sep = "."/*"::"*/; /* FIXME */
+
+ for (start = string, token = strtok_r(start, sep, &saveptr);
+ token != NULL;
+ start = NULL, token = strtok_r(NULL, sep, &saveptr))
+ {
+ parent = update_symbol_partial_name_in_tree_view(store, (start == string ? NULL : &parent),
+ token, match, token - string);
+ }
+
+ free(string);
+
+ }
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* FILTRAGE DES SYMBOLES PRESENTS */
@@ -1036,14 +1313,79 @@ static void on_symbols_filter_changed(GtkSearchEntry *entry, GSymbolsPanel *pane
{
update_regex_on_search_entry_changed(entry, &panel->filter);
- do_filtering_on_symbols(panel);
+ run_panel_update(G_UPDATABLE_PANEL(panel), PUI_1);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : store = organisation des données sous forme arborescente. *
+* iter = position du noeud courant à traiter. *
+* show = visibilité à obtenir pour le noeud final. *
+* *
+* Description : Met à jour l'affichage des noeuds en fonction des besoin. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void update_symbol_visibility(GtkTreeStore *store, GtkTreeIter *iter, bool show)
+{
+ GtkTreeModel *model; /* Autre vision du gestionnaire*/
+ guint points; /* Compteur de besoins */
+ GtkTreeIter parent; /* Position de noeuf parent */
+ gboolean further; /* Poursuite de remontée */
+
+ model = GTK_TREE_MODEL(store);
+
+ /* Enumération des besoins */
+
+ gtk_tree_model_get(model, iter, SBC_MATCH_POINTS, &points, -1);
+
+ if (show)
+ points++;
+
+ else
+ {
+ assert(points > 0);
+ points--;
+ }
+
+ gtk_tree_store_set(store, iter, SBC_MATCH_POINTS, points, -1);
+
+ /* Adaptation de l'affichage */
+
+ if (show)
+ {
+ if (points == 1)
+ gtk_tree_store_set(store, iter, SBC_MATCHED, true, -1);
+ }
+
+ else
+ {
+ if (points == 0)
+ gtk_tree_store_set(store, iter, SBC_MATCHED, false, -1);
+ }
+
+ /* Eventuel étage supérieur */
+
+ further = gtk_tree_model_iter_parent(model, &parent, iter);
+
+ if (further)
+ update_symbol_visibility(store, &parent, show);
}
/******************************************************************************
* *
-* Paramètres : panel = panneau assurant l'affichage des symboles. *
+* Paramètres : panel = panneau assurant l'affichage des symboles. *
+* status = barre de statut à tenir informée. *
+* id = identifiant pour le suivi de la progression. *
+* data = données complémentaire à manipuler. *
* *
* Description : Exécute un nouveau filtrage des symboles affichés. *
* *
@@ -1053,11 +1395,64 @@ static void on_symbols_filter_changed(GtkSearchEntry *entry, GSymbolsPanel *pane
* *
******************************************************************************/
-static void do_filtering_on_symbols(GSymbolsPanel *panel)
+static void do_filtering_on_symbols(const GSymbolsPanel *panel, GtkStatusStack *status, activity_id_t id, symbols_update_data *data)
{
- g_object_ref(G_OBJECT(panel->binary));
- change_symbols_panel_current_binary(panel, panel->binary);
- g_object_unref(G_OBJECT(panel->binary));
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeStore *store; /* Modèle de gestion */
+ GtkToggleToolButton *button; /* Mode de représentation */
+ gboolean as_list; /* Choix dudit mode */
+
+
+ gboolean filter_symbol_panel_iter(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gboolean *as_list)
+ {
+ GBinSymbol *symbol; /* Symbole manipulé */
+ regmatch_t match; /* Récupération des trouvailles*/
+ bool matched; /* Correspondance de sélection */
+ gboolean shown; /* Visibilité actuelle */
+
+ gtk_tree_model_get(model, iter, SBC_SYMBOL, &symbol, -1);
+
+ if (symbol != NULL)
+ {
+ matched = is_symbol_matching(panel, symbol, &match);
+
+ gtk_tree_model_get(model, iter, SBC_MATCHED, &shown, -1);
+
+ if (!matched)
+ {
+ if (shown)
+ update_symbol_visibility(store, iter, false);
+ }
+
+ else
+ {
+ if (*as_list)
+ update_symbol_name_in_list_view(store, iter, &match);
+ else
+ update_symbol_name_in_tree_view(store, symbol, &match);
+
+ if (!shown)
+ update_symbol_visibility(store, iter, true);
+
+ }
+
+ g_object_unref(G_OBJECT(symbol));
+
+ }
+
+ return FALSE;
+
+ }
+
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ store = GTK_TREE_STORE(gtk_builder_get_object(builder, "store"));
+ button = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(builder, "list_display"));
+
+ as_list = gtk_toggle_tool_button_get_active(button);
+
+ gtk_tree_model_foreach(GTK_TREE_MODEL(store), (GtkTreeModelForeachFunc)filter_symbol_panel_iter, &as_list);
}
@@ -1076,29 +1471,258 @@ static void do_filtering_on_symbols(GSymbolsPanel *panel)
* *
******************************************************************************/
-static bool is_symbol_matching(GSymbolsPanel *panel, const GBinSymbol *symbol, regmatch_t *match)
+static bool is_symbol_matching(const GSymbolsPanel *panel, const GBinSymbol *symbol, regmatch_t *match)
{
bool result; /* Bilan à retourner */
- SymbolStatus status; /* Visibilité du symbole obtenu*/
+#ifndef NDEBUG
SymbolType type; /* Type associé au symbole */
+#endif
- status = g_binary_symbol_get_status(symbol);
+#ifndef NDEBUG
- if (status == SSS_IMPORTED)
- result = false;
+ type = g_binary_symbol_get_target_type(symbol);
- else
+ assert(type == STP_ROUTINE || type == STP_ENTRY_POINT || type == STP_OBJECT);
+
+#endif
+
+ result = is_content_matching(panel->filter, g_binary_symbol_get_label(symbol), match);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MECANISMES DE MISE A JOUR DE PANNEAU */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* 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] *
+* *
+* Description : Prépare une opération de mise à jour de panneau. *
+* *
+* Retour : Description du message d'information. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static const char *g_symbols_panel_setup(const GSymbolsPanel *panel, unsigned int uid, size_t *count, symbols_update_data **data)
+{
+ const char *result; /* Message à retourner */
+ GBinFormat *format; /* Format du binaire */
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeView *treeview; /* Arborescence graphique */
+
+ *data = malloc(sizeof(symbols_update_data));
+
+ switch (uid)
{
- type = g_binary_symbol_get_target_type(symbol);
+ case PUI_0:
- if (type != STP_ROUTINE && type != STP_ENTRY_POINT && type != STP_OBJECT)
- result = false;
+ format = G_BIN_FORMAT(g_loaded_binary_get_format(panel->binary));
- else
- result = is_content_matching(panel->filter, g_binary_symbol_get_label(symbol), match);
+ g_binary_format_lock_symbols_rd(format);
+ *count = g_binary_format_count_symbols(format);
+ g_binary_format_unlock_symbols_rd(format);
+
+ g_object_unref(G_OBJECT(format));
+
+ (*data)->count = 0;
+
+ result = _("Loading symbols registered for the binary format...");
+
+ break;
+
+ case PUI_1:
+
+ *count = panel->count;
+ (*data)->count = panel->count;
+
+ result = _("Filtering symbols registered for the binary format...");
+
+ break;
+
+ }
+
+ /* Mémorisation de tous les noeuds ouverts */
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+ void keep_track_of_expanded(GtkTreeView *tv, GtkTreePath *path, symbols_update_data *sud)
+ {
+ if (sud->ecount == sud->eallocated)
+ {
+ sud->eallocated += EXPAND_ALLOC_RANGE;
+ sud->expanded = (char **)realloc(sud->expanded, sud->eallocated * sizeof(char *));
+ }
+
+ sud->expanded[sud->ecount] = gtk_tree_path_to_string(path);
+
+ sud->ecount++;
}
+ (*data)->expanded = NULL;
+ (*data)->ecount = 0;
+ (*data)->eallocated = 0;
+
+ gtk_tree_view_map_expanded_rows(treeview, (GtkTreeViewMappingFunc)keep_track_of_expanded, *data);
+
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 : Cette fonction est appelée depuis le contexte principal. *
+* *
+******************************************************************************/
+
+static void g_symbols_panel_introduce(const GSymbolsPanel *panel, unsigned int uid, symbols_update_data *data)
+{
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeView *treeview; /* Arborescence graphique */
+
+ /* Basculement de l'affichage hors ligne */
+
+ g_panel_item_switch_to_updating_mask(G_PANEL_ITEM(panel));
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+ data->model = gtk_tree_view_get_model(treeview);
+ g_object_ref(G_OBJECT(data->model));
+
+ gtk_tree_view_set_model(treeview, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* 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 g_symbols_panel_process(const GSymbolsPanel *panel, unsigned int uid, GtkStatusStack *status, activity_id_t id, symbols_update_data *data)
+{
+ switch (uid)
+ {
+ case PUI_0:
+ reload_symbols_panel_content(panel, status, id, data);
+ break;
+
+ case PUI_1:
+ do_filtering_on_symbols(panel, status, id, data);
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* 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 : Cette fonction est appelée depuis le contexte principal. *
+* *
+******************************************************************************/
+
+static void g_symbols_panel_conclude(GSymbolsPanel *panel, unsigned int uid, symbols_update_data *data)
+{
+ GtkBuilder *builder; /* Constructeur utilisé */
+ GtkTreeView *treeview; /* Arborescence graphique */
+ size_t i; /* Boucle de parcours */
+ GtkTreePath *path; /* Chemin d'accès à un noeud */
+
+ /* Mise à jour des compteurs */
+
+ panel->count = data->count;
+
+ /* Basculement de l'affichage en ligne */
+
+ builder = G_PANEL_ITEM(panel)->builder;
+
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview"));
+
+ gtk_tree_view_set_model(treeview, data->model);
+
+ g_object_unref(G_OBJECT(data->model));
+
+ for (i = 0; i < data->ecount; i++)
+ {
+ path = gtk_tree_path_new_from_string(data->expanded[i]);
+
+ gtk_tree_view_expand_to_path(treeview, path);
+
+ gtk_tree_path_free(path);
+
+ }
+
+ g_panel_item_switch_to_updated_content(G_PANEL_ITEM(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* 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 g_symbols_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, symbols_update_data *data)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < data->ecount; i++)
+ g_free(data->expanded[i]);
+
+ if (data->expanded != NULL)
+ free(data->expanded);
+
+}
diff --git a/src/gui/panels/symbols.ui b/src/gui/panels/symbols.ui
new file mode 100644
index 0000000..284e00a
--- /dev/null
+++ b/src/gui/panels/symbols.ui
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.21.0 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="store">
+ <columns>
+ <!-- column-name symbol -->
+ <column type="GObject"/>
+ <!-- column-name icon -->
+ <column type="CairoSurface"/>
+ <!-- column-name name -->
+ <column type="gchararray"/>
+ <!-- column-name original -->
+ <column type="gchararray"/>
+ <!-- column-name address -->
+ <column type="gchararray"/>
+ <!-- column-name section -->
+ <column type="gchararray"/>
+ <!-- column-name expand -->
+ <column type="gboolean"/>
+ <!-- column-name matched -->
+ <column type="gboolean"/>
+ <!-- column-name match_points -->
+ <column type="guint"/>
+ </columns>
+ </object>
+ <object class="GtkTreeModelSort" id="sorter">
+ <property name="model">store</property>
+ </object>
+ <object class="GtkTreeModelFilter" id="filter">
+ <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="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="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="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="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="resource">/org/chrysalide/gui/panels/../../../pixmaps/tbutton_tree_view.png</property>
+ </object>
+ <object class="GtkOffscreenWindow">
+ <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="orientation">vertical</property>
+ <child>
+ <object class="GtkToolbar">
+ <property name="visible">True</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="active">True</property>
+ <property name="group">tree_display</property>
+ <signal name="toggled" handler="on_symbols_list_display_toggle" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <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>
+ <signal name="toggled" handler="on_symbols_tree_display_toggle" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <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>
+ <signal name="clicked" handler="reorganize_symbols_tree_view" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <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>
+ <signal name="clicked" handler="reorganize_symbols_tree_view" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <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>
+ <signal name="clicked" handler="reorganize_symbols_tree_view" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSeparatorToolItem">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem">
+ <property name="visible">True</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>
+ <signal name="search-changed" handler="on_symbols_filter_changed" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="visible">True</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>
+ <child>
+ <object class="GtkTreeView" id="treeview">
+ <property name="name">treeview</property>
+ <property name="visible">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>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection">
+ <signal name="changed" handler="on_symbols_selection_change" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">page0</property>
+ <property name="title" translatable="yes">page0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinner" id="mask">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="active">True</property>
+ </object>
+ <packing>
+ <property name="name">page1</property>
+ <property name="title" translatable="yes">page1</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </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 eea8e3b..0007a5a 100644
--- a/src/gui/panels/updating-int.h
+++ b/src/gui/panels/updating-int.h
@@ -41,6 +41,9 @@ typedef void (* process_updatable_cb) (const GUpdatablePanel *, unsigned int, Gt
/* Bascule l'affichage d'un panneau après mise à jour. */
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 *);
+
/* Mécanisme de mise à jour d'un panneau (interface) */
struct _GUpdatablePanelIface
@@ -53,6 +56,7 @@ struct _GUpdatablePanelIface
introduce_updatable_cb introduce; /* Changement d'affichage #0 */
process_updatable_cb process; /* Mise à jour d'affichage */
conclude_updatable_cb conclude; /* Changement d'affichage #1 */
+ clean_updatable_data_cb clean; /* Nettoyage des données */
};
diff --git a/src/gui/panels/updating.c b/src/gui/panels/updating.c
index 15955dc..2dec844 100644
--- a/src/gui/panels/updating.c
+++ b/src/gui/panels/updating.c
@@ -219,6 +219,32 @@ void g_updatable_panel_conclude(GUpdatablePanel *panel, unsigned int uid, void *
}
+/******************************************************************************
+* *
+* 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 : - *
+* *
+******************************************************************************/
+
+void g_updatable_panel_clean_data(GUpdatablePanel *panel, unsigned int uid, void *data)
+{
+ GUpdatablePanelIface *iface; /* Interface utilisée */
+
+ iface = G_UPDATABLE_PANEL_GET_IFACE(panel);
+
+ if (iface->clean != NULL && data != NULL)
+ iface->clean(panel, uid, data);
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* AIDE POUR LA MISE A JOUR */
@@ -311,6 +337,8 @@ 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);
diff --git a/src/gui/panels/updating.h b/src/gui/panels/updating.h
index 4edf498..b02f1af 100644
--- a/src/gui/panels/updating.h
+++ b/src/gui/panels/updating.h
@@ -67,6 +67,9 @@ void g_updatable_panel_process(const GUpdatablePanel *, unsigned int, GtkStatusS
/* Bascule l'affichage d'un panneau après mise à jour. */
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 *);
+
/* ---------------------------- AIDE POUR LA MISE A JOUR ---------------------------- */