diff options
-rw-r--r-- | dive.c | 94 | ||||
-rw-r--r-- | dive.h | 5 | ||||
-rw-r--r-- | divelist.c | 20 | ||||
-rw-r--r-- | main.c | 6 |
4 files changed, 106 insertions, 19 deletions
@@ -713,11 +713,94 @@ static void merge_equipment(struct dive *res, struct dive *a, struct dive *b) } /* + * When merging two dives, this picks the trip from one, and removes it + * from the other. + * + * The 'next' dive is not involved in the dive merging, but is the dive + * that will be the next dive after the merged dive. + */ +static void pick_and_delete_trip(struct dive *res, struct dive *pick, struct dive *remove, struct dive *next) +{ + tripflag_t tripflag = pick->tripflag; + dive_trip_t *trip = pick->divetrip; + + res->tripflag = tripflag; + res->divetrip = trip; + + /* + * We may have to change the trip date if we picked an earlier + * date for the dive that now uses it. + */ + if (res->when < trip->when) + trip->when = res->when; + + /* Was it the same trip as the removed dive? All good*/ + if (trip == remove->divetrip) + return; + + /* Ok, we're dropping a dive. We may need to fix up the date on it */ + trip = remove->divetrip; + if (trip->when != remove->when) + return; + + if (next && next->divetrip == trip) { + trip->when = next->when; + return; + } + + delete_trip(trip); +} + +/* + * Pick a trip for a dive + */ +static void merge_trip(struct dive *res, struct dive *a, struct dive *b, struct dive *next) +{ + /* + * The larger tripflag is more relevant: we prefer + * take manually assigned trips over auto-generated + * ones. + */ + if (a->tripflag > b->tripflag) + goto pick_a; + + if (a->tripflag < b->tripflag) + goto pick_b; + + /* + * Ok, so the divetrips are equally "important". + * Pick the one with the better description. + */ + if (!a->location) + goto pick_b; + if (!b->location) + goto pick_a; + if (!a->notes) + goto pick_b; + if (!b->notes) + goto pick_a; + + /* + * Ok, so both have location and notes. + * Pick the earlier one. + */ + if (a->when < b->when) + goto pick_a; + goto pick_b; + +pick_a: + pick_and_delete_trip(res, a, b, next); + return; +pick_b: + pick_and_delete_trip(res, b, a, next); +} + +/* * This could do a lot more merging. Right now it really only * merges almost exact duplicates - something that happens easily * with overlapping dive downloads. */ -struct dive *try_to_merge(struct dive *a, struct dive *b) +struct dive *try_to_merge(struct dive *a, struct dive *b, struct dive *next) { struct dive *res; @@ -727,14 +810,7 @@ struct dive *try_to_merge(struct dive *a, struct dive *b) res = alloc_dive(); res->when = a->when; - /* the larger tripflag is more relevant */ - if(a->tripflag > b->tripflag) { - res->tripflag = a->tripflag; - res->divetrip = a->divetrip; - } else { - res->tripflag = b->tripflag; - res->divetrip = b->divetrip; - } + merge_trip(res, a, b, next); MERGE_NONZERO(res, a, b, latitude); MERGE_NONZERO(res, a, b, longitude); MERGE_TXT(res, a, b, location); @@ -242,7 +242,7 @@ struct event { #define W_IDX_SECONDARY 1 typedef gint64 timestamp_t; -typedef enum { TF_NONE, NO_TRIP, IN_TRIP, ASSIGNED_TRIP, AUTOGEN_TRIP, NUM_TRIPFLAGS } tripflag_t; +typedef enum { TF_NONE, NO_TRIP, IN_TRIP, AUTOGEN_TRIP, ASSIGNED_TRIP, NUM_TRIPFLAGS } tripflag_t; extern const char *tripflag_names[NUM_TRIPFLAGS]; typedef struct dive_trip { @@ -298,6 +298,7 @@ extern gboolean autogroup; #define DIVE_FITS_TRIP(_dive, _dive_trip) ((_dive_trip)->when - TRIP_THRESHOLD <= (_dive)->when) extern void insert_trip(dive_trip_t **trip); +extern void delete_trip(dive_trip_t *trip); /* * We keep our internal data in well-specified units, but @@ -390,7 +391,7 @@ extern void finish_sample(struct dive *dive); extern void report_dives(gboolean imported); extern struct dive *fixup_dive(struct dive *dive); -extern struct dive *try_to_merge(struct dive *a, struct dive *b); +extern struct dive *try_to_merge(struct dive *a, struct dive *b, struct dive *next); extern void renumber_dives(int nr); diff --git a/divelist.c b/divelist.c index 498210e1f..8819f4ab1 100644 --- a/divelist.c +++ b/divelist.c @@ -1025,7 +1025,7 @@ void insert_trip(dive_trip_t **dive_trip_p) #endif } -static inline void delete_trip(GList *trip) +static inline void delete_trip_list_entry(GList *trip) { dive_trip_t *dive_trip = (dive_trip_t *)g_list_nth_data(trip, 0); if (dive_trip->location) @@ -1035,6 +1035,12 @@ static inline void delete_trip(GList *trip) dump_trip_list(); #endif } + +void delete_trip(dive_trip_t *trip) +{ + delete_trip_list_entry(find_trip(trip->when)); +} + static dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive) { dive_trip_t *dive_trip = calloc(sizeof(dive_trip_t),1); @@ -1693,7 +1699,7 @@ static void remove_from_trip(GtkTreePath *path) /* if this was the last dive on the trip, remove the trip */ if (! gtk_tree_model_iter_has_child(MODEL(dive_list), &parent)) { gtk_tree_store_remove(STORE(dive_list), &parent); - delete_trip(find_trip(dive->divetrip->when)); + delete_trip(dive->divetrip); free(dive->divetrip); } /* mark the dive as intentionally at the top level */ @@ -1803,7 +1809,7 @@ void remove_trip(GtkTreePath *trippath, gboolean force_no_trip) } /* finally, remove the trip */ gtk_tree_store_remove(STORE(dive_list), &parent); - delete_trip(find_trip(dive_trip->when)); + delete_trip(dive_trip); free(dive_trip); #ifdef DEBUG_TRIP dump_trip_list(); @@ -1858,7 +1864,7 @@ void merge_trips_cb(GtkWidget *menuitem, GtkTreePath *trippath) } update_trip_timestamp(&prevtripiter, DIVE_TRIP(prevtrip)); free(DIVE_TRIP(trip)); - delete_trip(trip); + delete_trip_list_entry(trip); gtk_tree_store_remove(STORE(dive_list), &thistripiter); mark_divelist_changed(TRUE); } @@ -1975,7 +1981,7 @@ static void delete_selected_dives_cb(GtkWidget *menuitem, GtkTreePath *path) if (dive->divetrip == divetrip_to_update) divetrip_to_update->when = dive->when; else - delete_trip(find_trip(divetrip_to_update->when)); + delete_trip(divetrip_to_update); } continue; } @@ -1984,7 +1990,7 @@ static void delete_selected_dives_cb(GtkWidget *menuitem, GtkTreePath *path) * that needs to be updated, check if this dive is still in that trip; * if not, delete the trip */ if (divetrip_needs_update && dive->divetrip != divetrip_to_update) { - delete_trip(find_trip(divetrip_to_update->when)); + delete_trip(divetrip_to_update); divetrip_needs_update = FALSE; } /* if this dive is part of a divetrip and is the first dive that @@ -2044,7 +2050,7 @@ static void delete_dive_cb(GtkWidget *menuitem, GtkTreePath *path) if (dive->divetrip && dive->when == dive->divetrip->when) { struct dive *next_dive = get_dive(idx + 1); if (!next_dive || next_dive->divetrip != dive->divetrip) - delete_trip(find_trip(dive->when)); + delete_trip(dive->divetrip); else next_dive->divetrip->when = next_dive->when; } @@ -126,12 +126,16 @@ void report_dives(gboolean is_imported) struct dive **pp = &dive_table.dives[i-1]; struct dive *prev = pp[0]; struct dive *dive = pp[1]; + struct dive *next; struct dive *merged; if (prev->when + prev->duration.seconds < dive->when) continue; - merged = try_to_merge(prev, dive); + next = NULL; + if (i < dive_table.nr-1) + next = pp[2]; + merged = try_to_merge(prev, dive, next); if (!merged) continue; |