From 9edb7811ef3366cf5ee378a07adb7121fab8630a Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 11 Feb 2015 10:33:36 -0800 Subject: Remove redundant function We had two functions doing exactly the same thing. Let's drop the one with the highly confusing name. Signed-off-by: Dirk Hohndel --- dive.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'dive.h') diff --git a/dive.h b/dive.h index b350527a7..a5d0e8712 100644 --- a/dive.h +++ b/dive.h @@ -494,13 +494,6 @@ extern unsigned int dc_number; #define current_dive (get_dive(selected_dive)) #define current_dc (get_dive_dc(current_dive, dc_number)) -static inline struct dive *get_gps_location(int nr, struct dive_table *table) -{ - if (nr >= table->nr || nr < 0) - return NULL; - return table->dives[nr]; -} - static inline struct dive *get_dive(int nr) { if (nr >= dive_table.nr || nr < 0) -- cgit v1.2.3-70-g09d2 From dcfda29da6d5539c602935f3518749942dad2153 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 11 Feb 2015 11:22:00 -0800 Subject: Add dive site data structure This leaves location and gps coordinates in the struct dive to allow a step by step migration. Signed-off-by: Dirk Hohndel --- dive.h | 1 + divesite.c | 2 ++ divesite.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ subsurface.pro | 2 ++ 4 files changed, 52 insertions(+) create mode 100644 divesite.c create mode 100644 divesite.h (limited to 'dive.h') diff --git a/dive.h b/dive.h index a5d0e8712..2c9ef3336 100644 --- a/dive.h +++ b/dive.h @@ -319,6 +319,7 @@ struct dive { bool downloaded; timestamp_t when; char *location; + uint32_t dive_site_uuid; char *notes; char *divemaster, *buddy; int rating; diff --git a/divesite.c b/divesite.c new file mode 100644 index 000000000..1d3bb1c0d --- /dev/null +++ b/divesite.c @@ -0,0 +1,2 @@ +/* divesite.c */ +#include "divesite.h" diff --git a/divesite.h b/divesite.h new file mode 100644 index 000000000..e11a10738 --- /dev/null +++ b/divesite.h @@ -0,0 +1,47 @@ +#ifndef DIVESITE_H +#define DIVESITE_H + +#include "units.h" +#include + +struct dive_site +{ + uint32_t uuid; + char *name; + degrees_t latitude, longitude; + char *description; + char *notes; +}; + +struct dive_site_table { + int nr, allocated; + struct dive_site **dive_sites; +}; + +extern struct dive_site_table dive_site_table; + +static inline struct dive_site *get_dive_site(int nr) +{ + if (nr >= dive_site_table.nr || nr < 0) + return NULL; + return dive_site_table.dive_sites[nr]; +} + +static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid) +{ + for (int i = 0; i < dive_site_table.nr; i++) + if (get_dive_site(i)->uuid == uuid) + return get_dive_site(i); + return NULL; +} + +/* there could be multiple sites of the same name - return the first one */ +static inline struct dive_site *get_dive_site_by_name(const char *name) +{ + for (int i = 0; i < dive_site_table.nr; i++) + if (get_dive_site(i)->name == name) + return get_dive_site(i); + return NULL; +} + +#endif // DIVESITE_H diff --git a/subsurface.pro b/subsurface.pro index 2469b8aa9..4853796c0 100644 --- a/subsurface.pro +++ b/subsurface.pro @@ -29,6 +29,7 @@ HEADERS = \ display.h \ dive.h \ divelist.h \ + divesite.h \ file.h \ gettextfromc.h \ gettext.h \ @@ -119,6 +120,7 @@ SOURCES = \ device.c \ dive.c \ divelist.c \ + divesite.c \ equipment.c \ file.c \ gettextfromc.cpp \ -- cgit v1.2.3-70-g09d2 From 4b15b9dfe910fd0df63bdc8024a919a566c380be Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Wed, 11 Feb 2015 21:46:02 -0800 Subject: Save and parse dive site structures to XML Read and write divesite sections in the XML file. Read divelogs of version 2 and create dive site structures on the fly. Read version 3 files that have divesiteid instead of location / gps. Saves version 3 files where dives no longer have location and gps but instead refer to a divesiteid The commit contains quite a few fprintf(stderr,...) in order to allow better monitoring of the parsing / transforming of locations and gps to dive sites. This will need to be removed later. Signed-off-by: Dirk Hohndel --- dive.h | 16 ++++-- parse-xml.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++----------- save-xml.c | 54 ++++++++------------ 3 files changed, 167 insertions(+), 69 deletions(-) (limited to 'dive.h') diff --git a/dive.h b/dive.h index 2c9ef3336..c38016bb5 100644 --- a/dive.h +++ b/dive.h @@ -8,6 +8,7 @@ #include #include #include +#include "divesite.h" /* Windows has no MIN/MAX macros - so let's just roll our own */ #define MIN(x, y) ({ \ @@ -387,11 +388,6 @@ extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); -static inline int dive_has_gps_location(struct dive *dive) -{ - return dive->latitude.udeg || dive->longitude.udeg; -} - static inline void copy_gps_location(struct dive *from, struct dive *to) { if (from && to) { @@ -607,6 +603,16 @@ static inline int get_idx_by_uniq_id(int id) return i; } +static inline bool dive_site_has_gps_location(struct dive_site *ds) +{ + return ds && (ds->latitude.udeg || ds->longitude.udeg); +} + +static inline int dive_has_gps_location(struct dive *dive) +{ + return dive_site_has_gps_location(get_dive_site_by_uuid(dive->dive_site_uuid)); +} + #ifdef __cplusplus extern "C" { #endif diff --git a/parse-xml.c b/parse-xml.c index 5baa40394..4377a32cb 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -128,6 +128,7 @@ const struct units IMPERIAL_units = IMPERIAL_UNITS; #define MAX_EVENT_NAME 128 static struct divecomputer *cur_dc; static struct dive *cur_dive; +static struct dive_site *cur_dive_site; static dive_trip_t *cur_trip = NULL; static struct sample *cur_sample; static struct picture *cur_picture; @@ -968,22 +969,21 @@ void try_to_fill_userid(const char *name, char *buf) static const char *country, *city; -static void divinglog_place(char *place, char **location) +static void divinglog_place(char *place, uint32_t *uuid) { char buffer[1024], *p; int len; - len = snprintf(buffer, sizeof(buffer), - "%s%s%s%s%s", - place, - city ? ", " : "", - city ? city : "", - country ? ", " : "", - country ? country : ""); - - p = malloc(len + 1); - memcpy(p, buffer, len + 1); - *location = p; + snprintf(buffer, sizeof(buffer), + "%s%s%s%s%s", + place, + city ? ", " : "", + city ? city : "", + country ? ", " : "", + country ? country : ""); + *uuid = get_dive_site_uuid_by_name(buffer); + if (*uuid == 0) + *uuid = create_dive_site(buffer, (degrees_t){0}, (degrees_t){0}); city = NULL; country = NULL; @@ -1005,7 +1005,7 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf) MATCH("names.buddy", utf8_string, &dive->buddy) || MATCH("name.country", utf8_string, &country) || MATCH("name.city", utf8_string, &city) || - MATCH("name.place", divinglog_place, &dive->location) || + MATCH("name.place", divinglog_place, &dive->dive_site_uuid) || 0; } @@ -1138,12 +1138,64 @@ static void gps_long(char *buffer, struct dive *dive) dive->longitude = parse_degrees(buffer, &end); } -static void gps_location(char *buffer, struct dive *dive) +static void gps_location(char *buffer, struct dive_site *ds) { char *end; - dive->latitude = parse_degrees(buffer, &end); - dive->longitude = parse_degrees(end, &end); + ds->latitude = parse_degrees(buffer, &end); + ds->longitude = parse_degrees(end, &end); +} + +static void gps_in_dive(char *buffer, struct dive *dive) +{ + char *end; + fprintf(stderr, "called gps_in_dive with buffer |%s|\n", buffer); + degrees_t latitude = parse_degrees(buffer, &end); + degrees_t longitude = parse_degrees(end, &end); + fprintf(stderr, "got lat %f lon %f\n", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); + uint32_t uuid = dive->dive_site_uuid; + if (uuid == 0) { + fprintf(stderr, "found no uuid in dive, creating a divesite without name and above GPS\n"); + dive->dive_site_uuid = create_dive_site("", latitude, longitude); + } else { + fprintf(stderr, "found uuid in dive, checking to see if we should add GPS\n"); + struct dive_site *ds = get_dive_site_by_uuid(uuid); + if (dive_site_has_gps_location(ds) && + (latitude.udeg != 0 || longitude.udeg != 0) && + (ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) { + // Houston, we have a problem + fprintf(stderr, "dive site uuid in dive, but gps location (%10.6f/%10.6f) different from dive location (%10.6f/%10.6f)\n", + ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0, + latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); + } else { + fprintf(stderr, "let's add the gps coordinates to divesite with uuid %8x and name %s\n", ds->uuid, ds->name ?: "(none)"); + ds->latitude = latitude; + ds->longitude = longitude; + } + } +} + +static void add_dive_site(char *buffer, struct dive *dive) +{ + fprintf(stderr, "add_dive_site with name %s\n", buffer); + int size; + size = trimspace(buffer); + if(size) { + if (dive->dive_site_uuid) { + // we have a uuid, let's hope there's no name + struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid); + if (!ds) { + fprintf(stderr, "dive contains a non-existing dive site uuid %x\n", dive->dive_site_uuid); + exit(1); + } + if (!same_string(ds->name, buffer)) { + fprintf(stderr, "dive links to dive site of different name %s / %s\n", ds->name, buffer); + exit(1); + } + } else { + dive->dive_site_uuid = create_dive_site(buffer, (degrees_t){0}, (degrees_t){0}); + } + } } static void gps_picture_location(char *buffer, struct picture *pic) @@ -1173,7 +1225,8 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) default: break; } - + if (MATCH("divesiteid", hex_value, &dive->dive_site_uuid)) + return; if (MATCH("number", get_index, &dive->number)) return; if (MATCH("tags", divetags, &dive->tag_list)) @@ -1203,9 +1256,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) return; if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end)) return; - if (MATCH("gps", gps_location, dive)) + if (MATCH("gps", gps_in_dive, dive)) return; - if (MATCH("Place", gps_location, dive)) + if (MATCH("Place", gps_in_dive, dive)) return; if (MATCH("latitude", gps_lat, dive)) return; @@ -1219,9 +1272,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) return; if (MATCH("lon", gps_long, dive)) return; - if (MATCH("location", utf8_string, &dive->location)) + if (MATCH("location", add_dive_site, dive)) return; - if (MATCH("name.dive", utf8_string, &dive->location)) + if (MATCH("name.dive", add_dive_site, dive)) return; if (MATCH("suit", utf8_string, &dive->suit)) return; @@ -1290,6 +1343,27 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char * nonmatch("trip", name, buf); } +/* We're processing a divesite entry - try to fill the components */ +static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, char *buf) +{ + start_match("divesite", name, buf); + + struct dive_site *ds = *ds_p; + + if (MATCH("uuid", hex_value, &ds->uuid)) + return; + if (MATCH("name", utf8_string, &ds->name)) + return; + if (MATCH("description", utf8_string, &ds->description)) + return; + if (MATCH("notes", utf8_string, &ds->notes)) + return; + if (MATCH("gps", gps_location, ds)) + return; + + nonmatch("divesite", name, buf); +} + /* * While in some formats file boundaries are dive boundaries, in many * others (as for example in our native format) there are @@ -1305,7 +1379,7 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char * static bool is_dive(void) { return (cur_dive && - (cur_dive->location || cur_dive->when || cur_dive->dc.samples)); + (cur_dive->dive_site_uuid || cur_dive->when || cur_dive->dc.samples)); } static void reset_dc_info(struct divecomputer *dc) @@ -1349,6 +1423,32 @@ static void dc_settings_end(void) reset_dc_settings(); } +static void dive_site_start(void) +{ + if (cur_dive_site) + return; + cur_dive_site = calloc(1, sizeof(struct dive_site)); + fprintf(stderr, "allocated cur_dive_site\n"); +} + +static void dive_site_end(void) +{ + fprintf(stderr, "done with dive_site\n"); + if (!cur_dive_site) + return; + if (cur_dive_site->uuid) { + uint32_t tmp = create_dive_site(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude); + struct dive_site *ds = get_dive_site_by_uuid(tmp); + ds->uuid = cur_dive_site->uuid; + ds->notes = cur_dive_site->notes; + ds->description = cur_dive_site->description; + } + free(cur_dive_site); + cur_dive_site = NULL; +} + +// now we need to add the code to parse the parts of the divesite enry + static void dive_start(void) { if (cur_dive) @@ -1538,6 +1638,10 @@ static void entry(const char *name, char *buf) try_to_match_autogroup(name, buf); return; } + if (cur_dive_site) { + try_to_fill_dive_site(&cur_dive_site, name, buf); + return; + } if (!cur_event.deleted) { try_to_fill_event(name, buf); return; @@ -1666,6 +1770,7 @@ static struct nesting { } nesting[] = { { "divecomputerid", dc_settings_start, dc_settings_end }, { "settings", settings_start, settings_end }, + { "site", dive_site_start, dive_site_end }, { "dive", dive_start, dive_end }, { "Dive", dive_start, dive_end }, { "trip", trip_start, trip_end }, @@ -2291,7 +2396,7 @@ extern int shearwater_dive(void *param, int columns, char **data, char **column) cur_dive->when = (time_t)(atol(data[1])); if (data[2]) - utf8_string(data[2], &cur_dive->location); + add_dive_site(data[2], cur_dive); if (data[3]) utf8_string(data[3], &cur_dive->buddy); if (data[4]) @@ -2388,19 +2493,20 @@ extern int cobalt_visibility(void *handle, int columns, char **data, char **colu extern int cobalt_location(void *handle, int columns, char **data, char **column) { + static char *location = NULL; if (data[0]) { - if (cur_dive->location) { - char *tmp = malloc(strlen(cur_dive->location) + strlen(data[0]) + 4); + if (location) { + char *tmp = malloc(strlen(location) + strlen(data[0]) + 4); if (!tmp) return -1; - sprintf(tmp, "%s / %s", cur_dive->location, data[0]); - free(cur_dive->location); - cur_dive->location = tmp; + sprintf(tmp, "%s / %s", location, data[0]); + free(location); + location = NULL; + cur_dive->dive_site_uuid = create_dive_site(tmp, (degrees_t){0}, (degrees_t){0}); } else { - utf8_string(data[0], &cur_dive->location); + location = strdup(data[0]); } } - return 0; } diff --git a/save-xml.c b/save-xml.c index 053b8fc96..dad57dc9b 100644 --- a/save-xml.c +++ b/save-xml.c @@ -110,38 +110,8 @@ static void save_salinity(struct membuffer *b, struct divecomputer *dc) put_string(b, " />\n"); } -static void show_location(struct membuffer *b, struct dive *dive) -{ - degrees_t latitude = dive->latitude; - degrees_t longitude = dive->longitude; - - /* Should we write a location tag at all? */ - if (!(latitude.udeg || longitude.udeg) && !dive->location) - return; - - put_string(b, " location && dive->location[0] != '\0') - show_utf8(b, dive->location, ">", "\n", 0); - else - put_string(b, "/>\n"); -} - static void save_overview(struct membuffer *b, struct dive *dive) { - show_location(b, dive); show_utf8(b, dive->divemaster, " ", "\n", 0); show_utf8(b, dive->buddy, " ", "\n", 0); show_utf8(b, dive->notes, " ", "\n", 0); @@ -424,7 +394,8 @@ void save_one_dive(struct membuffer *b, struct dive *dive) if (dive->visibility) put_format(b, " visibility='%d'", dive->visibility); save_tags(b, dive->tag_list); - + if (dive->dive_site_uuid) + put_format(b, " divesiteid='%8x'", dive->dive_site_uuid); show_date(b, dive->when); put_format(b, " duration='%u:%02u min'>\n", FRACTION(dive->dc.duration.seconds, 60)); @@ -507,7 +478,7 @@ static void save_one_device(void *_f, const char *model, uint32_t deviceid, put_format(b, "/>\n"); } -#define VERSION 2 +#define VERSION 3 int save_dives(const char *filename) { @@ -529,8 +500,23 @@ void save_dives_buffer(struct membuffer *b, const bool select_only) call_for_each_dc(b, save_one_device); if (autogroup) put_format(b, " \n"); - put_format(b, "\n\n"); - + put_format(b, "\n"); + + /* save the dive sites */ + put_format(b, "\n"); + for (i = 0; i < dive_site_table.nr; i++) { + struct dive_site *ds = get_dive_site(i); + put_format(b, "uuid); + show_utf8(b, ds->name, " name='", "'", 1); + if (ds->latitude.udeg || ds->longitude.udeg) { + put_degrees(b, ds->latitude, " gps='", " "); + put_degrees(b, ds->longitude, "", "'"); + } + show_utf8(b, ds->description, " description='", "'", 1); + show_utf8(b, ds->notes, " notes='", "'", 1); + put_format(b, "/>\n"); + } + put_format(b, "\n\n"); for (trip = dive_trip_list; trip != NULL; trip = trip->next) trip->index = 0; -- cgit v1.2.3-70-g09d2 From d488c37cc11a6051f94715465264a38bf7cf4dc2 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 01:19:07 -0800 Subject: Show dive coordinates on map based on dive site Signed-off-by: Dirk Hohndel --- dive.h | 7 +++++++ qt-ui/globe.cpp | 42 ++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 18 deletions(-) (limited to 'dive.h') diff --git a/dive.h b/dive.h index c38016bb5..42cec6224 100644 --- a/dive.h +++ b/dive.h @@ -505,6 +505,13 @@ static inline struct dive *get_dive_from_table(int nr, struct dive_table *dt) return dt->dives[nr]; } +static inline struct dive_site *get_dive_site_for_dive(struct dive *dive) +{ + if (dive) + return get_dive_site_by_uuid(dive->dive_site_uuid); + return NULL; +} + static inline unsigned int number_of_computers(struct dive *dive) { unsigned int total_number = 0; diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp index cda408ddc..58e7dc620 100644 --- a/qt-ui/globe.cpp +++ b/qt-ui/globe.cpp @@ -164,10 +164,11 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) QList selectedDiveIds; for_each_dive (idx, dive) { long lat_diff, lon_diff; - if (!dive_has_gps_location(dive)) + struct dive_site *ds = get_dive_site_for_dive(dive); + if (!dive_site_has_gps_location(ds)) continue; - lat_diff = labs(dive->latitude.udeg - lat_udeg); - lon_diff = labs(dive->longitude.udeg - lon_udeg); + lat_diff = labs(ds->latitude.udeg - lat_udeg); + lon_diff = labs(ds->longitude.udeg - lon_udeg); if (lat_diff > 180000000) lat_diff = 360000000 - lat_diff; if (lon_diff > 180000000) @@ -186,6 +187,7 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) void GlobeGPS::repopulateLabels() { + struct dive_site *ds; if (loadedDives) { model()->treeModel()->removeDocument(loadedDives); delete loadedDives; @@ -204,12 +206,13 @@ void GlobeGPS::repopulateLabels() // don't show that flag, it's either already shown as displayed_dive // or it's the one that we are moving right now... continue; - if (dive_has_gps_location(dive)) { - GeoDataPlacemark *place = new GeoDataPlacemark(dive->location); - place->setCoordinate(dive->longitude.udeg / 1000000.0, dive->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); + ds = get_dive_site_for_dive(dive); + if (dive_site_has_gps_location(ds)) { + GeoDataPlacemark *place = new GeoDataPlacemark(ds->name); + place->setCoordinate(ds->longitude.udeg / 1000000.0, ds->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); // don't add dive locations twice, unless they are at least 50m apart - if (locationMap[QString(dive->location)]) { - GeoDataCoordinates existingLocation = locationMap[QString(dive->location)]->coordinate(); + if (locationMap[QString(ds->name)]) { + GeoDataCoordinates existingLocation = locationMap[QString(ds->name)]->coordinate(); GeoDataLineString segment = GeoDataLineString(); segment.append(existingLocation); GeoDataCoordinates newLocation = place->coordinate(); @@ -220,7 +223,7 @@ void GlobeGPS::repopulateLabels() if (dist < 0.05) continue; } - locationMap[QString(dive->location)] = place; + locationMap[QString(ds->name)] = place; loadedDives->append(place); } } @@ -236,23 +239,23 @@ void GlobeGPS::reload() void GlobeGPS::centerOnCurrentDive() { - struct dive *dive = current_dive; + struct dive_site *ds = get_dive_site_for_dive(current_dive); // dive has changed, if we had the 'editingDive', hide it. - if (messageWidget->isVisible() && (!dive || dive_has_gps_location(dive) || amount_selected != 1)) + if (messageWidget->isVisible() && (!ds || dive_site_has_gps_location(ds) || amount_selected != 1)) messageWidget->hide(); editingDiveLocation = false; - if (!dive) + if (!ds) return; - qreal longitude = dive->longitude.udeg / 1000000.0; - qreal latitude = dive->latitude.udeg / 1000000.0; + qreal longitude = ds->longitude.udeg / 1000000.0; + qreal latitude = ds->latitude.udeg / 1000000.0; - if ((!dive_has_gps_location(dive) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) { + if ((!dive_site_has_gps_location(ds) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) { prepareForGetDiveCoordinates(); return; } - if (!dive_has_gps_location(dive)) { + if (!dive_site_has_gps_location(ds)) { zoomOutForNoGPS(); return; } @@ -309,8 +312,10 @@ void GlobeGPS::prepareForGetDiveCoordinates() } } +// This needs to update the dive site, not just this dive void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) { + struct dive_site *ds; messageWidget->hide(); if (MainWindow::instance()->dive_list()->selectionModel()->selection().isEmpty()) @@ -324,8 +329,9 @@ void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::U centerOn(lon, lat, true); // change the location of the displayed_dive and put the UI in edit mode - displayed_dive.latitude.udeg = lrint(lat * 1000000.0); - displayed_dive.longitude.udeg = lrint(lon * 1000000.0); + ds = get_dive_site_for_dive(&displayed_dive); + ds->latitude.udeg = lrint(lat * 1000000.0); + ds->longitude.udeg = lrint(lon * 1000000.0); emit(coordinatesChanged()); repopulateLabels(); editingDiveLocation = false; -- cgit v1.2.3-70-g09d2 From 7fb35c98d3657407287e6674e7d20ff2525ef152 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 12:49:25 -0800 Subject: Get trip location from dive's dive site This adds another useful helper function as well. Signed-off-by: Dirk Hohndel --- dive.h | 8 ++++++++ divelist.c | 7 +++---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'dive.h') diff --git a/dive.h b/dive.h index 42cec6224..76ea4b597 100644 --- a/dive.h +++ b/dive.h @@ -512,6 +512,14 @@ static inline struct dive_site *get_dive_site_for_dive(struct dive *dive) return NULL; } +static inline char *get_dive_location(struct dive *dive) +{ + struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid); + if (ds && ds->name) + return ds->name; + return NULL; +} + static inline unsigned int number_of_computers(struct dive *dive) { unsigned int total_number = 0; diff --git a/divelist.c b/divelist.c index f1dd7006c..a6f6332e1 100644 --- a/divelist.c +++ b/divelist.c @@ -678,9 +678,9 @@ void add_dive_to_trip(struct dive *dive, dive_trip_t *trip) dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive) { dive_trip_t *dive_trip = calloc(1, sizeof(dive_trip_t)); + dive_trip->when = dive->when; - if (dive->location) - dive_trip->location = strdup(dive->location); + dive_trip->location = copy_string(get_dive_location(dive)); insert_trip(&dive_trip); dive->tripflag = IN_TRIP; @@ -714,7 +714,7 @@ void autogroup_dives(void) dive_trip_t *trip = lastdive->divetrip; add_dive_to_trip(dive, trip); if (dive->location && !trip->location) - trip->location = strdup(dive->location); + trip->location = copy_string(get_dive_location(dive)); lastdive = dive; continue; } @@ -745,7 +745,6 @@ void delete_single_dive(int idx) dive_table.dives[--dive_table.nr] = NULL; /* free all allocations */ free(dive->dc.sample); - free((void *)dive->location); free((void *)dive->notes); free((void *)dive->divemaster); free((void *)dive->buddy); -- cgit v1.2.3-70-g09d2 From 32da12664dd1055befdb7385176ff9eb8a3b9379 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 20:58:03 -0800 Subject: Switch components for cut/paste dive to dive site logic Signed-off-by: Dirk Hohndel --- dive.h | 3 +-- qt-ui/divecomponentselection.ui | 57 ++++++++++++++++++----------------------- qt-ui/maintab.cpp | 5 ++-- qt-ui/simplewidgets.cpp | 6 ++--- 4 files changed, 30 insertions(+), 41 deletions(-) (limited to 'dive.h') diff --git a/dive.h b/dive.h index 76ea4b597..09c831e43 100644 --- a/dive.h +++ b/dive.h @@ -349,14 +349,13 @@ extern int get_cylinder_idx_by_use(struct dive *dive, enum cylinderuse cylinder_ /* when selectively copying dive information, which parts should be copied? */ struct dive_components { - unsigned int location : 1; + unsigned int divesite : 1; unsigned int notes : 1; unsigned int divemaster : 1; unsigned int buddy : 1; unsigned int suit : 1; unsigned int rating : 1; unsigned int visibility : 1; - unsigned int gps : 1; unsigned int tags : 1; unsigned int cylinders : 1; unsigned int weights : 1; diff --git a/qt-ui/divecomponentselection.ui b/qt-ui/divecomponentselection.ui index dbd0839ba..7eade039b 100644 --- a/qt-ui/divecomponentselection.ui +++ b/qt-ui/divecomponentselection.ui @@ -9,8 +9,8 @@ 0 0 - 308 - 263 + 401 + 317 @@ -41,9 +41,9 @@ - + - Location + Dive site @@ -54,34 +54,6 @@ - - - - GPS coordinates - - - - - - - Divemaster - - - - - - - Buddy - - - - - - - Rating - - - @@ -117,6 +89,27 @@ + + + + Divemaster + + + + + + + Buddy + + + + + + + Rating + + + diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index b0c2009d3..e2ccd44de 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -1314,7 +1314,6 @@ void MainTab::showAndTriggerEditSelective(struct dive_components what) // take the data in our copyPasteDive and apply it to selected dives enableEdition(); copyPaste = true; - SHOW_SELECTIVE(location); SHOW_SELECTIVE(buddy); SHOW_SELECTIVE(divemaster); SHOW_SELECTIVE(suit); @@ -1329,8 +1328,8 @@ void MainTab::showAndTriggerEditSelective(struct dive_components what) ui.rating->setCurrentStars(displayed_dive.rating); if (what.visibility) ui.visibility->setCurrentStars(displayed_dive.visibility); - if (what.gps) - updateGpsCoordinates(); + if (what.divesite) + ui.location->setText(get_dive_location(&displayed_dive)); if (what.tags) { char buf[1024]; taglist_get_tagstring(displayed_dive.tag_list, buf, 1024); diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 756251b51..97b39ee61 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -457,8 +457,7 @@ DiveComponentSelection::DiveComponentSelection(QWidget *parent, struct dive *tar { ui.setupUi(this); what = _what; - UI_FROM_COMPONENT(location); - UI_FROM_COMPONENT(gps); + UI_FROM_COMPONENT(divesite); UI_FROM_COMPONENT(divemaster); UI_FROM_COMPONENT(buddy); UI_FROM_COMPONENT(rating); @@ -478,8 +477,7 @@ DiveComponentSelection::DiveComponentSelection(QWidget *parent, struct dive *tar void DiveComponentSelection::buttonClicked(QAbstractButton *button) { if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) { - COMPONENT_FROM_UI(location); - COMPONENT_FROM_UI(gps); + COMPONENT_FROM_UI(divesite); COMPONENT_FROM_UI(divemaster); COMPONENT_FROM_UI(buddy); COMPONENT_FROM_UI(rating); -- cgit v1.2.3-70-g09d2 From d4f2b7214863b2a40ebcf69e7add113412f795b8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Feb 2015 23:35:52 -0800 Subject: Make special backup when switching XML versions Since the last few dozen commits change the format in irreversible ways and could therefore be destructive and lose data for testers of the development version, let's try to be extra careful and create "special" backup files that aren't overwritten by subsequent backups. At least this way people can go back to the previous state. Of course people using the git backend don't have to worry about this as they always can go back to any earlier save. Signed-off-by: Dirk Hohndel --- dive.h | 2 ++ parse-xml.c | 4 ++++ save-xml.c | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'dive.h') diff --git a/dive.h b/dive.h index 09c831e43..9de3423ad 100644 --- a/dive.h +++ b/dive.h @@ -48,6 +48,8 @@ extern "C" { #include #endif +extern int last_xml_version; + enum dive_comp_type {OC, CCR, PSCR, FREEDIVE, NUM_DC_TYPE}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type enum cylinderuse {OC_GAS, DILUENT, OXYGEN, NUM_GAS_USE}; // The different uses for cylinders diff --git a/parse-xml.c b/parse-xml.c index c93d25453..6cc2d881a 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -21,6 +21,7 @@ int verbose, quit; int metric = 1; +int last_xml_version = -1; static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params); @@ -1644,6 +1645,9 @@ static void userid_stop(void) static void entry(const char *name, char *buf) { + if (!strncmp(name, "version.program", sizeof("version.program") - 1) || + !strncmp(name, "version.divelog", sizeof("version.divelog") - 1)) + last_xml_version = atoi(buf); if (in_userid) { try_to_fill_userid(name, buf); return; diff --git a/save-xml.c b/save-xml.c index dad57dc9b..5a0c6976c 100644 --- a/save-xml.c +++ b/save-xml.c @@ -591,7 +591,15 @@ static void try_to_backup(const char *filename) while (extension[i][0] != '\0') { int elen = strlen(extension[i]); if (strcasecmp(filename + flen - elen, extension[i]) == 0) { - save_backup(filename, extension[i], "bak"); + if (last_xml_version < VERSION) { + int se_len = strlen(extension[i]) + 5; + char *special_ext = malloc(se_len); + snprintf(special_ext, se_len, "%s.v%d", extension[i], last_xml_version); + save_backup(filename, extension[i], special_ext); + free(special_ext); + } else { + save_backup(filename, extension[i], "bak"); + } break; } i++; -- cgit v1.2.3-70-g09d2 From 6708e06872b395c5a0d22d4f5cf17f8ec19bdaf3 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 07:14:30 -0800 Subject: Adapt GPS coordinate download from our companion app to dive sites This is a bit awkward now. We are downloading what looks like fake dives in the v2 format. So we create a dive site for every single fix. After we merge those new dive sites into the existing dives we need to throw away all the dive sites that weren't used. Signed-off-by: Dirk Hohndel --- dive.h | 11 ---------- qt-ui/subsurfacewebservices.cpp | 47 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 16 deletions(-) (limited to 'dive.h') diff --git a/dive.h b/dive.h index 9de3423ad..105d5d8c5 100644 --- a/dive.h +++ b/dive.h @@ -389,17 +389,6 @@ extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); -static inline void copy_gps_location(struct dive *from, struct dive *to) -{ - if (from && to) { - to->latitude.udeg = from->latitude.udeg; - to->longitude.udeg = from->longitude.udeg; - if (!to->location) { - to->location = strdup(from->location); - } - } -} - static inline int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null) { int mbar = dive->surface_pressure.mbar; diff --git a/qt-ui/subsurfacewebservices.cpp b/qt-ui/subsurfacewebservices.cpp index a247888a2..17c15583f 100644 --- a/qt-ui/subsurfacewebservices.cpp +++ b/qt-ui/subsurfacewebservices.cpp @@ -29,7 +29,25 @@ #endif struct dive_table gps_location_table; -static bool merge_locations_into_dives(void); + +// we don't overwrite any existing GPS info in the dive +// so get the dive site and if there is none or there is one without GPS fix, add it +static void copy_gps_location(struct dive *from, struct dive *to) +{ + struct dive_site *ds = get_dive_site_for_dive(to); + if (!ds || !dive_site_has_gps_location(ds)) { + struct dive_site *gds = get_dive_site_for_dive(from); + if (!ds) { + // simply link to the one created for the fake dive + to->dive_site_uuid = gds->uuid; + } else { + ds->latitude = gds->latitude; + ds->longitude = gds->longitude; + if (same_string(ds->name, "")) + ds->name = copy_string(gds->name); + } + } +} #define SAME_GROUP 6 * 3600 // six hours //TODO: C Code. static functions are not good if we plan to have a test for them. @@ -49,7 +67,7 @@ static bool merge_locations_into_dives(void) * Asign and mark position, and end gps_location loop */ if ((dive->when <= gpsfix->when && gpsfix->when <= dive->when + dive->duration.seconds)) { - copy_gps_location(gpsfix,dive); + copy_gps_location(gpsfix, dive); changed++; tracer = j; break; @@ -65,7 +83,7 @@ static bool merge_locations_into_dives(void) * If not, simply fail and nextgpsfix will be evaluated in next iteration. */ if ((dive->when + dive->duration.seconds - gpsfix->when) < (nextgpsfix->when - gpsfix->when)) { - copy_gps_location(gpsfix,dive); + copy_gps_location(gpsfix, dive); tracer = j; break; } @@ -73,7 +91,7 @@ static bool merge_locations_into_dives(void) * If no more positions in range, the actual is the one. Asign, mark and end loop. */ } else { - copy_gps_location(gpsfix,dive); + copy_gps_location(gpsfix, dive); changed++; tracer = j; break; @@ -329,10 +347,19 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton *button) ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); switch (ui.buttonBox->buttonRole(button)) { case QDialogButtonBox::ApplyRole: { + int i; + struct dive *d; + struct dive_site *ds; clear_table(&gps_location_table); QByteArray url = tr("Webservice").toLocal8Bit(); parse_xml_buffer(url.data(), downloadedData.data(), downloadedData.length(), &gps_location_table, NULL); - + // make sure we mark all the dive sites that were created + for (i = 0; i < gps_location_table.nr; i++) { + d = get_dive_from_table(i, &gps_location_table); + ds = get_dive_site_by_uuid(d->dive_site_uuid); + if (ds) + ds->notes = strdup("SubsurfaceWebservice"); + } /* now merge the data in the gps_location table into the dive_table */ if (merge_locations_into_dives()) { mark_divelist_changed(true); @@ -361,6 +388,16 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton *button) hide(); close(); resetState(); + /* and now clean up and remove all the extra dive sites that were created */ + QSet usedUuids; + for_each_dive(i, d) { + if (d->dive_site_uuid) + usedUuids.insert(d->dive_site_uuid); + } + for_each_dive_site(i, ds) { + if (!usedUuids.contains(ds->uuid) && same_string(ds->notes, "SubsurfaceWebservice")) + delete_dive_site(ds->uuid); + } } break; case QDialogButtonBox::RejectRole: if (reply != NULL && reply->isOpen()) { -- cgit v1.2.3-70-g09d2 From 06e578424e272b1c500c2a9e79b4367465fb4ac8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 12:14:24 -0800 Subject: Finally remove location, latitude and longitude from struct dive With this all references to these members should be gone and all the code should be switched over to the dive site infrastructure. Signed-off-by: Dirk Hohndel --- dive.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'dive.h') diff --git a/dive.h b/dive.h index 105d5d8c5..533a193b6 100644 --- a/dive.h +++ b/dive.h @@ -321,12 +321,10 @@ struct dive { bool hidden_by_filter; bool downloaded; timestamp_t when; - char *location; uint32_t dive_site_uuid; char *notes; char *divemaster, *buddy; int rating; - degrees_t latitude, longitude; int visibility; /* 0 - 5 star rating */ cylinder_t cylinder[MAX_CYLINDERS]; weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS]; -- cgit v1.2.3-70-g09d2 From 32ad046f5681ad02e3f9842075447e880145267d Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Feb 2015 12:38:56 -0800 Subject: Allow editing of dive sites And hook things up when double clicking the globe. The user experience isn't consistent with what we do on the main tab (i.e., no coloring of fields that are changed), but it seems to work. Signed-off-by: Dirk Hohndel --- dive.c | 1 + dive.h | 1 + qt-ui/globe.cpp | 10 ++++++---- qt-ui/mainwindow.cpp | 9 ++++----- qt-ui/simplewidgets.cpp | 35 +++++++++++++++++++++++++++++++---- qt-ui/simplewidgets.h | 1 + 6 files changed, 44 insertions(+), 13 deletions(-) (limited to 'dive.h') diff --git a/dive.c b/dive.c index 3b682ee5f..758368615 100644 --- a/dive.c +++ b/dive.c @@ -13,6 +13,7 @@ * it's used in the UI, but it seems to make the most sense to have it * here */ struct dive displayed_dive; +struct dive_site displayed_dive_site; struct tag_entry *g_tag_list = NULL; diff --git a/dive.h b/dive.h index 533a193b6..8247a5f50 100644 --- a/dive.h +++ b/dive.h @@ -474,6 +474,7 @@ struct dive_table { extern struct dive_table dive_table; extern struct dive displayed_dive; +extern struct dive_site displayed_dive_site; extern int selected_dive; extern unsigned int dc_number; #define current_dive (get_dive(selected_dive)) diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp index 256eff175..91bb4e858 100644 --- a/qt-ui/globe.cpp +++ b/qt-ui/globe.cpp @@ -206,7 +206,10 @@ void GlobeGPS::repopulateLabels() // don't show that flag, it's either already shown as displayed_dive // or it's the one that we are moving right now... continue; - ds = get_dive_site_for_dive(dive); + if (idx == -1) + ds = &displayed_dive_site; + else + ds = get_dive_site_for_dive(dive); if (dive_site_has_gps_location(ds)) { GeoDataPlacemark *place = new GeoDataPlacemark(ds->name); place->setCoordinate(ds->longitude.udeg / 1000000.0, ds->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); @@ -329,9 +332,8 @@ void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::U centerOn(lon, lat, true); // change the location of the displayed_dive and put the UI in edit mode - ds = get_dive_site_for_dive(&displayed_dive); - ds->latitude.udeg = lrint(lat * 1000000.0); - ds->longitude.udeg = lrint(lon * 1000000.0); + displayed_dive_site.latitude.udeg = lrint(lat * 1000000.0); + displayed_dive_site.longitude.udeg = lrint(lon * 1000000.0); emit(coordinatesChanged()); repopulateLabels(); editingDiveLocation = false; diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 7776f312e..6a67befa1 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -113,6 +113,8 @@ MainWindow::MainWindow() : QMainWindow(), connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan())); connect(mainTab, SIGNAL(requestDiveSiteEdit(uint32_t)), this, SLOT(enableDiveSiteEdit(uint32_t))); connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(setDefaultState())); + connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(refreshDisplay())); + #ifdef NO_PRINTING ui.printPlan->hide(); ui.menuFile->removeAction(ui.actionPrint); @@ -133,10 +135,7 @@ MainWindow::MainWindow() : QMainWindow(), #ifdef NO_MARBLE ui.menuView->removeAction(ui.actionViewGlobe); #else - // FIXME - // TODO - // we need this on the dive sites - //connect(globe(), SIGNAL(coordinatesChanged()), information(), SLOT(updateGpsCoordinates())); + connect(globe(), SIGNAL(coordinatesChanged()), locationInformation, SLOT(updateGpsCoordinates())); #endif #ifdef NO_USERMANUAL ui.menuHelp->removeAction(ui.actionUserManual); @@ -218,7 +217,6 @@ LocationInformationWidget *MainWindow::locationInformationWidget() { } void MainWindow::enableDiveSiteEdit(uint32_t id) { - locationInformationWidget()->setLocationId(id); setApplicationState("EditDiveSite"); } @@ -276,6 +274,7 @@ void MainWindow::current_dive_changed(int divenr) } graphics()->plotDive(); information()->updateDiveInfo(); + locationInformationWidget()->setLocationId(displayed_dive.dive_site_uuid); } void MainWindow::on_actionNew_triggered() diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 97b39ee61..00f749780 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -666,19 +666,46 @@ LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBo void LocationInformationWidget::setLocationId(uint32_t uuid) { currentDs = get_dive_site_by_uuid(uuid); - ui.diveSiteName->setText(currentDs->name); - ui.diveSiteDescription->setText(currentDs->description); - ui.diveSiteNotes->setPlainText(currentDs->notes); - ui.diveSiteCoordinates->setText(printGPSCoords(currentDs->latitude.udeg, currentDs->longitude.udeg)); + displayed_dive_site = *currentDs; + ui.diveSiteName->setText(displayed_dive_site.name); + ui.diveSiteDescription->setText(displayed_dive_site.description); + ui.diveSiteNotes->setPlainText(displayed_dive_site.notes); + ui.diveSiteCoordinates->setText(printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg)); +} + +void LocationInformationWidget::updateGpsCoordinates() +{ + ui.diveSiteCoordinates->setText(printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg)); + MainWindow::instance()->setApplicationState("EditDiveSite"); } void LocationInformationWidget::acceptChanges() { + char *uiString; + currentDs->latitude = displayed_dive_site.latitude; + currentDs->longitude = displayed_dive_site.longitude; + uiString = ui.diveSiteName->text().toUtf8().data(); + if (!same_string(uiString, currentDs->name)) { + free(currentDs->name); + currentDs->name = copy_string(uiString); + } + uiString = ui.diveSiteDescription->text().toUtf8().data(); + if (!same_string(uiString, currentDs->description)) { + free(currentDs->description); + currentDs->description = copy_string(uiString); + } + uiString = ui.diveSiteNotes->document()->toPlainText().toUtf8().data(); + if (!same_string(uiString, currentDs->notes)) { + free(currentDs->notes); + currentDs->notes = copy_string(uiString); + } + mark_divelist_changed(true); emit informationManagementEnded(); } void LocationInformationWidget::rejectChanges() { + setLocationId(currentDs->uuid); emit informationManagementEnded(); } diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index 9cedb8ad5..d0cb60508 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -229,6 +229,7 @@ public slots: void showEvent(QShowEvent *); void setLocationId(uint32_t uuid); + void updateGpsCoordinates(void); signals: void informationManagementEnded(); -- cgit v1.2.3-70-g09d2