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; 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 { do {
struct divecomputer **p = &dc->next; 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.. */ /* Check this dc against all the following ones.. */
while (*p) { while (*p) {
struct divecomputer *check = *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; *p = check->next;
check->next = NULL; check->next = NULL;
free_dc(check); free_dc(check);
@ -1340,7 +1357,8 @@ static void remove_redundant_dc(struct divecomputer *dc)
p = &check->next; p = &check->next;
} }
/* .. and then continue down the chain */ /* .. and then continue down the chain, but we */
prefer_downloaded = 0;
dc = dc->next; dc = dc->next;
} while (dc); } while (dc);
} }
@ -1357,19 +1375,7 @@ static struct divecomputer *find_matching_computer(struct divecomputer *match, s
while ((p = list) != NULL) { while ((p = list) != NULL) {
list = list->next; list = list->next;
/* No dive computer model? That matches anything */ if (might_be_same_device(match, p))
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)
break; break;
} }
return p; 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 * name etc), we will prefer a new-style one and just throw
* away the old. We're assuming it's a re-download. * 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; struct divecomputer *tmp;
@ -1449,7 +1459,7 @@ static void join_dive_computers(struct divecomputer *res, struct divecomputer *a
*tmp->next = *b; *tmp->next = *b;
clear_dc(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) 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_MIN_PREFDL(res, dl, a, b, watertemp.mkelvin);
merge_equipment(res, a, b); merge_equipment(res, a, b);
if (dl) { if (dl) {
res->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);
* 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);
} else if (offset) } else if (offset)
interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset); interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset);
else else
join_dive_computers(&res->dc, &a->dc, &b->dc); join_dive_computers(&res->dc, &a->dc, &b->dc, 0);
fixup_dive(res); fixup_dive(res);
return res; return res;