[PATCH] When only a dive trip is selected, select all the dives in the trip

Linus Torvalds torvalds at linux-foundation.org
Mon Feb 18 15:43:18 PST 2013


From: Linus Torvalds <torvalds at linux-foundation.org>
Date: Mon, 18 Feb 2013 15:35:47 -0800
Subject: [PATCH] When only a dive trip is selected, select all the dives in the trip

This does a final pass after all the selection logic, and notices if we
have dive trips that are selected, but that have no dives in them
selected.  In that case, we assume that the user wanted to select all
dives in that trip.

NOTE! This still allows a range selection that selects the dive trip
entry and a few dives under the trip.  If a trip has any dives selected
in it, we leave that manual selection alone.  So this new logic really
only triggers on the case where somebody selected *just* the trip.

Note: unselecting the trip still leaves the dives under it selected,
because having a dive trip that isn't selected have all the dives under
it be selected is normal, and we can't recognize that as some kind of
special event.

Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
---

This gets you the expected behavior for almost all cases. But note the 
"user unselected just the dive trip entry". We really don't know whether 
the user meant to unselect all the dives under the trip or just the trip 
entry, and we have no really sane way to find out.

We could have more insane heuristics like "if the only change in selection 
was the dive trip, let's unselect all the dives under it too", but it 
really gets to be too crazy. I don't think it matters from a UX 
standpoint.

 dive.h     |  2 +-
 divelist.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/dive.h b/dive.h
index afccfe023aa0..cf3a735fcf07 100644
--- a/dive.h
+++ b/dive.h
@@ -299,7 +299,7 @@ typedef struct dive_trip {
 	struct dive *dives;
 	int nrdives;
 	int index;
-	unsigned expanded:1, selected:1, autogen:1;
+	unsigned expanded:1, selected:1, autogen:1, fixup:1;
 	struct dive_trip *next;
 } dive_trip_t;
 
diff --git a/divelist.c b/divelist.c
index b5fe48e5bee5..76cce83f5a94 100644
--- a/divelist.c
+++ b/divelist.c
@@ -2744,24 +2744,96 @@ static void entry_selected(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *
 		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))
+		if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(dive_list.tree_view), path)) {
+			trip->fixup = 1;
 			return;
+		}
+
 		/* Otherwise, consider each dive under it selected */
 		for_each_dive(i, dive) {
 			if (dive->divetrip == trip)
 				select_dive(i);
 		}
+		trip->fixup = 0;
 	} else {
 		select_dive(idx);
 	}
 }
 
+static void update_gtk_selection(GtkTreeSelection *selection, GtkTreeModel *model)
+{
+	GtkTreeIter iter;
+
+	if (!gtk_tree_model_get_iter_first(model, &iter))
+		return;
+	do {
+		GtkTreeIter child;
+
+		if (!gtk_tree_model_iter_children(model, &child, &iter))
+			continue;
+
+		do {
+			int idx;
+			struct dive *dive;
+			dive_trip_t *trip;
+
+			gtk_tree_model_get(model, &child, DIVE_INDEX, &idx, -1);
+			dive = get_dive(idx);
+			if (!dive || !dive->selected)
+				break;
+			trip = dive->divetrip;
+			if (!trip)
+				break;
+			gtk_tree_selection_select_iter(selection, &child);
+		} while (gtk_tree_model_iter_next(model, &child));
+	} while (gtk_tree_model_iter_next(model, &iter));
+}
+
 /* this is called when gtk thinks that the selection has changed */
 static void selection_cb(GtkTreeSelection *selection, GtkTreeModel *model)
 {
+	int i, fixup;
+	struct dive *dive;
+
 	gtk_tree_selection_selected_foreach(selection, entry_selected, model);
 
+	/*
+	 * Go through all the dives, if there is a trip that is selected but no
+	 * dives under it are selected, force-select all the dives
+	 */
+
+	/* First, clear "fixup" for any trip that has selected dives */
+	for_each_dive(i, dive) {
+		dive_trip_t *trip = dive->divetrip;
+		if (!trip || !trip->fixup)
+			continue;
+		if (dive->selected || !trip->selected)
+			trip->fixup = 0;
+	}
+
+	/*
+	 * Ok, not fixup is only set for trips that are selected
+	 * but have no selected dives in them. Select all dives
+	 * for such trips.
+	 */
+	fixup = 0;
+	for_each_dive(i, dive) {
+		dive_trip_t *trip = dive->divetrip;
+		if (!trip || !trip->fixup)
+			continue;
+		fixup = 1;
+		select_dive(i);
+	}
+
+	/*
+	 * Ok, we did a forced selection of dives, now we need to update the gtk
+	 * view of what is selected too..
+	 */
+	if (fixup)
+		update_gtk_selection(selection, model);
+
 #if DEBUG_SELECTION_TRACKING
 	dump_selection();
 #endif
-- 
1.8.1.3.556.gb3310b5



More information about the subsurface mailing list