Handle new dives correctly if trips exist

There is an interesting issue when adding new dives into a dive list with
existing trips. Since fill_dive_list walks the list backwards and trips
are determined by the timestamp of the first dive in a trip, it is
non-trivial to know when a dive is added if it should be part of an
existing trip or not. Let's say when we see the dive we can also see a
trip entry that starts four days earlier. Without looking forward in the
list of dives we cannot tell if this is a multi-day trip that this dive
would fit into, or if there is a break of more than tree days (our current
trip threshold).

Instead this commit adds a second scan of the dives in chronological order
that does the right thing for new dives.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2012-09-07 10:12:31 -07:00
parent 6ddf0e1d22
commit b49b081bb9
2 changed files with 73 additions and 0 deletions

1
dive.h
View file

@ -271,6 +271,7 @@ extern gboolean autogroup;
#define UNGROUPED_DIVE(_dive) ((_dive)->tripflag == NO_TRIP)
#define DIVE_IN_TRIP(_dive) ((_dive)->tripflag == IN_TRIP)
#define DIVE_NEEDS_TRIP(_dive) ((_dive)->tripflag == TF_NONE)
#define NEXT_TRIP(_entry) ((_entry) ? g_list_next(_entry) : (dive_trip_list))
#define PREV_TRIP(_entry) ((_entry) ? g_list_previous(_entry) : g_list_last(dive_trip_list))
#define DIVE_TRIP(_trip) ((struct dive *)(_trip)->data)

View file

@ -65,6 +65,9 @@ enum {
DIVELIST_COLUMNS
};
static void turn_dive_into_trip(GtkTreePath *path);
static void merge_dive_into_trip_above_cb(GtkWidget *menuitem, GtkTreePath *path);
#ifdef DEBUG_MODEL
static gboolean dump_model_entry(GtkTreeModel *model, GtkTreePath *path,
GtkTreeIter *iter, gpointer data)
@ -136,6 +139,28 @@ static void first_leaf(GtkTreeModel *model, GtkTreeIter *iter, int *diveidx)
}
}
static GtkTreePath *path_match;
static gboolean match_dive(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
int idx;
struct dive *dive = data;
gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, -1);
if (idx >= 0)
if (get_dive(idx)->when == dive->when) {
path_match = gtk_tree_path_copy(path);
return TRUE;
}
return FALSE;
}
static GtkTreePath *get_path_from(struct dive *dive)
{
gtk_tree_model_foreach(TREEMODEL(dive_list), match_dive, dive);
return path_match;
}
/* make sure that if we expand a summary row that is selected, the children show
up as selected, too */
void row_expanded_cb(GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path, gpointer data)
@ -935,6 +960,7 @@ static void fill_dive_list(void)
struct dive *last_trip = NULL;
GList *trip;
struct dive *dive_trip = NULL;
gboolean need_scan = FALSE;
/* if we have pre-existing trips, start on the last one */
trip = g_list_last(dive_trip_list);
@ -981,6 +1007,15 @@ static void fill_dive_list(void)
dive_trip = NULL;
parent_ptr = NULL;
}
/* if we have an new dive and the dive_trip date is earlier than the
* dive then this is an existing trip and a new dive; as we are walking the
* dive_list oldest first it's very hard right now to know if this dive
* should be in that trip; so postpone this decision until the 'forward'
* scan at the end of this function */
if (DIVE_NEEDS_TRIP(dive) && dive_trip && dive_trip->when < dive->when) {
dive_trip = NULL;
need_scan = TRUE;
}
/* update dive as part of dive_trip and
* (if necessary) update dive_trip time and location */
if (dive_trip) {
@ -1041,6 +1076,43 @@ static void fill_dive_list(void)
DIVE_DATE, dive_trip->when,
DIVE_LOCATION, dive_trip->location,
-1);
/* now walk the dive list one more time to make sure any new
* dives that fit into an existing dive_trip have been added
* to the matching trips */
if (autogroup && need_scan) {
struct dive *dive;
time_t last_trip_dive_when;
GtkTreePath *path;
trip = dive_trip_list;
last_trip_dive_when = DIVE_TRIP(trip)->when;
for (i = 0; i < dive_table.nr; i++) {
dive = get_dive(i);
if (UNGROUPED_DIVE(dive)) {
/* this ends any trip */
trip = NULL;
last_trip_dive_when = 0;
} else if (DIVE_IN_TRIP(dive)) {
trip = find_matching_trip(dive->when);
if (dive->when > last_trip_dive_when)
last_trip_dive_when = dive->when;
} else { /* DIVE_NEEDS_TRIP */
if (dive->when - last_trip_dive_when < TRIP_THRESHOLD) {
/* dive should be in this trip */
dive->tripflag = IN_TRIP;
dive->divetrip = DIVE_TRIP(trip);
/* now move the tree node into place */
path = get_path_from(dive);
merge_dive_into_trip_above_cb(NULL, path);
} else {
/* we did need a new trip for this dive */
path = get_path_from(dive);
turn_dive_into_trip(path);
}
}
}
}
update_dive_list_units();
if (gtk_tree_model_get_iter_first(MODEL(dive_list), &iter)) {
GtkTreeSelection *selection;