summaryrefslogtreecommitdiffstats
path: root/divelist.c
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2013-01-30 06:15:23 +1100
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-01-30 06:47:48 +1100
commit4b5b732f2cf8a63445a610642285304526850c91 (patch)
tree840075b04b0fec75863a1f02a48557fabf88464b /divelist.c
parent14524d8e1dcb60b58ddbd117d19298b19255d1f3 (diff)
downloadsubsurface-4b5b732f2cf8a63445a610642285304526850c91.tar.gz
Don't deselect all dives on all selection "change" events
gtk sends the selection change events all the time, for pretty much any "divelist changed - so selection changed". The expansion of a trip, the switch to a new model, yadda yadda. But we actually want selections to be sticky across these events, so we can't just forget all of our old selection state and repopulate it. So we re-introduce the "am I allowed to change this row" callback, which we used to use to create a list of every actual selection that was changed. But instead of remembering the list (and having the stale entries issue with that remembered list that caused problems), we now just use that as a "that *particular* selection cleared" event. So this callback works as the "which part of the visible, currently selected state got cleared" notifier, and handles unselection. Then, when the selection is over, we use the new model of "let's just traverse the list of things gtk thinks are selected" and use that to handle new selections in the visible state that gtk actually tracks well. So that logic handles the new selections. This way, dives that aren't visible to gtk don't ever get modified: gtk won't ask about them being selected or not, and gtk won't track them in its selection logic, so with this model their state never changes for us. gtk selections are annoying. They are simple for the case gtk knows about (ie they are *visually* selected in the GUI), but since we very much want to track selection across events that change the visual state, we need to have this insane "impedance match". Reported-by: Dirk Hohdnel <dirk@hohndel.org> 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.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/divelist.c b/divelist.c
index 440c88922..e023dcd6c 100644
--- a/divelist.c
+++ b/divelist.c
@@ -2605,6 +2605,38 @@ static void select_dive(int idx)
}
}
+static void deselect_dive(int idx)
+{
+ struct dive *dive = get_dive(idx);
+ if (dive && dive->selected) {
+ dive->selected = 0;
+ amount_selected--;
+ if (selected_dive > idx)
+ selected_dive--;
+ }
+}
+
+gboolean modify_selection_cb(GtkTreeSelection *selection, GtkTreeModel *model,
+ GtkTreePath *path, gboolean was_selected, gpointer userdata)
+{
+ int idx;
+ timestamp_t when;
+ GtkTreeIter iter;
+
+ if (!was_selected)
+ return TRUE;
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, DIVE_INDEX, &idx, DIVE_DATE, &when, -1);
+ if (idx < 0) {
+ dive_trip_t *trip = find_trip_by_time(when);
+ if (trip)
+ trip->selected = 0;
+ } else {
+ deselect_dive(idx);
+ }
+ return TRUE;
+}
+
/* This gets called for each selected entry after a selection has changed */
static void entry_selected(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
@@ -2636,13 +2668,6 @@ static void entry_selected(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *
/* 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
@@ -2740,6 +2765,8 @@ 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);