From 0769fafb253b846b58cd97c4a1df98ca7417ae1c Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 21 Feb 2018 00:02:44 +0100 Subject: Replaced the old symbol panel by a new improved one. --- ChangeLog | 28 + pixmaps/symbol_object_classic.png | Bin 0 -> 569 bytes src/gtkext/tmgt.c | 2 +- src/gui/panels/Makefile.am | 1 + src/gui/panels/errors.c | 2 +- src/gui/panels/gresource.xml | 4 + src/gui/panels/symbols.c | 1088 +++++++++++++++++++++++++++++-------- src/gui/panels/symbols.ui | 244 +++++++++ src/gui/panels/updating-int.h | 4 + src/gui/panels/updating.c | 28 + src/gui/panels/updating.h | 3 + 11 files changed, 1170 insertions(+), 234 deletions(-) create mode 100644 pixmaps/symbol_object_classic.png create mode 100644 src/gui/panels/symbols.ui diff --git a/ChangeLog b/ChangeLog index 616debb..90898d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +18-02-21 Cyrille Bagard + + * pixmaps/symbol_object_classic.png: + New entry: create an icon for object symbols. + + * src/gtkext/tmgt.c: + Typo. + + * src/gui/panels/Makefile.am: + Add the 'symbols.ui' file to UI_FILES. + + * src/gui/panels/errors.c: + Typo. + + * src/gui/panels/gresource.xml: + Update code. + + * src/gui/panels/symbols.c: + Replace the old symbol panel by a new improved one. + + * src/gui/panels/symbols.ui: + New entry: create a GUI for the symbol panel using Glade. + + * src/gui/panels/updating-int.h: + * src/gui/panels/updating.c: + * src/gui/panels/updating.h: + Clean the data used for updates when needed. + 18-02-18 Cyrille Bagard * src/gui/panels/errors.c: diff --git a/pixmaps/symbol_object_classic.png b/pixmaps/symbol_object_classic.png new file mode 100644 index 0000000..eb028ba Binary files /dev/null and b/pixmaps/symbol_object_classic.png differ 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 @@ + ../../../pixmaps/tbutton_list_view.png + ../../../pixmaps/tbutton_tree_view.png ../../../pixmaps/tbutton_collapse.png ../../../pixmaps/tbutton_expand.png + ../../../pixmaps/symbol_class_classic.png bintree.ui errors.ui + symbols.ui welcome.ui 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + store + + + sorter + + + True + False + /org/chrysalide/gui/panels/../../../pixmaps/symbol_class_classic.png + + + True + False + /org/chrysalide/gui/panels/../../../pixmaps/tbutton_collapse.png + + + True + False + /org/chrysalide/gui/panels/../../../pixmaps/tbutton_expand.png + + + True + False + /org/chrysalide/gui/panels/../../../pixmaps/tbutton_list_view.png + + + True + False + /org/chrysalide/gui/panels/../../../pixmaps/tbutton_tree_view.png + + + False + + + True + False + vertical + + + True + False + + + True + False + Show symbols using a list view + True + tbutton_list_view.png + True + tree_display + + + + False + True + + + + + True + False + Show symbols using a tree view + True + tbutton_tree_view.png + + + + False + True + + + + + True + False + + + False + True + + + + + True + False + Collapse all symbol nodes in the tree view + True + tbutton_collapse.png + + + + False + True + + + + + True + False + Expand all symbol nodes in the tree view + True + tbutton_expand.png + + + + False + True + + + + + True + False + Show all classes in the tree view + True + symbol_class_classic.png + + + + False + True + + + + + True + False + + + False + True + + + + + True + False + + + True + True + Filter symbols using POSIX extended regular expressions + edit-find-symbolic + False + False + + + + + + True + True + + + + + False + True + 0 + + + + + True + False + + + True + True + in + + + treeview + True + True + filter + False + 2 + + + + + + + + + + page0 + page0 + + + + + True + False + True + + + page1 + page1 + 1 + + + + + True + True + 1 + + + + + + + + + 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 ---------------------------- */ -- cgit v0.11.2-87-g4458