Improve on the "prefer downloaded" dive computer model

It used to be that when you checked the "Prefer downloaded" checkmark,
we'd throw away *any* old dive computer data.  That was good, because it
allowed us to start from a clean slate when you had some old subsurface
data with questionable dive computer data.

However, it was a bit extreme, and it's really not what you want if you
already have (good) dive computer data from other dive computers.

So this modifies the logic a bit.  Instead of throwing away all old dive
computer data, the "Prefer downloaded" checkmark now means:

 - the newly downloaded data becomes the "primary" dive computer data
   (ie the first in the list)

 - if there was old dive computer data that *could* have been from this
   new dive computer (ie it didn't have model information, or it had a
   matching model but no device ID data), we throw that away

 - but any existing dive computer data from other dive computers is left.

This seems to be much closer to what we really would want for a new
"preferred" download.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Linus Torvalds 2013-01-22 16:57:07 -08:00 committed by Dirk Hohndel
parent 20ad07d4ac
commit acd6dff4a8

60
dive.c
View file

@ -1323,7 +1323,24 @@ static int same_dc(struct divecomputer *a, struct divecomputer *b)
return eva == evb;
}
static void remove_redundant_dc(struct divecomputer *dc)
static int might_be_same_device(struct divecomputer *a, struct divecomputer *b)
{
/* No dive computer model? That matches anything */
if (!a->model || !b->model)
return 1;
/* Otherwise at least the model names have to match */
if (strcasecmp(a->model, b->model))
return 0;
/* No device ID? Match */
if (!a->deviceid || !b->deviceid)
return 1;
return a->deviceid == b->deviceid;
}
static void remove_redundant_dc(struct divecomputer *dc, int prefer_downloaded)
{
do {
struct divecomputer **p = &dc->next;
@ -1331,7 +1348,7 @@ static void remove_redundant_dc(struct divecomputer *dc)
/* Check this dc against all the following ones.. */
while (*p) {
struct divecomputer *check = *p;
if (same_dc(dc, check)) {
if (same_dc(dc, check) || (prefer_downloaded && might_be_same_device(dc, check))) {
*p = check->next;
check->next = NULL;
free_dc(check);
@ -1340,7 +1357,8 @@ static void remove_redundant_dc(struct divecomputer *dc)
p = &check->next;
}
/* .. and then continue down the chain */
/* .. and then continue down the chain, but we */
prefer_downloaded = 0;
dc = dc->next;
} while (dc);
}
@ -1357,19 +1375,7 @@ static struct divecomputer *find_matching_computer(struct divecomputer *match, s
while ((p = list) != NULL) {
list = list->next;
/* No dive computer model? That matches anything */
if (!match->model || !p->model)
break;
/* Otherwise at least the model names have to match */
if (strcasecmp(match->model, p->model))
continue;
/* No device ID? Match */
if (!match->deviceid || !p->deviceid)
break;
if (match->deviceid == p->deviceid)
if (might_be_same_device(match, p))
break;
}
return p;
@ -1422,9 +1428,13 @@ static void interleave_dive_computers(struct divecomputer *res,
* name etc), we will prefer a new-style one and just throw
* away the old. We're assuming it's a re-download.
*
* Otherwise, we'll just try to keep all the information.
* Otherwise, we'll just try to keep all the information,
* unless the user has specified that they prefer the
* downloaded computer, in which case we'll aggressively
* try to throw out old information that *might* be from
* that one.
*/
static void join_dive_computers(struct divecomputer *res, struct divecomputer *a, struct divecomputer *b)
static void join_dive_computers(struct divecomputer *res, struct divecomputer *a, struct divecomputer *b, int prefer_downloaded)
{
struct divecomputer *tmp;
@ -1449,7 +1459,7 @@ static void join_dive_computers(struct divecomputer *res, struct divecomputer *a
*tmp->next = *b;
clear_dc(b);
remove_redundant_dc(res);
remove_redundant_dc(res, prefer_downloaded);
}
struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean prefer_downloaded)
@ -1490,18 +1500,12 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean pr
MERGE_MIN_PREFDL(res, dl, a, b, watertemp.mkelvin);
merge_equipment(res, a, b);
if (dl) {
res->dc = dl->dc;
/*
* Since we copied the events and samples,
* we can't free them from the source when
* we free it - so make sure the source
* dive computer data is cleared out.
*/
clear_dc(&dl->dc);
/* If we prefer downloaded, do those first, and get rid of "might be same" computers */
join_dive_computers(&res->dc, &dl->dc, &a->dc, 1);
} else if (offset)
interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset);
else
join_dive_computers(&res->dc, &a->dc, &b->dc);
join_dive_computers(&res->dc, &a->dc, &b->dc, 0);
fixup_dive(res);
return res;