From: Dirk Hohndel Date: Mon, 13 Aug 2012 21:53:07 +0000 (-0700) Subject: Maintain selected rows when switching between list model and tree model X-Git-Url: http://git.tdb.fi/?p=ext%2Fsubsurface.git;a=commitdiff_plain;h=dc9d0e23e5d158ea4775021b2f629e7f90b5377c Maintain selected rows when switching between list model and tree model 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 --- diff --git a/display-gtk.h b/display-gtk.h index 4ce0546..3043c87 100644 --- a/display-gtk.h +++ b/display-gtk.h @@ -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, diff --git a/divelist.c b/divelist.c index b70b415..4260651 100644 --- a/divelist.c +++ b/divelist.c @@ -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); + } } } diff --git a/statistics.c b/statistics.c index 1910565..adfc9c7 100644 --- a/statistics.c +++ b/statistics.c @@ -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); } }