From d0a25ef16eef28d0cc355b00f5874c6c28004c78 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 5 Aug 2015 19:01:38 +0000 Subject: Properly handled the history selection and updated the history on changes. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@566 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 5 ++ src/gui/panels/history.c | 178 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 140 insertions(+), 43 deletions(-) diff --git a/ChangeLog b/ChangeLog index 140dc62..25a9176 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +15-08-05 Cyrille Bagard + + * src/gui/panels/history.c: + Properly handle the history selection and update the history on changes. + 15-08-04 Cyrille Bagard * src/analysis/db/collection.c: diff --git a/src/gui/panels/history.c b/src/gui/panels/history.c index 1e86880..7d0cdd5 100644 --- a/src/gui/panels/history.c +++ b/src/gui/panels/history.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * history.c - panneau de la liste des évolutions d'utilisateur(s) * - * Copyright (C) 2008-2013 Cyrille Bagard + * Copyright (C) 2015 Cyrille Bagard * * This file is part of Chrysalide. * @@ -94,8 +94,8 @@ static void on_history_changed(GDbCollection *, DBAction, GDbItem *, GHistoryPan /* Compare deux lignes entre elles pour le tri des évolutions. */ static gint sort_history_lines(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *, gpointer); -/* Réagit à une validation d'une ligne affichée. */ -static void on_history_row_activated(GtkTreeView *, GtkTreePath *, GtkTreeViewColumn *, GHistoryPanel *); +/* Réagit au changement de sélection des éléments d'historique. */ +static void on_history_selection_change(GtkTreeSelection *, GHistoryPanel *); /* Annule l'élément d'évolution courant. */ static void do_history_undo(GtkButton *, GHistoryPanel *); @@ -163,6 +163,7 @@ static void g_history_panel_init(GHistoryPanel *panel) GtkTreeViewColumn *column; /* Colonne de la liste */ GtkWidget *box; /* Séparation horizontale */ GtkWidget *button; /* Bouton de cette même barre */ + GtkTreeSelection *select; /* Sélection dans la liste */ base = G_EDITOR_ITEM(panel); @@ -170,8 +171,7 @@ static void g_history_panel_init(GHistoryPanel *panel) gtk_container_set_border_width(GTK_CONTAINER(base->widget), 8); gtk_widget_show(base->widget); - ref = G_OBJECT(base->widget); - g_object_set_data(ref, "panel", panel); + ref = G_OBJECT(panel); /* Liste des éléments d'évolution */ @@ -194,8 +194,6 @@ static void g_history_panel_init(GHistoryPanel *panel) gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(panel->store), sort_history_lines, NULL, NULL); - g_signal_connect(treeview, "row-activated", G_CALLBACK(on_history_row_activated), panel); - gtk_widget_show(treeview); gtk_container_add(GTK_CONTAINER(scrollwnd), treeview); @@ -226,11 +224,11 @@ static void g_history_panel_init(GHistoryPanel *panel) gtk_widget_show(box); gtk_box_pack_start(GTK_BOX(base->widget), box, FALSE, TRUE, 0); - button = qck_create_button_with_css_img(NULL, NULL, "img-undo", _("Undo"), + button = qck_create_button_with_css_img(ref, "undo", "img-undo", _("Undo"), G_CALLBACK(do_history_undo), panel); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); - button = qck_create_button_with_css_img(NULL, NULL, "img-redo", _("Redo"), + button = qck_create_button_with_css_img(ref, "redo", "img-redo", _("Redo"), G_CALLBACK(do_history_redo), panel); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); @@ -238,6 +236,12 @@ static void g_history_panel_init(GHistoryPanel *panel) G_CALLBACK(do_history_clean), panel); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); + /* Prise en compte de la sélection */ + + select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); + gtk_tree_selection_set_mode(select, GTK_SELECTION_BROWSE); + g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(on_history_selection_change), panel); + } @@ -349,27 +353,39 @@ GPanelItem *create_history_panel(GObject *ref) static void change_history_panel_current_binary(GHistoryPanel *panel, GLoadedBinary *binary) { - - - GtkTreeStore *store; /* Modèle de gestion */ GList *collections; /* Ensemble de collections */ GList *c; /* Boucle de parcours #1 */ GDbCollection *collec; /* Collection visée manipulée */ + GtkTreeStore *store; /* Modèle de gestion */ GList *items; /* Liste des éléments groupés */ GList *i; /* Boucle de parcours #2 */ GDbItem *item; /* Elément à intégrer */ GtkTreeIter iter; /* Point d'insertion */ - /* Basculement du binaire utilisé */ + if (panel->binary != NULL) + { + collections = g_loaded_binary_get_all_collections(panel->binary); + rlock_collections(collections); - panel->binary = binary; + for (c = g_list_first(collections); c != NULL; c = g_list_next(c)) + { + collec = G_DB_COLLECTION(c->data); + g_signal_handlers_disconnect_by_func(collec, G_CALLBACK(on_history_changed), panel); + } + runlock_collections(collections); + g_object_unref(G_OBJECT(panel->binary)); + } + panel->binary = binary; + + if (panel->binary != NULL) + g_object_ref(G_OBJECT(binary)); store = GTK_TREE_STORE(gtk_tree_view_get_model(panel->treeview)); gtk_tree_store_clear(store); @@ -410,6 +426,9 @@ static void change_history_panel_current_binary(GHistoryPanel *panel, GLoadedBin runlock_collections(collections); + /* Force une sélection initiale */ + on_history_changed(NULL, DBA_COUNT, NULL, panel); + } @@ -432,34 +451,102 @@ static void on_history_changed(GDbCollection *collec, DBAction action, GDbItem * { GtkTreeModel *model; /* Modèle de gestion courant */ GtkTreeIter iter; /* Boucle de parcours */ - GDbItem *displayed; /* Elément de collection */ + GtkTreeSelection *selection; /* Nouvelle sélection à établir*/ model = GTK_TREE_MODEL(panel->store); - switch (action) + /* Mise à jour de la liste affichée */ + + bool find_changed_item(GtkTreeModel *_model, GDbItem *target, GtkTreeIter *_found) { - case DBA_CHANGE_STATE: + bool status; + GtkTreeIter candidate; + GDbItem *displayed; + + status = false; + + if (gtk_tree_model_get_iter_first(_model, &candidate)) + do + { + gtk_tree_model_get(_model, &candidate, HTC_ITEM, &displayed, -1); - if (gtk_tree_model_get_iter_first(model, &iter)) - do + if (target == displayed) { - gtk_tree_model_get(model, &iter, HTC_ITEM, &displayed, -1); + *_found = candidate; + status = true; + } - if (item == displayed) - { - gtk_tree_store_set(panel->store, &iter, - HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", - -1); - break; - } + g_object_unref(G_OBJECT(displayed)); - g_object_unref(G_OBJECT(displayed)); + } + while (!status && gtk_tree_model_iter_next(_model, &candidate)); - } - while (gtk_tree_model_iter_next(model, &iter)); + return status; + + } + + switch (action) + { + case DBA_ADD_ITEM: + + gtk_tree_store_append(panel->store, &iter, NULL); + gtk_tree_store_set(panel->store, &iter, + HTC_ITEM, item, + //HTC_PICTURE, G_BOOKMARKS_PANEL_GET_CLASS(panel)->bookmark_img, + HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", + HTC_LABEL, g_db_item_get_label(item), + -1); break; + case DBA_REM_ITEM: + + if (find_changed_item(model, item, &iter)) + gtk_tree_store_remove(panel->store, &iter); + + break; + + case DBA_CHANGE_STATE: + + if (find_changed_item(model, item, &iter)) + gtk_tree_store_set(panel->store, &iter, + HTC_FOREGROUND, g_db_item_is_active(item) ? NULL : "grey", + -1); + break; + + case DBA_COUNT: + /* Actualisation artificielle de la sélection */ + break; + + } + + /* Redéfinition de la sélection */ + + if (gtk_tree_model_get_iter_first(model, &iter)) + { + gboolean find_last_active(GtkTreeModel *_model, GtkTreePath *_path, GtkTreeIter *_iter, GtkTreeIter *last) + { + GDbItem *item; + gboolean active; + + gtk_tree_model_get(_model, _iter, HTC_ITEM, &item, -1); + + active = g_db_item_is_active(item); + + g_object_unref(G_OBJECT(item)); + + if (active) + *last = *_iter; + + return !active; + + } + + gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc)find_last_active, &iter); + + selection = gtk_tree_view_get_selection(panel->treeview); + gtk_tree_selection_select_iter(selection, &iter); + } } @@ -501,12 +588,10 @@ static gint sort_history_lines(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter /****************************************************************************** * * -* Paramètres : treeview = composant graphique manipulé par l'utilisateur. * -* path = chemin d'accès à la ligne activée. * -* column = colonne impactée par l'action. * -* panel = panneau d'historique concerné par la procédure. * +* Paramètres : selection = sélection modifiée. * +* panel = structure contenant les informations maîtresses. * * * -* Description : Réagit à une validation d'une ligne affichée. * +* Description : Réagit au changement de sélection des éléments d'historique. * * * * Retour : - * * * @@ -514,20 +599,30 @@ static gint sort_history_lines(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter * * ******************************************************************************/ -static void on_history_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, GHistoryPanel *panel) +static void on_history_selection_change(GtkTreeSelection *selection, GHistoryPanel *panel) { + GtkTreeIter iter; /* Point de sélection */ + GtkTreeModel *model; /* Modèle de gestion */ + GDbItem *item; /* Elément de collection */ + GtkWidget *button; /* Bouton de barre de contrôle */ + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + gtk_tree_model_get(model, &iter, HTC_ITEM, &item, -1); + button = GTK_WIDGET(g_object_get_data(G_OBJECT(panel), "undo")); + gtk_widget_set_sensitive(button, g_db_item_is_active(item)); + button = GTK_WIDGET(g_object_get_data(G_OBJECT(panel), "redo")); + gtk_widget_set_sensitive(button, !g_db_item_is_active(item)); + g_object_unref(G_OBJECT(item)); + } } - - - /****************************************************************************** * * * Paramètres : button = bouton d'édition de l'historique d'évolution. * @@ -622,9 +717,6 @@ static void do_history_redo(GtkButton *button, GHistoryPanel *panel) static void do_history_clean(GtkButton *button, GHistoryPanel *panel) { - - - - + /* TODO */ } -- cgit v0.11.2-87-g4458