From ed59530ca0cc8e4cf03ea8328122bb3d279840a9 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 9 Jun 2013 14:01:57 +0000 Subject: Improved the whole symbols panel and added a filter on it. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@351 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 15 ++ pixmaps/Makefile.am | 1 - pixmaps/tbutton_namespace.png | Bin 358 -> 0 bytes src/gtkext/easygtk.c | 11 +- src/gtkext/easygtk.h | 4 +- src/gui/panels/symbols.c | 327 ++++++++++++++++++++++++++++++++++++------ 6 files changed, 309 insertions(+), 49 deletions(-) delete mode 100644 pixmaps/tbutton_namespace.png diff --git a/ChangeLog b/ChangeLog index 7fcc79d..e8d9c4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +13-06-09 Cyrille Bagard + + * pixmaps/Makefile.am: + Remove 'tbutton_namespace.png' from TOOLBAR_BUTTONS. + + * pixmaps/tbutton_namespace.png: + Deleted entry. + + * src/gtkext/easygtk.c: + * src/gtkext/easygtk.h: + Set captions for toolbar buttons. + + * src/gui/panels/symbols.c: + Improve the whole symbols panel and add a filter on it. + 13-06-08 Cyrille Bagard * src/Makefile.am: diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am index 2029a8a..5b1c100 100644 --- a/pixmaps/Makefile.am +++ b/pixmaps/Makefile.am @@ -21,7 +21,6 @@ TOOLBAR_BUTTONS = \ tbutton_collapse.png \ tbutton_expand.png \ tbutton_list_view.png \ - tbutton_namespace.png \ tbutton_tree_view.png LIST_ICONS = \ diff --git a/pixmaps/tbutton_namespace.png b/pixmaps/tbutton_namespace.png deleted file mode 100644 index 10bfe98..0000000 Binary files a/pixmaps/tbutton_namespace.png and /dev/null differ diff --git a/src/gtkext/easygtk.c b/src/gtkext/easygtk.c index 2d000e7..be65578 100644 --- a/src/gtkext/easygtk.c +++ b/src/gtkext/easygtk.c @@ -800,6 +800,7 @@ GtkWidget *qck_create_menu_separator(void) * * * Paramètres : object = espace dédié à l'inscription de références. * * name = nom à donner au nouveau composant. * +* caption = étquette pour le bouton ou NULL. * * filename = nom du fichier d'image à charger. * * handler = éventuelle fonction de sélection associée. * * data = données à transmettre avec l'événement si besoin. * @@ -812,13 +813,13 @@ GtkWidget *qck_create_menu_separator(void) * * ******************************************************************************/ -GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char *filename, GCallback handler, gpointer data) +GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char *caption, const char *filename, GCallback handler, gpointer data) { GtkWidget *result; /* Résultat à renvoyer */ GtkWidget *image; /* Image de représentation */ image = get_image_from_file(filename); - result = GTK_WIDGET(gtk_tool_button_new(image, NULL)); + result = GTK_WIDGET(gtk_tool_button_new(image, caption)); if (G_IS_OBJECT(object) && name != NULL) { @@ -840,6 +841,7 @@ GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char * * * Paramètres : object = espace dédié à l'inscription de références. * * name = nom à donner au nouveau composant. * +* caption = étquette pour le bouton ou NULL. * * filename = nom du fichier d'image à charger. * * handler = éventuelle fonction de sélection associée. * * data = données à transmettre avec l'événement si besoin. * @@ -852,13 +854,16 @@ GtkWidget *qck_create_tool_button(GObject *object, const char *name, const char * * ******************************************************************************/ -GtkWidget *qck_create_toggle_tool_button(GObject *object, const char *name, const char *filename, GCallback handler, gpointer data) +GtkWidget *qck_create_toggle_tool_button(GObject *object, const char *name, const char *caption, const char *filename, GCallback handler, gpointer data) { GtkWidget *result; /* Résultat à renvoyer */ GtkWidget *image; /* Image de représentation */ result = GTK_WIDGET(gtk_toggle_tool_button_new()); + if (caption != NULL) + gtk_tool_button_set_label(GTK_TOOL_BUTTON(result), caption); + image = get_image_from_file(filename); gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(result), image); diff --git a/src/gtkext/easygtk.h b/src/gtkext/easygtk.h index 815e5c2..31a2b78 100644 --- a/src/gtkext/easygtk.h +++ b/src/gtkext/easygtk.h @@ -99,10 +99,10 @@ GtkWidget *qck_create_menu_separator(void); /* Crée et enregistre un composant 'GtkToolButton'. */ -GtkWidget *qck_create_tool_button(GObject *, const char *, const char *, GCallback, gpointer); +GtkWidget *qck_create_tool_button(GObject *, const char *, const char *, const char *, GCallback, gpointer); /* Crée et enregistre un composant 'GtkToggleToolButton'. */ -GtkWidget *qck_create_toggle_tool_button(GObject *, const char *, const char *, GCallback, gpointer); +GtkWidget *qck_create_toggle_tool_button(GObject *, const char *, const char *, const char *, GCallback, gpointer); /* Crée et enregistre un composant 'GtkSeparatorToolItem'. */ GtkWidget *qck_create_tool_separator(GObject *, const char *); diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c index 0073318..c04b460 100644 --- a/src/gui/panels/symbols.c +++ b/src/gui/panels/symbols.c @@ -25,7 +25,13 @@ #include "symbols.h" +#include + + +#include +#include #include +#include #include "panel-int.h" @@ -48,8 +54,9 @@ struct _GSymbolsPanel GLoadedBinary *binary; /* Binaire à prendre en compte */ -}; + regex_t *filter; /* Filtre appliqué ou NULL */ +}; /* Panneau d'aperçu de graphiques (classe) */ struct _GSymbolsPanelClass @@ -80,6 +87,9 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *); /* Initialise une instance de panneau d'aperçu de graphiques. */ static void g_symbols_panel_init(GSymbolsPanel *); +/* Réagit au changement d'affichage des symboles. */ +static void on_symbols_display_change(GtkToggleToolButton *, GSymbolsPanel *); + /* Réagit au changement de sélection des symboles. */ static void on_symbols_selection_change(GtkTreeSelection *, GSymbolsPanel *); @@ -114,8 +124,22 @@ static void reorganize_symbols_tree_view(GtkToolButton *, GObject *); /* Fait en sorte que toutes les classes soient affichées. */ static gboolean show_all_classes_in_tree_view(GtkTreeModel *, GtkTreePath *, GtkTreeIter *, GtkTreeView *); -/* Réagit à une demande de nouvelle forme d'affichage. */ -static void modify_types_in_symbols_tree_view(GtkToggleToolButton *, GObject *); + + +/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */ + + +/* Démarre l'actualisation du filtrage des symboles. */ +static gboolean filter_symbols_from_key_press(GtkEntry *, GdkEventKey *, GSymbolsPanel *); + +/* Démarre l'actualisation du filtrage des symboles. */ +static void filter_symbols_from_icons(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GSymbolsPanel *); + +/* Exécute un nouveau filtrage des symboles affichés. */ +static void do_filtering_on_symbols(GSymbolsPanel *, GtkEntry *); + +/* Détermine si un nom de symbole doit être filtré ou non. */ +static bool is_symbol_filtered(GSymbolsPanel *, const char *); @@ -162,9 +186,11 @@ static void g_symbols_panel_init(GSymbolsPanel *panel) { GEditorItem *base; /* Version basique d'instance */ 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 *entry; /* Zone de recherche */ GtkWidget *scrollwnd; /* Support défilant */ GtkWidget *treeview; /* Affichage de la liste */ GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ @@ -181,44 +207,64 @@ static void g_symbols_panel_init(GSymbolsPanel *panel) /* Barre d'outils supérieure */ + box = gtk_hbox_new(FALSE, 0); + 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(base->widget), toolbar, FALSE, FALSE, 0); - - //group = gtk_tool_item_group_new(_("View")); - //gtk_widget_show(group); - //gtk_container_add(GTK_CONTAINER(toolbar), group); - - button = qck_create_toggle_tool_button(ref, "list", "tbutton_list_view.png", G_CALLBACK(NULL), NULL); - gtk_container_add(GTK_CONTAINER(toolbar), button); - //gtk_tool_item_group_insert(GTK_TOOL_ITEM_GROUP(group), GTK_TOOL_ITEM(button), -1); - - button = qck_create_toggle_tool_button(ref, "tree", "tbutton_tree_view.png", G_CALLBACK(NULL), NULL); - gtk_container_add(GTK_CONTAINER(toolbar), button); + 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); - //gtk_tool_item_group_insert(GTK_TOOL_ITEM_GROUP(group), GTK_TOOL_ITEM(button), -1); + 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); + 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); - button = qck_create_tool_button(ref, "collapse", "tbutton_collapse.png", G_CALLBACK(reorganize_symbols_tree_view), ref); - gtk_container_add(GTK_CONTAINER(toolbar), button); + /* Espace de recherche */ - button = qck_create_tool_button(ref, "expand", "tbutton_expand.png", G_CALLBACK(reorganize_symbols_tree_view), ref); - gtk_container_add(GTK_CONTAINER(toolbar), button); + entry = qck_create_entry(ref, "search", ""); + gtk_widget_set_tooltip_text(entry, _("Filter symbols using POSIX extended regular expressions")); - button = qck_create_tool_button(ref, "classes", "symbol_class_classic.png", G_CALLBACK(reorganize_symbols_tree_view), ref); - gtk_container_add(GTK_CONTAINER(toolbar), button); + gtk_entry_set_icon_from_stock(GTK_ENTRY(entry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_FIND); - separator = qck_create_tool_separator(NULL, NULL); - gtk_container_add(GTK_CONTAINER(toolbar), separator); + g_signal_connect(G_OBJECT(entry), "key-press-event", + G_CALLBACK(filter_symbols_from_key_press), panel); + g_signal_connect(G_OBJECT(entry), "icon-press", + G_CALLBACK(filter_symbols_from_icons), panel); - button = qck_create_toggle_tool_button(ref, "namespace", "tbutton_namespace.png", G_CALLBACK(modify_types_in_symbols_tree_view), ref); - gtk_container_add(GTK_CONTAINER(toolbar), button); + gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); /* Liste arborescente ou linéaire */ @@ -333,6 +379,72 @@ GPanelItem *create_symbols_panel(GObject *ref) /****************************************************************************** * * +* Paramètres : button = bouton de la barre activé. * +* panel = structure contenant les informations maîtresses. * +* * +* Description : Réagit au changement d'affichage des symboles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_symbols_display_change(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 */ + + ref = G_OBJECT(G_EDITOR_ITEM(panel)->widget); + + list = GTK_TOGGLE_TOOL_BUTTON(g_object_get_data(ref, "list")); + tree = GTK_TOGGLE_TOOL_BUTTON(g_object_get_data(ref, "tree")); + + /* Désactivation de l'autre bouton */ + + state = gtk_toggle_tool_button_get_active(button); + + if (button == list) other = tree; + else other = list; + + 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); + + /* Définition des accès sur le reste de la barre */ + + 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); + + /* Actualisation */ + + 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)); + } + +} + + +/****************************************************************************** +* * * Paramètres : selection = sélection modifiée. * * panel = structure contenant les informations maîtresses. * * * @@ -437,8 +549,10 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) size_t routines_count; /* Nombre de ces routines */ GArchProcessor *proc; /* Architecture utilisée */ size_t i; /* Boucle de parcours */ + const char *name; /* Désignation du symbole */ vmpa_t address; /* Adresse associée au symbole */ char tmp[VMPA_MAX_SIZE]; /* Version humainement lisible */ + GdkPixbuf *pixbuf; /* Icone pour l'élément inséré */ GtkTreeIter iter; /* Point d'insertion */ format = g_loaded_binary_get_format(panel->binary); @@ -452,13 +566,21 @@ static void reload_symbols_for_new_list_view(GSymbolsPanel *panel) for (i = 0; i < routines_count; i++) { + name = g_binary_routine_to_string(routines[i]); + + if (is_symbol_filtered(panel, name)) + continue; + address = g_binary_routine_get_address(routines[i]); vmpa_to_string(address, g_arch_processor_get_memory_size(proc), tmp); + pixbuf = get_pixbuf_from_file("symbol_routine_classic.png"); + gtk_tree_store_append(panel->store, &iter, NULL); gtk_tree_store_set(panel->store, &iter, + SBC_ICON, pixbuf, SBC_ADDRESS, tmp, - SBC_NAME, g_binary_routine_to_string(routines[i]), + SBC_NAME, name, -1); } @@ -585,9 +707,8 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) GBinRoutine **routines; /* Liste des routines trouvées */ size_t routines_count; /* Nombre de ces routines */ GArchProcessor *proc; /* Architecture utilisée */ - Routine2StringOptions options; /* Options de rendu */ - GtkToggleToolButton *button; /* Mode de représentation */ size_t i; /* Boucle de parcours */ + const char *name; /* Désignation du symbole */ vmpa_t address; /* Adresse associée au symbole */ char tmp[VMPA_MAX_SIZE]; /* Version humainement lisible */ GtkTreeIter parent; /* Point d'insertion parent */ @@ -603,15 +724,13 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) { proc = get_arch_processor_from_format(format); - options = 0; - - button = g_object_get_data(G_OBJECT(G_EDITOR_ITEM(panel)->widget), "namespace"); - - if (gtk_toggle_tool_button_get_active(button)) - options |= RSO_LONG_TYPE; - for (i = 0; i < routines_count; i++) { + name = g_binary_routine_to_string(routines[i]); + + if (is_symbol_filtered(panel, name)) + continue; + address = g_binary_routine_get_address(routines[i]); vmpa_to_string(address, g_arch_processor_get_memory_size(proc), tmp); @@ -635,7 +754,7 @@ static void reload_symbols_for_new_tree_view(GSymbolsPanel *panel) gtk_tree_store_set(panel->store, &iter, SBC_ICON, pixbuf, SBC_ADDRESS, tmp, - SBC_NAME, _g_binary_routine_to_string(routines[i], options), + SBC_NAME, name, -1); if (pixbuf != NULL) @@ -720,12 +839,50 @@ static gboolean show_all_classes_in_tree_view(GtkTreeModel *model, GtkTreePath * } + +/* ---------------------------------------------------------------------------------- */ +/* FILTRAGE DES SYMBOLES PRESENTS */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : button = bouton concerné par l'action. * -* ref = espace de référencement des composants. * +* Paramètres : entry = entrée de texte contenant le filtre brut. * +* event = informations liées à l'événement. * +* panel = panneau assurant l'affichage des symboles. * +* * +* Description : Démarre l'actualisation du filtrage des symboles. * * * -* Description : Réagit à une demande de nouvelle forme d'affichage. * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean filter_symbols_from_key_press(GtkEntry *entry, GdkEventKey *event, GSymbolsPanel *panel) +{ + switch (event->keyval) + { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + do_filtering_on_symbols(panel, entry); + break; + + } + + return FALSE; + +} + + +/****************************************************************************** +* * +* Paramètres : entry = entrée de texte contenant le filtre brut. * +* icon_pos = position de l'image de fond. * +* event = informations liées à l'événement. * +* panel = panneau assurant l'affichage des symboles. * +* * +* Description : Démarre l'actualisation du filtrage des symboles. * * * * Retour : - * * * @@ -733,12 +890,96 @@ static gboolean show_all_classes_in_tree_view(GtkTreeModel *model, GtkTreePath * * * ******************************************************************************/ -static void modify_types_in_symbols_tree_view(GtkToggleToolButton *button, GObject *ref) +static void filter_symbols_from_icons(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GSymbolsPanel *panel) { - GSymbolsPanel *panel; /* Données du panneau */ + do_filtering_on_symbols(panel, entry); - panel = (GSymbolsPanel *)g_object_get_data(ref, "panel"); +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau assurant l'affichage des symboles. * +* entry = entrée de texte contenant le filtre brut. * +* * +* Description : Exécute un nouveau filtrage des symboles affichés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +static void do_filtering_on_symbols(GSymbolsPanel *panel, GtkEntry *entry) +{ + const gchar *text; /* Texte de l'utilisateur */ + int ret; /* Bilan de mise en place */ + GdkColor error; /* Couleur d'erreur */ + + if (panel->filter != NULL) + { + regfree(panel->filter); + free(panel->filter); + panel->filter = NULL; + } + + text = gtk_entry_get_text(entry); + + if (strlen(text) > 0) + { + panel->filter = (regex_t *)calloc(1, sizeof(regex_t)); + ret = regcomp(panel->filter, text, REG_EXTENDED); + + if (ret != 0) + { + free(panel->filter); + panel->filter = NULL; + + error.red = 65535; + error.green = 0; + error.blue = 0; + gtk_widget_modify_text(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error); + + return; + + } + + } + + gtk_widget_modify_text(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL); + + g_object_ref(G_OBJECT(panel->binary)); change_symbols_panel_current_binary(panel, panel->binary); + g_object_unref(G_OBJECT(panel->binary)); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = panneau assurant l'affichage des symboles. * +* name = désignation du symbole à traiter. * +* * +* Description : Détermine si un nom de symbole doit être filtré ou non. * +* * +* Retour : true si le symbol ne doit pas être affiché, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool is_symbol_filtered(GSymbolsPanel *panel, const char *name) +{ + regmatch_t match; /* Récupération des trouvailles*/ + int ret; /* Bilan du filtrage */ + + if (panel->filter == NULL) + return false; + + ret = regexec(panel->filter, name, 1, &match, 0); + if (ret == REG_NOMATCH) + return true; + + return false; } -- cgit v0.11.2-87-g4458