]> git.tdb.fi Git - ext/subsurface.git/commitdiff
Maintain selected rows when switching between list model and tree model
authorDirk Hohndel <dirk@hohndel.org>
Mon, 13 Aug 2012 21:53:07 +0000 (14:53 -0700)
committerDirk Hohndel <dirk@hohndel.org>
Tue, 14 Aug 2012 19:43:16 +0000 (12:43 -0700)
We keep track of the DIVE_INDEX of all selected dives and simply re-select
those dives after changing model (date based sort or sort by other
column).

There are a few TODOs left. We lose the sort direction (ascending /
descending) when switching models. We also don't correctly deal with the
user selecting summary rows in the tree model.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
display-gtk.h
divelist.c
statistics.c

index 4ce05468c7ba7d673014f2202d43d33f4f62d1a5..3043c873b4ddacc95bdd78e5ce1212cc0a1622f7 100644 (file)
@@ -72,7 +72,7 @@ extern GtkWidget *dive_list_create(void);
 
 unsigned int amount_selected;
 
-extern void process_selected_dives(GList *, GtkTreeModel *);
+extern void process_selected_dives(GList *, int *, GtkTreeModel *);
 
 typedef void (*data_func_t)(GtkTreeViewColumn *col,
                            GtkCellRenderer *renderer,
index b70b415cae4a064ff52c47162fca0387ab087a09..4260651b7fd66eb72974fa7809c55028b391d620 100644 (file)
@@ -79,6 +79,7 @@ static void dump_model(GtkListStore *store)
 #endif
 
 static GList *selected_dives;
+static int *selectiontracker;
 
 static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
 {
@@ -92,6 +93,7 @@ static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
                g_list_free (selected_dives);
        }
        selected_dives = gtk_tree_selection_get_selected_rows(selection, NULL);
+       selectiontracker = realloc(selectiontracker, nr_selected * sizeof(int));
 
        switch (nr_selected) {
        case 0: /* keep showing the last selected dive */
@@ -118,6 +120,7 @@ static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
                                        gtk_tree_view_expand_row(GTK_TREE_VIEW(dive_list.tree_view), tpath, FALSE);
                                gtk_tree_model_get(GTK_TREE_MODEL(dive_list.model), &iter, DIVE_INDEX, &selected_dive, -1);
                        }
+                       selectiontracker[0] = selected_dive;
                        repaint_dive();
                }
                return;
@@ -127,8 +130,11 @@ static void selection_cb(GtkTreeSelection *selection, gpointer userdata)
                  * is the most intuitive solution.
                  * I do however want to keep around which dives have
                  * been selected */
+                /* TODO:
+                   this also does not handle the case if a summary row is selected;
+                   We should iterate and select all dives under that row */
                amount_selected = g_list_length(selected_dives);
-               process_selected_dives(selected_dives, GTK_TREE_MODEL(dive_list.model));
+               process_selected_dives(selected_dives, selectiontracker, GTK_TREE_MODEL(dive_list.model));
                repaint_dive();
                return;
        }
@@ -777,6 +783,8 @@ static void fill_dive_list(void)
                GtkTreeSelection *selection;
                selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
                gtk_tree_selection_select_iter(selection, &iter);
+               selectiontracker = realloc(selectiontracker, sizeof(int));
+               gtk_tree_model_get(GTK_TREE_MODEL(dive_list.model), &iter, DIVE_INDEX, selectiontracker, -1);
        }
 }
 
@@ -896,9 +904,37 @@ static gboolean button_press_cb(GtkWidget *treeview, GdkEventButton *event, gpoi
        return FALSE;
 }
 
+/* we need to have a temporary copy of the selected dives while
+   switching model as the selection_cb function keeps getting called
+   by when gtk_tree_selection_select_path is called. */
+static int *oldselection;
+static int old_nr_selected;
+
+/* Check if this dive was selected previously and select it again in the new model;
+ * This is used after we switch models to maintain consistent selections.
+ * We always return FALSE to iterate through all dives */
+static gboolean select_selected(GtkTreeModel *model, GtkTreePath *path,
+                               GtkTreeIter *iter, gpointer data)
+{
+       int i, idx;
+       GtkTreeSelection *selection = GTK_TREE_SELECTION(data);
+
+       gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
+       for (i = 0; i < old_nr_selected; i++)
+               if (oldselection[i] == idx) {
+                       gtk_tree_view_expand_to_path(GTK_TREE_VIEW(dive_list.tree_view), path);
+                       gtk_tree_selection_select_path(selection, path);
+
+                       return FALSE;
+               }
+       return FALSE;
+
+}
+
 /* If the sort column is date (default), show the tree model.
    For every other sort column only show the list model.
-   If the model changed, inform the new model of the chosen sort column. */
+   If the model changed, inform the new model of the chosen sort column and make
+   sure the same dives are still selected. */
 static void sort_column_change_cb(GtkTreeSortable *treeview, gpointer data)
 {
        int colid;
@@ -911,8 +947,23 @@ static void sort_column_change_cb(GtkTreeSortable *treeview, gpointer data)
        else
                dive_list.model = dive_list.listmodel;
        if (dive_list.model != currentmodel) {
+               /* TODO
+                  we should remember the sort order we had for each column */
+               GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dive_list.tree_view));
+
+               /* remember what is currently selected, switch models and reselect the selected rows */
+               old_nr_selected = amount_selected;
+               oldselection = malloc(old_nr_selected * sizeof(int));
+               memcpy(oldselection, selectiontracker, amount_selected * sizeof(int));
+
                gtk_tree_view_set_model(GTK_TREE_VIEW(dive_list.tree_view), GTK_TREE_MODEL(dive_list.model));
                gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dive_list.model), colid, order);
+
+               if (old_nr_selected) {
+                       /* we need to select all the dives that were selected */
+                       /* this is fundamentally an n^2 algorithm as implemented - YUCK */
+                       gtk_tree_model_foreach(GTK_TREE_MODEL(dive_list.model), select_selected, selection);
+               }
        }
 }
 
index 19105653c2aa1ad8014cfa095dd86bf524f940fc..adfc9c77ac4f471922178d01de73c6d122b742c6 100644 (file)
@@ -142,10 +142,11 @@ static void process_all_dives(struct dive *dive, struct dive **prev_dive)
        }
 }
 
-void process_selected_dives(GList *selected_dives, GtkTreeModel *model)
+void process_selected_dives(GList *selected_dives, int *selectiontracker, GtkTreeModel *model)
 {
        struct dive *dp;
        unsigned int i;
+       int idx;
        GtkTreeIter iter;
        GtkTreePath *path;
 
@@ -157,9 +158,13 @@ void process_selected_dives(GList *selected_dives, GtkTreeModel *model)
                path = g_list_nth_data(selected_dives, i);
                if (gtk_tree_model_get_iter(model, &iter, path)) {
                        gtk_tree_model_get_value(model, &iter, 0, &value);
-                       dp = get_dive(g_value_get_int(&value));
+                       idx = g_value_get_int(&value);
+                       dp = get_dive(idx);
+                       if (dp) {
+                               selectiontracker[i] = idx;
+                               process_dive(dp, &stats_selection);
+                       }
                }
-               process_dive(dp, &stats_selection);
        }
 }