diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-28 22:22:31 -0800 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-01-28 22:36:28 -0800 |
commit | 8d6dd5f87d38fa25769e900028781fa1e851ebc5 (patch) | |
tree | db938b0c5807f82e3b4d204b18ad332a41155741 /divelist.c | |
parent | da62919ae143d2b9dcaa9b1bc093a8c48ff647f7 (diff) | |
download | subsurface-8d6dd5f87d38fa25769e900028781fa1e851ebc5.tar.gz |
Rewrite gtk dive selection tracking logic
We used to generate a list of possibly changed selections using the gtk
tree selection "selection function".
But that's actually meant to just tell gtk whether an entry can be
selected or not, and our list of possibly changed entries ended up being
stale if the selection change was due to a list entry removal, for
example.
So rip out the old model entirely, and instead just walk the whole
selection that gtk gives us on a selection "change" event. We throw all
our old selections away when this happens, and just rebuild it all.
This should fix the occasional internal gtklib-quartz assertion that
Henrik is seeing. And it actually simplifies the code too.
Reported-by: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'divelist.c')
-rw-r--r-- | divelist.c | 170 |
1 files changed, 56 insertions, 114 deletions
diff --git a/divelist.c b/divelist.c index 82ef339d8..b31c9ac25 100644 --- a/divelist.c +++ b/divelist.c @@ -217,118 +217,6 @@ void row_collapsed_cb(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *pa gtk_tree_selection_select_iter(selection, iter); } -static GList *selection_changed = NULL; - -/* - * This is called _before_ the selection is changed, for every single entry; - * - * We simply create a list of all changed entries, and make sure that the - * group entries go at the end of the list. - */ -gboolean modify_selection_cb(GtkTreeSelection *selection, GtkTreeModel *model, - GtkTreePath *path, gboolean was_selected, gpointer userdata) -{ - GtkTreeIter iter, *p; - - if (!gtk_tree_model_get_iter(model, &iter, path)) - return TRUE; - - /* Add the group entries to the end */ - p = gtk_tree_iter_copy(&iter); - if (gtk_tree_model_iter_has_child(model, p)) - selection_changed = g_list_append(selection_changed, p); - else - selection_changed = g_list_prepend(selection_changed, p); - return TRUE; -} - -static void select_dive(struct dive *dive, int selected) -{ - if (dive->selected != selected) { - amount_selected += selected ? 1 : -1; - dive->selected = selected; - } -} - -/* - * This gets called when a dive group has changed selection. - */ -static void select_dive_group(GtkTreeModel *model, GtkTreeSelection *selection, GtkTreeIter *iter, int selected) -{ - int first = 1; - GtkTreeIter child; - - if (selected == selected_children(model, iter)) - return; - - if (!gtk_tree_model_iter_children(model, &child, iter)) - return; - - do { - int idx; - struct dive *dive; - - gtk_tree_model_get(model, &child, DIVE_INDEX, &idx, -1); - if (first && selected) - selected_dive = idx; - first = 0; - dive = get_dive(idx); - if (dive->selected == selected) - continue; - - select_dive(dive, selected); - if (selected) - gtk_tree_selection_select_iter(selection, &child); - else - gtk_tree_selection_unselect_iter(selection, &child); - } while (gtk_tree_model_iter_next(model, &child)); -} - -/* - * This gets called _after_ the selections have changed, for each entry that - * may have changed. Check if the gtk selection state matches our internal - * selection state to verify. - * - * The group entries are at the end, this guarantees that we have handled - * all the dives before we handle groups. - */ -static void check_selection_cb(GtkTreeIter *iter, GtkTreeSelection *selection) -{ - GtkTreeModel *model = MODEL(dive_list); - struct dive *dive; - int idx, gtk_selected; - - gtk_tree_model_get(model, iter, - DIVE_INDEX, &idx, - -1); - dive = get_dive(idx); - gtk_selected = gtk_tree_selection_iter_is_selected(selection, iter); - if (idx < 0) - select_dive_group(model, selection, iter, gtk_selected); - else { - select_dive(dive, gtk_selected); - if (gtk_selected) - selected_dive = idx; - } - gtk_tree_iter_free(iter); -} - -/* this is called when gtk thinks that the selection has changed */ -static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model) -{ - GList *changed = selection_changed; - - selection_changed = NULL; - g_list_foreach(changed, (GFunc) check_selection_cb, selection); - g_list_free(changed); -#if DEBUG_SELECTION_TRACKING - dump_selection(); -#endif - - process_selected_dives(); - repaint_dive(); -} - const char *star_strings[] = { ZERO_STARS, ONE_STARS, @@ -2707,6 +2595,62 @@ static void sort_column_change_cb(GtkTreeSortable *treeview, gpointer data) } } +static void select_dive(struct dive *dive) +{ + if (dive && !dive->selected) { + dive->selected = 1; + amount_selected++; + } +} + +/* This gets called for each selected entry after a selection has changed */ +static void entry_selected(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) +{ + int idx; + timestamp_t when; + + gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DATE, &when, -1); + if (idx < 0) { + int i; + struct dive *dive; + dive_trip_t *trip = find_trip_by_time(when); + + if (!trip) + return; + trip->selected = 1; + /* If this is expanded, let the gtk selection happen for each dive under it */ + if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), path)) + return; + /* Otherwise, consider each dive under it selected */ + for_each_dive(i, dive) { + if (dive->divetrip == trip) + select_dive(dive); + } + } else { + select_dive(get_dive(idx)); + } +} + +/* this is called when gtk thinks that the selection has changed */ +static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model) +{ + int i; + struct dive *dive; + + amount_selected = 0; + for_each_dive(i, dive) + dive->selected = 0; + + gtk_tree_selection_selected_foreach(selection, entry_selected, model); + +#if DEBUG_SELECTION_TRACKING + dump_selection(); +#endif + + process_selected_dives(); + repaint_dive(); +} + GtkWidget *dive_list_create(void) { GtkTreeSelection *selection; @@ -2794,8 +2738,6 @@ GtkWidget *dive_list_create(void) g_signal_connect(dive_list.listmodel, "sort-column-changed", G_CALLBACK(sort_column_change_cb), NULL); g_signal_connect(dive_list.treemodel, "sort-column-changed", G_CALLBACK(sort_column_change_cb), NULL); - gtk_tree_selection_set_select_function(selection, modify_selection_cb, NULL, NULL); - dive_list.container_widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dive_list.container_widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); |