diff options
-rw-r--r-- | display-gtk.h | 3 | ||||
-rw-r--r-- | dive.c | 61 | ||||
-rw-r--r-- | dive.h | 7 | ||||
-rw-r--r-- | divelist.c | 4 | ||||
-rw-r--r-- | gtk-gui.c | 27 | ||||
-rw-r--r-- | libdivecomputer.c | 3 | ||||
-rw-r--r-- | libdivecomputer.h | 1 | ||||
-rw-r--r-- | main.c | 11 | ||||
-rw-r--r-- | uemis-downloader.c | 8 |
9 files changed, 90 insertions, 35 deletions
diff --git a/display-gtk.h b/display-gtk.h index d709696a6..4f156c7f7 100644 --- a/display-gtk.h +++ b/display-gtk.h @@ -113,6 +113,7 @@ typedef gint (*sort_func_t)(GtkTreeModel *model, extern GtkTreeViewColumn *tree_view_column(GtkWidget *tree_view, int index, const char *title, data_func_t data_func, unsigned int flags); -GError *uemis_download(const char *path, char **divenr, char **xml_buffer, progressbar_t *progress); +GError *uemis_download(const char *path, char **divenr, char **xml_buffer, + progressbar_t *progress, gboolean force_download); #endif @@ -590,6 +590,9 @@ struct dive *fixup_dive(struct dive *dive) #define MERGE_TXT(res, a, b, n) res->n = merge_text(a->n, b->n) #define MERGE_NONZERO(res, a, b, n) res->n = a->n ? a->n : b->n +#define MERGE_MAX_PREFDL(res, dl, a, b, n) res->n = (dl && dl->n) ? dl->n : MAX(a->n, b->n) +#define MERGE_MIN_PREFDL(res, dl, a, b, n) res->n = (dl && dl->n) ? dl->n : (a->n)?(b->n)?MIN(a->n, b->n):(a->n):(b->n) + static struct dive *add_sample(struct sample *sample, int time, struct dive *dive) { struct sample *p = prepare_sample(&dive); @@ -684,6 +687,20 @@ add_sample_b: } } +static struct dive *copy_samples(struct dive *res, struct dive *src) +{ + int samples = src->samples; + struct sample *s = src->sample; + while (samples) { + if (!res) + return NULL; + res = add_sample(s, s->time.seconds, res); + s++; + samples--; + } + return fixup_dive(res); +} + static char *merge_text(const char *a, const char *b) { char *res; @@ -1027,9 +1044,9 @@ static int find_sample_offset(struct dive *a, struct dive *b) * 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, gboolean prefer_downloaded) { - int offset; + int offset = 0; /* * This assumes that the clocks on the dive computers are @@ -1037,19 +1054,26 @@ struct dive *try_to_merge(struct dive *a, struct dive *b) */ if ((a->when >= b->when + 60) || (a->when <= b->when - 60)) return NULL; - - /* Dive 'a' is 'offset' seconds before dive 'b' */ - offset = find_sample_offset(a, b); - if (offset > 120 || offset < -120) + if (prefer_downloaded && a->when != b->when) return NULL; - - return merge_dives(a, b, offset); + if (!prefer_downloaded) { + /* Dive 'a' is 'offset' seconds before dive 'b' */ + offset = find_sample_offset(a, b); + if (offset > 120 || offset < -120) + return NULL; + } + return merge_dives(a, b, offset, prefer_downloaded); } -struct dive *merge_dives(struct dive *a, struct dive *b, int offset) +struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean prefer_downloaded) { struct dive *res = alloc_dive(); + struct dive *dl = NULL; + if (a->downloaded) + dl = a; + else if (b->downloaded) + dl = b; res->when = a->when; res->selected = a->selected || b->selected; merge_trip(res, a, b); @@ -1062,16 +1086,21 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset) MERGE_MAX(res, a, b, rating); MERGE_TXT(res, a, b, suit); MERGE_MAX(res, a, b, number); - MERGE_MAX(res, a, b, maxdepth.mm); + MERGE_MAX_PREFDL(res, dl, a, b, maxdepth.mm); res->meandepth.mm = 0; MERGE_NONZERO(res, a, b, salinity); MERGE_NONZERO(res, a, b, visibility); MERGE_NONZERO(res, a, b, surface_pressure.mbar); - MERGE_MAX(res, a, b, duration.seconds); - MERGE_MAX(res, a, b, surfacetime.seconds); - MERGE_MAX(res, a, b, airtemp.mkelvin); - MERGE_MIN(res, a, b, watertemp.mkelvin); + MERGE_MAX_PREFDL(res, dl, a, b, duration.seconds); + MERGE_MAX_PREFDL(res, dl, a, b, surfacetime.seconds); + MERGE_MAX_PREFDL(res, dl, a, b, airtemp.mkelvin); + MERGE_MIN_PREFDL(res, dl, a, b, watertemp.mkelvin); merge_equipment(res, a, b); - merge_events(res, a, b, offset); - return merge_samples(res, a, b, offset); + if (dl) { + res->events = dl->events; + return copy_samples(res, dl); + } else { + merge_events(res, a, b, offset); + return merge_samples(res, a, b, offset); + } } @@ -261,6 +261,7 @@ struct dive { tripflag_t tripflag; dive_trip_t *divetrip; int selected; + gboolean downloaded; int start, end; timestamp_t when; char *location; @@ -414,10 +415,10 @@ extern void delete_dive(struct dive *dive); extern struct sample *prepare_sample(struct dive **divep); extern void finish_sample(struct dive *dive); -extern void report_dives(gboolean imported); +extern void report_dives(gboolean imported, gboolean prefer_imported); extern struct dive *fixup_dive(struct dive *dive); -extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset); -extern struct dive *try_to_merge(struct dive *a, struct dive *b); +extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean prefer_downloaded); +extern struct dive *try_to_merge(struct dive *a, struct dive *b, gboolean prefer_downloaded); extern void renumber_dives(int nr); diff --git a/divelist.c b/divelist.c index fd55dcd60..10c1ce4b3 100644 --- a/divelist.c +++ b/divelist.c @@ -1417,7 +1417,7 @@ void add_dive_cb(GtkWidget *menuitem, gpointer data) dive = alloc_dive(); if (add_new_dive(dive)) { record_dive(dive); - report_dives(TRUE); + report_dives(TRUE, FALSE); return; } free(dive); @@ -2088,7 +2088,7 @@ static void merge_dive_index(int i, struct dive *a) struct dive *b = get_dive(i+1); struct dive *res; - res = merge_dives(a, b, b->when - a->when); + res = merge_dives(a, b, b->when - a->when, FALSE); if (!res) return; @@ -43,6 +43,8 @@ static const char *default_dive_computer_vendor; static const char *default_dive_computer_product; static const char *default_dive_computer_device; static char *uemis_max_dive_data; +static gboolean force_download; +static gboolean prefer_downloaded; static int is_default_dive_computer(const char *vendor, const char *product) { @@ -350,7 +352,7 @@ static void file_open(GtkWidget *w, gpointer data) } g_free(filename); g_slist_free(fn_glist); - report_dives(FALSE); + report_dives(FALSE, FALSE); } gtk_widget_destroy(dialog); } @@ -510,6 +512,8 @@ OPTIONCALLBACK(autogroup_toggle, autogroup) OPTIONCALLBACK(po2_toggle, partial_pressure_graphs.po2) OPTIONCALLBACK(pn2_toggle, partial_pressure_graphs.pn2) OPTIONCALLBACK(phe_toggle, partial_pressure_graphs.phe) +OPTIONCALLBACK(force_toggle, force_download) +OPTIONCALLBACK(prefer_dl_toggle, prefer_downloaded) static void event_toggle(GtkWidget *w, gpointer _data) { @@ -1605,7 +1609,7 @@ void import_files(GtkWidget *w, gpointer data) filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(fs_dialog)); if (filenames) { g_slist_foreach(filenames, do_import_file, NULL); - report_dives(TRUE); + report_dives(TRUE, FALSE); g_slist_free(filenames); } } @@ -1619,7 +1623,7 @@ static GError *setup_uemis_import(device_data_t *data) GError *error = NULL; char *buf = NULL; - error = uemis_download(data->devname, &uemis_max_dive_data, &buf, &data->progress); + error = uemis_download(data->devname, &uemis_max_dive_data, &buf, &data->progress, data->force_download); if (buf && strlen(buf) > 1) { #ifdef DEBUGFILE fprintf(debugfile, "xml buffer \"%s\"\n\n", buf); @@ -1696,6 +1700,18 @@ void download_dialog(GtkWidget *w, gpointer data) devicedata.progress.bar = gtk_progress_bar_new(); gtk_container_add(GTK_CONTAINER(hbox), devicedata.progress.bar); + force_download = FALSE; + button = gtk_check_button_new_with_label(_("Force download of all dives")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); + gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(force_toggle), NULL); + + prefer_downloaded = FALSE; + button = gtk_check_button_new_with_label(_("Always prefer downloaded dive")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); + gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 6); + g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(prefer_dl_toggle), NULL); + button = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); if (!gtk_combo_box_get_active_iter(computer, &iter)) gtk_widget_set_sensitive(button, FALSE); @@ -1747,15 +1763,16 @@ repeat: while (*(--ne) == ' ' || *ne == '\t') *ne = '\0'; devicedata.devname = ns; + devicedata.force_download = force_download; info = import_dive_computer(&devicedata, GTK_DIALOG(dialog)); free((void *)devname); if (info) goto repeat; - report_dives(TRUE); + report_dives(TRUE, prefer_downloaded); break; default: /* it's possible that some dives were downloaded */ - report_dives(TRUE); + report_dives(TRUE, prefer_downloaded); break; } gtk_widget_destroy(dialog); diff --git a/libdivecomputer.c b/libdivecomputer.c index 6a9b07f80..f0c3c7549 100644 --- a/libdivecomputer.c +++ b/libdivecomputer.c @@ -311,9 +311,10 @@ static int dive_cb(const unsigned char *data, unsigned int size, dc_parser_destroy(parser); /* If we already saw this dive, abort. */ - if (find_dive(dive, devdata)) + if (!devdata->force_download && find_dive(dive, devdata)) return 0; + dive->downloaded = TRUE; record_dive(dive); return 1; } diff --git a/libdivecomputer.h b/libdivecomputer.h index 6430c8448..7497abf11 100644 --- a/libdivecomputer.h +++ b/libdivecomputer.h @@ -17,6 +17,7 @@ typedef struct device_data_t { dc_context_t *context; progressbar_t progress; int preexisting; + gboolean force_download; } device_data_t; extern GError *do_import(device_data_t *data); @@ -111,7 +111,7 @@ static gboolean imported = FALSE; * This doesn't really report anything at all. We just sort the * dives, the GUI does the reporting */ -void report_dives(gboolean is_imported) +void report_dives(gboolean is_imported, gboolean prefer_imported) { int i; int preexisting = dive_table.preexisting; @@ -131,7 +131,7 @@ void report_dives(gboolean is_imported) if (prev->when + prev->duration.seconds < dive->when) continue; - merged = try_to_merge(prev, dive); + merged = try_to_merge(prev, dive, prefer_imported); if (!merged) continue; @@ -145,6 +145,9 @@ void report_dives(gboolean is_imported) delete_single_dive(i+1); delete_single_dive(i+1); } + /* make sure no dives are still marked as downloaded */ + for (i = 1; i < dive_table.nr; i++) + dive_table.dives[i]->downloaded = FALSE; if (is_imported) { /* Was the previous dive table state numbered? */ @@ -173,7 +176,7 @@ static void parse_argument(const char *arg) if (strcmp(arg,"--import") == 0) { /* mark the dives so far as the base, * everything after is imported */ - report_dives(FALSE); + report_dives(FALSE, FALSE); imported = TRUE; return; } @@ -276,7 +279,7 @@ int main(int argc, char **argv) set_filename(filename, FALSE); free((void *)filename); } - report_dives(imported); + report_dives(imported, FALSE); if (dive_table.nr == 0) show_dive_info(NULL); run_ui(); diff --git a/uemis-downloader.c b/uemis-downloader.c index 6f85eca59..922aa90ae 100644 --- a/uemis-downloader.c +++ b/uemis-downloader.c @@ -44,6 +44,7 @@ struct argument_block { char **max_dive_data; char **xml_buffer; progressbar_t *progress; + gboolean force_download; }; static int import_thread_done = 0, import_thread_cancelled; @@ -796,7 +797,7 @@ static char *do_uemis_download(struct argument_block *args) * certainly want to start downloading from the first dive on * the Uemis; otherwise check which was the last dive * downloaded */ - if (dive_table.nr > 0) + if (!args->force_download && dive_table.nr > 0) newmax = get_divenr(*max_dive_data, deviceid); else newmax = strdup("0"); @@ -874,11 +875,12 @@ static void *pthread_wrapper(void *_data) return (void *)err_string; } -GError *uemis_download(const char *mountpath, char **max_dive_data, char **xml_buffer, progressbar_t *progress) +GError *uemis_download(const char *mountpath, char **max_dive_data, char **xml_buffer, progressbar_t *progress, + gboolean force_download) { pthread_t pthread; void *retval; - struct argument_block args = {mountpath, max_dive_data, xml_buffer, progress}; + struct argument_block args = {mountpath, max_dive_data, xml_buffer, progress, force_download}; /* I'm sure there is some better interface for waiting on a thread in a UI main loop */ import_thread_done = 0; |