From d0a25ef16eef28d0cc355b00f5874c6c28004c78 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
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 <nocbos@gmail.com>
+
+	* src/gui/panels/history.c:
+	Properly handle the history selection and update the history on changes.
+
 15-08-04  Cyrille Bagard <nocbos@gmail.com>
 
 	* 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