Add 'location_t' data structure

Instead of having people treat latitude and longitude as separate
things, just add a 'location_t' data structure that contains both.

Almost all cases want to always act on them together.

This is really just prep-work for adding a few more locations that we
track: I want to add a entry/exit location to each dive (independent of
the dive site) because of how the Garmin Descent gives us the
information (and hopefully, some day, other dive computers too).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Linus Torvalds 2018-10-20 14:12:15 -04:00 committed by Lubomir I. Ivanov
parent c986940630
commit 28e3413ff6
40 changed files with 251 additions and 264 deletions

View file

@ -4048,8 +4048,7 @@ void dive_create_picture(struct dive *dive, const char *filename, int shift_time
struct picture *picture = alloc_picture(); struct picture *picture = alloc_picture();
picture->filename = strdup(filename); picture->filename = strdup(filename);
picture->offset.seconds = metadata.timestamp - dive->when + shift_time; picture->offset.seconds = metadata.timestamp - dive->when + shift_time;
picture->longitude = metadata.longitude; picture->location = metadata.location;
picture->latitude = metadata.latitude;
dive_add_picture(dive, picture); dive_add_picture(dive, picture);
dive_set_geodata_from_picture(dive, picture); dive_set_geodata_from_picture(dive, picture);
@ -4078,12 +4077,11 @@ unsigned int dive_get_picture_count(struct dive *dive)
void dive_set_geodata_from_picture(struct dive *dive, struct picture *picture) void dive_set_geodata_from_picture(struct dive *dive, struct picture *picture)
{ {
struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid); struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid);
if (!dive_site_has_gps_location(ds) && (picture->latitude.udeg || picture->longitude.udeg)) { if (!dive_site_has_gps_location(ds) && has_location(&picture->location)) {
if (ds) { if (ds) {
ds->latitude = picture->latitude; ds->location = picture->location;
ds->longitude = picture->longitude;
} else { } else {
dive->dive_site_uuid = create_dive_site_with_gps("", picture->latitude, picture->longitude, dive->when); dive->dive_site_uuid = create_dive_site_with_gps("", &picture->location, dive->when);
invalidate_dive_cache(dive); invalidate_dive_cache(dive);
} }
} }
@ -4428,7 +4426,7 @@ int get_idx_by_uniq_id(int id)
bool dive_site_has_gps_location(const struct dive_site *ds) bool dive_site_has_gps_location(const struct dive_site *ds)
{ {
return ds && (ds->latitude.udeg || ds->longitude.udeg); return ds && has_location(&ds->location);
} }
int dive_has_gps_location(const struct dive *dive) int dive_has_gps_location(const struct dive *dive)

View file

@ -363,8 +363,7 @@ extern enum divemode_t get_divemode_at_time(const struct divecomputer *dc, int d
struct picture { struct picture {
char *filename; char *filename;
offset_t offset; offset_t offset;
degrees_t latitude; location_t location;
degrees_t longitude;
struct picture *next; struct picture *next;
}; };

View file

@ -26,12 +26,12 @@ uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp)
} }
/* there could be multiple sites at the same GPS fix - return the first one */ /* there could be multiple sites at the same GPS fix - return the first one */
uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp) uint32_t get_dive_site_uuid_by_gps(const location_t *loc, struct dive_site **dsp)
{ {
int i; int i;
struct dive_site *ds; struct dive_site *ds;
for_each_dive_site (i, ds) { for_each_dive_site (i, ds) {
if (ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg) { if (same_location(loc, &ds->location)) {
if (dsp) if (dsp)
*dsp = ds; *dsp = ds;
return ds->uuid; return ds->uuid;
@ -43,23 +43,23 @@ uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, stru
/* to avoid a bug where we have two dive sites with different name and the same GPS coordinates /* to avoid a bug where we have two dive sites with different name and the same GPS coordinates
* and first get the gps coordinates (reading a V2 file) and happen to get back "the other" name, * and first get the gps coordinates (reading a V2 file) and happen to get back "the other" name,
* this function allows us to verify if a very specific name/GPS combination already exists */ * this function allows us to verify if a very specific name/GPS combination already exists */
uint32_t get_dive_site_uuid_by_gps_and_name(char *name, degrees_t latitude, degrees_t longitude) uint32_t get_dive_site_uuid_by_gps_and_name(char *name, const location_t *loc)
{ {
int i; int i;
struct dive_site *ds; struct dive_site *ds;
for_each_dive_site (i, ds) { for_each_dive_site (i, ds) {
if (ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg && same_string(ds->name, name)) if (same_location(loc, &ds->location) && same_string(ds->name, name))
return ds->uuid; return ds->uuid;
} }
return 0; return 0;
} }
// Calculate the distance in meters between two coordinates. // Calculate the distance in meters between two coordinates.
unsigned int get_distance(degrees_t lat1, degrees_t lon1, degrees_t lat2, degrees_t lon2) unsigned int get_distance(const location_t *loc1, const location_t *loc2)
{ {
double lat2_r = udeg_to_radians(lat2.udeg); double lat2_r = udeg_to_radians(loc2->lat.udeg);
double lat_d_r = udeg_to_radians(lat2.udeg-lat1.udeg); double lat_d_r = udeg_to_radians(loc2->lat.udeg - loc1->lat.udeg);
double lon_d_r = udeg_to_radians(lon2.udeg-lon1.udeg); double lon_d_r = udeg_to_radians(loc2->lon.udeg - loc1->lon.udeg);
double a = sin(lat_d_r/2) * sin(lat_d_r/2) + double a = sin(lat_d_r/2) * sin(lat_d_r/2) +
cos(lat2_r) * cos(lat2_r) * sin(lon_d_r/2) * sin(lon_d_r/2); cos(lat2_r) * cos(lat2_r) * sin(lon_d_r/2) * sin(lon_d_r/2);
@ -70,7 +70,7 @@ unsigned int get_distance(degrees_t lat1, degrees_t lon1, degrees_t lat2, degree
} }
/* find the closest one, no more than distance meters away - if more than one at same distance, pick the first */ /* find the closest one, no more than distance meters away - if more than one at same distance, pick the first */
uint32_t get_dive_site_uuid_by_gps_proximity(degrees_t latitude, degrees_t longitude, int distance, struct dive_site **dsp) uint32_t get_dive_site_uuid_by_gps_proximity(const location_t *loc, int distance, struct dive_site **dsp)
{ {
int i; int i;
int uuid = 0; int uuid = 0;
@ -78,7 +78,7 @@ uint32_t get_dive_site_uuid_by_gps_proximity(degrees_t latitude, degrees_t longi
unsigned int cur_distance, min_distance = distance; unsigned int cur_distance, min_distance = distance;
for_each_dive_site (i, ds) { for_each_dive_site (i, ds) {
if (dive_site_has_gps_location(ds) && if (dive_site_has_gps_location(ds) &&
(cur_distance = get_distance(ds->latitude, ds->longitude, latitude, longitude)) < min_distance) { (cur_distance = get_distance(&ds->location, loc)) < min_distance) {
min_distance = cur_distance; min_distance = cur_distance;
uuid = ds->uuid; uuid = ds->uuid;
if (dsp) if (dsp)
@ -232,13 +232,12 @@ uint32_t create_dive_site_from_current_dive(const char *name)
} }
/* same as before, but with GPS data */ /* same as before, but with GPS data */
uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude, timestamp_t divetime) uint32_t create_dive_site_with_gps(const char *name, const location_t *loc, timestamp_t divetime)
{ {
uint32_t uuid = create_divesite_uuid(name, divetime); uint32_t uuid = create_divesite_uuid(name, divetime);
struct dive_site *ds = alloc_or_get_dive_site(uuid); struct dive_site *ds = alloc_or_get_dive_site(uuid);
ds->name = copy_string(name); ds->name = copy_string(name);
ds->latitude = latitude; ds->location = *loc;
ds->longitude = longitude;
return ds->uuid; return ds->uuid;
} }
@ -250,8 +249,7 @@ bool dive_site_is_empty(struct dive_site *ds)
(empty_string(ds->name) && (empty_string(ds->name) &&
empty_string(ds->description) && empty_string(ds->description) &&
empty_string(ds->notes) && empty_string(ds->notes) &&
ds->latitude.udeg == 0 && !has_location(&ds->location));
ds->longitude.udeg == 0);
} }
void copy_dive_site(struct dive_site *orig, struct dive_site *copy) void copy_dive_site(struct dive_site *orig, struct dive_site *copy)
@ -260,8 +258,7 @@ void copy_dive_site(struct dive_site *orig, struct dive_site *copy)
free(copy->notes); free(copy->notes);
free(copy->description); free(copy->description);
copy->latitude = orig->latitude; copy->location = orig->location;
copy->longitude = orig->longitude;
copy->name = copy_string(orig->name); copy->name = copy_string(orig->name);
copy->notes = copy_string(orig->notes); copy->notes = copy_string(orig->notes);
copy->description = copy_string(orig->description); copy->description = copy_string(orig->description);
@ -290,8 +287,7 @@ static void merge_string(char **a, char **b)
void merge_dive_site(struct dive_site *a, struct dive_site *b) void merge_dive_site(struct dive_site *a, struct dive_site *b)
{ {
if (!a->latitude.udeg) a->latitude.udeg = b->latitude.udeg; if (!has_location(&a->location)) a->location = b->location;
if (!a->longitude.udeg) a->longitude.udeg = b->longitude.udeg;
merge_string(&a->name, &b->name); merge_string(&a->name, &b->name);
merge_string(&a->notes, &b->notes); merge_string(&a->notes, &b->notes);
merge_string(&a->description, &b->description); merge_string(&a->description, &b->description);
@ -310,8 +306,8 @@ void clear_dive_site(struct dive_site *ds)
ds->name = NULL; ds->name = NULL;
ds->notes = NULL; ds->notes = NULL;
ds->description = NULL; ds->description = NULL;
ds->latitude.udeg = 0; ds->location.lat.udeg = 0;
ds->longitude.udeg = 0; ds->location.lon.udeg = 0;
ds->uuid = 0; ds->uuid = 0;
ds->taxonomy.nr = 0; ds->taxonomy.nr = 0;
free_taxonomy(&ds->taxonomy); free_taxonomy(&ds->taxonomy);

View file

@ -18,7 +18,7 @@ struct dive_site
{ {
uint32_t uuid; uint32_t uuid;
char *name; char *name;
degrees_t latitude, longitude; location_t location;
char *description; char *description;
char *notes; char *notes;
struct taxonomy_data taxonomy; struct taxonomy_data taxonomy;
@ -60,17 +60,17 @@ void free_dive_site(struct dive_site *ds);
void delete_dive_site(uint32_t id); void delete_dive_site(uint32_t id);
uint32_t create_dive_site(const char *name, timestamp_t divetime); uint32_t create_dive_site(const char *name, timestamp_t divetime);
uint32_t create_dive_site_from_current_dive(const char *name); uint32_t create_dive_site_from_current_dive(const char *name);
uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude, timestamp_t divetime); uint32_t create_dive_site_with_gps(const char *name, const location_t *, timestamp_t divetime);
uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp); uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp);
uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp); uint32_t get_dive_site_uuid_by_gps(const location_t *, struct dive_site **dsp);
uint32_t get_dive_site_uuid_by_gps_and_name(char *name, degrees_t latitude, degrees_t longitude); uint32_t get_dive_site_uuid_by_gps_and_name(char *name, const location_t *);
uint32_t get_dive_site_uuid_by_gps_proximity(degrees_t latitude, degrees_t longitude, int distance, struct dive_site **dsp); uint32_t get_dive_site_uuid_by_gps_proximity(const location_t *, int distance, struct dive_site **dsp);
bool dive_site_is_empty(struct dive_site *ds); bool dive_site_is_empty(struct dive_site *ds);
void copy_dive_site_taxonomy(struct dive_site *orig, struct dive_site *copy); void copy_dive_site_taxonomy(struct dive_site *orig, struct dive_site *copy);
void copy_dive_site(struct dive_site *orig, struct dive_site *copy); void copy_dive_site(struct dive_site *orig, struct dive_site *copy);
void merge_dive_site(struct dive_site *a, struct dive_site *b); void merge_dive_site(struct dive_site *a, struct dive_site *b);
void clear_dive_site(struct dive_site *ds); void clear_dive_site(struct dive_site *ds);
unsigned int get_distance(degrees_t lat1, degrees_t lon1, degrees_t lat2, degrees_t lon2); unsigned int get_distance(const location_t *loc1, const location_t *loc2);
uint32_t find_or_create_dive_site_with_name(const char *name, timestamp_t divetime); uint32_t find_or_create_dive_site_with_name(const char *name, timestamp_t divetime);
void merge_dive_sites(uint32_t ref, uint32_t *uuids, int count); void merge_dive_sites(uint32_t ref, uint32_t *uuids, int count);

View file

@ -137,7 +137,7 @@ QString GpsLocation::currentPosition()
if (delta < 300) { if (delta < 300) {
// we can simply use the last position that we tracked // we can simply use the last position that we tracked
gpsTracker gt = m_trackers.last(); gpsTracker gt = m_trackers.last();
QString gpsString = printGPSCoords(gt.latitude.udeg, gt.longitude.udeg); QString gpsString = printGPSCoords(&gt.location);
qDebug() << "returning last position" << gpsString; qDebug() << "returning last position" << gpsString;
return gpsString; return gpsString;
} else { } else {
@ -159,8 +159,8 @@ void GpsLocation::newPosition(QGeoPositionInfo pos)
int nr = m_trackers.count(); int nr = m_trackers.count();
if (nr) { if (nr) {
gpsTracker gt = m_trackers.last(); gpsTracker gt = m_trackers.last();
lastCoord.setLatitude(gt.latitude.udeg / 1000000.0); lastCoord.setLatitude(gt.location.lat.udeg / 1000000.0);
lastCoord.setLongitude(gt.longitude.udeg / 1000000.0); lastCoord.setLongitude(gt.location.lon.udeg / 1000000.0);
lastTime = gt.when; lastTime = gt.when;
} }
// if we are waiting for a position update or // if we are waiting for a position update or
@ -176,8 +176,7 @@ void GpsLocation::newPosition(QGeoPositionInfo pos)
gpsTracker gt; gpsTracker gt;
gt.when = pos.timestamp().toTime_t(); gt.when = pos.timestamp().toTime_t();
gt.when += gettimezoneoffset(gt.when); gt.when += gettimezoneoffset(gt.when);
gt.latitude.udeg = lrint(pos.coordinate().latitude() * 1000000); gt.location = create_location(pos.coordinate().latitude(), pos.coordinate().longitude());
gt.longitude.udeg = lrint(pos.coordinate().longitude() * 1000000);
addFixToStorage(gt); addFixToStorage(gt);
gpsTracker gtNew = m_trackers.last(); gpsTracker gtNew = m_trackers.last();
qDebug() << "newest fix is now at" << QDateTime().fromMSecsSinceEpoch(gtNew.when - gettimezoneoffset(gtNew.when) * 1000).toString(); qDebug() << "newest fix is now at" << QDateTime().fromMSecsSinceEpoch(gtNew.when - gettimezoneoffset(gtNew.when) * 1000).toString();
@ -215,8 +214,7 @@ static void copy_gps_location(struct gpsTracker &gps, struct dive *d)
d->dive_site_uuid = create_dive_site(qPrintable(gps.name), gps.when); d->dive_site_uuid = create_dive_site(qPrintable(gps.name), gps.when);
ds = get_dive_site_by_uuid(d->dive_site_uuid); ds = get_dive_site_by_uuid(d->dive_site_uuid);
} }
ds->latitude = gps.latitude; ds->location = gps.location;
ds->longitude = gps.longitude;
} }
#define SAME_GROUP 6 * 3600 /* six hours */ #define SAME_GROUP 6 * 3600 /* six hours */
@ -331,8 +329,8 @@ void GpsLocation::loadFromStorage()
for (int i = 0; i < nr; i++) { for (int i = 0; i < nr; i++) {
struct gpsTracker gt; struct gpsTracker gt;
gt.when = geoSettings->value(QString("gpsFix%1_time").arg(i)).toLongLong(); gt.when = geoSettings->value(QString("gpsFix%1_time").arg(i)).toLongLong();
gt.latitude.udeg = geoSettings->value(QString("gpsFix%1_lat").arg(i)).toInt(); gt.location.lat.udeg = geoSettings->value(QString("gpsFix%1_lat").arg(i)).toInt();
gt.longitude.udeg = geoSettings->value(QString("gpsFix%1_lon").arg(i)).toInt(); gt.location.lon.udeg = geoSettings->value(QString("gpsFix%1_lon").arg(i)).toInt();
gt.name = geoSettings->value(QString("gpsFix%1_name").arg(i)).toString(); gt.name = geoSettings->value(QString("gpsFix%1_name").arg(i)).toString();
gt.idx = i; gt.idx = i;
m_trackers.insert(gt.when, gt); m_trackers.insert(gt.when, gt);
@ -347,11 +345,10 @@ void GpsLocation::replaceFixToStorage(gpsTracker &gt)
} }
gpsTracker replacedTracker = m_trackers.value(gt.when); gpsTracker replacedTracker = m_trackers.value(gt.when);
geoSettings->setValue(QString("gpsFix%1_time").arg(replacedTracker.idx), gt.when); geoSettings->setValue(QString("gpsFix%1_time").arg(replacedTracker.idx), gt.when);
geoSettings->setValue(QString("gpsFix%1_lat").arg(replacedTracker.idx), gt.latitude.udeg); geoSettings->setValue(QString("gpsFix%1_lat").arg(replacedTracker.idx), gt.location.lat.udeg);
geoSettings->setValue(QString("gpsFix%1_lon").arg(replacedTracker.idx), gt.longitude.udeg); geoSettings->setValue(QString("gpsFix%1_lon").arg(replacedTracker.idx), gt.location.lon.udeg);
geoSettings->setValue(QString("gpsFix%1_name").arg(replacedTracker.idx), gt.name); geoSettings->setValue(QString("gpsFix%1_name").arg(replacedTracker.idx), gt.name);
replacedTracker.latitude = gt.latitude; replacedTracker.location = gt.location;
replacedTracker.longitude = gt.longitude;
replacedTracker.name = gt.name; replacedTracker.name = gt.name;
} }
@ -360,8 +357,8 @@ void GpsLocation::addFixToStorage(gpsTracker &gt)
int nr = m_trackers.count(); int nr = m_trackers.count();
geoSettings->setValue("count", nr + 1); geoSettings->setValue("count", nr + 1);
geoSettings->setValue(QString("gpsFix%1_time").arg(nr), gt.when); geoSettings->setValue(QString("gpsFix%1_time").arg(nr), gt.when);
geoSettings->setValue(QString("gpsFix%1_lat").arg(nr), gt.latitude.udeg); geoSettings->setValue(QString("gpsFix%1_lat").arg(nr), gt.location.lat.udeg);
geoSettings->setValue(QString("gpsFix%1_lon").arg(nr), gt.longitude.udeg); geoSettings->setValue(QString("gpsFix%1_lon").arg(nr), gt.location.lon.udeg);
geoSettings->setValue(QString("gpsFix%1_name").arg(nr), gt.name); geoSettings->setValue(QString("gpsFix%1_name").arg(nr), gt.name);
gt.idx = nr; gt.idx = nr;
geoSettings->sync(); geoSettings->sync();
@ -389,8 +386,8 @@ void GpsLocation::deleteFixFromStorage(gpsTracker &gt)
m_trackers.remove(movedTracker.when); m_trackers.remove(movedTracker.when);
m_trackers.insert(movedTracker.when, movedTracker); m_trackers.insert(movedTracker.when, movedTracker);
geoSettings->setValue(QString("gpsFix%1_time").arg(movedTracker.idx), when); geoSettings->setValue(QString("gpsFix%1_time").arg(movedTracker.idx), when);
geoSettings->setValue(QString("gpsFix%1_lat").arg(movedTracker.idx), movedTracker.latitude.udeg); geoSettings->setValue(QString("gpsFix%1_lat").arg(movedTracker.idx), movedTracker.location.lat.udeg);
geoSettings->setValue(QString("gpsFix%1_lon").arg(movedTracker.idx), movedTracker.longitude.udeg); geoSettings->setValue(QString("gpsFix%1_lon").arg(movedTracker.idx), movedTracker.location.lon.udeg);
geoSettings->setValue(QString("gpsFix%1_name").arg(movedTracker.idx), movedTracker.name); geoSettings->setValue(QString("gpsFix%1_name").arg(movedTracker.idx), movedTracker.name);
geoSettings->remove(QString("gpsFix%1_lat").arg(cnt - 1)); geoSettings->remove(QString("gpsFix%1_lat").arg(cnt - 1));
geoSettings->remove(QString("gpsFix%1_lon").arg(cnt - 1)); geoSettings->remove(QString("gpsFix%1_lon").arg(cnt - 1));

View file

@ -14,8 +14,7 @@
#define GPS_CURRENT_POS gettextFromC::tr("Waiting to aquire GPS location") #define GPS_CURRENT_POS gettextFromC::tr("Waiting to aquire GPS location")
struct gpsTracker { struct gpsTracker {
degrees_t latitude; location_t location;
degrees_t longitude;
qint64 when; qint64 when;
QString name; QString name;
int idx; int idx;

View file

@ -569,7 +569,7 @@ static void set_dc_serial(struct divecomputer *dc, const char *serial)
dc->deviceid = calculate_string_hash(serial); dc->deviceid = calculate_string_hash(serial);
} }
extern degrees_t parse_degrees(char *buf, char **end); extern void parse_location(char *, location_t *);
static void parse_string_field(struct dive *dive, dc_field_string_t *str) static void parse_string_field(struct dive *dive, dc_field_string_t *str)
{ {
@ -591,14 +591,12 @@ static void parse_string_field(struct dive *dive, dc_field_string_t *str)
/* GPS data? */ /* GPS data? */
if (!strncmp(str->desc, "GPS", 3)) { if (!strncmp(str->desc, "GPS", 3)) {
char *line = (char *) str->value; char *line = (char *) str->value;
degrees_t latitude, longitude; location_t location;
latitude = parse_degrees(line, &line); parse_location(line, &location);
if (*line == ',') line++;
longitude = parse_degrees(line, &line);
if (latitude.udeg && longitude.udeg) if (location.lat.udeg && location.lon.udeg)
dive->dive_site_uuid = create_dive_site_with_gps(str->value, latitude, longitude, time(NULL)); dive->dive_site_uuid = create_dive_site_with_gps(str->value, &location, time(NULL));
} }
} }
#endif #endif

View file

@ -31,7 +31,7 @@ struct keyword_action {
}; };
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0])) #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
extern degrees_t parse_degrees(char *buf, char **end); extern void parse_location(char *buf, location_t *);
git_blob *git_tree_entry_blob(git_repository *repo, const git_tree_entry *entry); git_blob *git_tree_entry_blob(git_repository *repo, const git_tree_entry *entry);
static char *get_utf8(struct membuffer *b) static char *get_utf8(struct membuffer *b)
@ -152,25 +152,24 @@ static void parse_dive_gps(char *line, struct membuffer *str, void *_dive)
{ {
UNUSED(str); UNUSED(str);
uint32_t uuid; uint32_t uuid;
degrees_t latitude = parse_degrees(line, &line); location_t location;
degrees_t longitude = parse_degrees(line, &line);
struct dive *dive = _dive; struct dive *dive = _dive;
struct dive_site *ds = get_dive_site_for_dive(dive); struct dive_site *ds = get_dive_site_for_dive(dive);
parse_location(line, &location);
if (!ds) { if (!ds) {
uuid = get_dive_site_uuid_by_gps(latitude, longitude, NULL); uuid = get_dive_site_uuid_by_gps(&location, NULL);
if (!uuid) if (!uuid)
uuid = create_dive_site_with_gps("", latitude, longitude, dive->when); uuid = create_dive_site_with_gps("", &location, dive->when);
dive->dive_site_uuid = uuid; dive->dive_site_uuid = uuid;
} else { } else {
if (dive_site_has_gps_location(ds) && if (dive_site_has_gps_location(ds) && !same_location(&ds->location, &location)) {
(ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) { const char *coords = printGPSCoords(&location);
const char *coords = printGPSCoords(latitude.udeg, longitude.udeg);
// we have a dive site that already has GPS coordinates // we have a dive site that already has GPS coordinates
ds->notes = add_to_string(ds->notes, translate("gettextFromC", "multiple GPS locations for this dive site; also %s\n"), coords); ds->notes = add_to_string(ds->notes, translate("gettextFromC", "multiple GPS locations for this dive site; also %s\n"), coords);
free((void *)coords); free((void *)coords);
} }
ds->latitude = latitude; ds->location = location;
ds->longitude = longitude;
} }
} }
@ -274,14 +273,12 @@ static void parse_site_name(char *line, struct membuffer *str, void *_ds)
static void parse_site_notes(char *line, struct membuffer *str, void *_ds) static void parse_site_notes(char *line, struct membuffer *str, void *_ds)
{ UNUSED(line); struct dive_site *ds = _ds; ds->notes = strdup(mb_cstring(str)); } { UNUSED(line); struct dive_site *ds = _ds; ds->notes = strdup(mb_cstring(str)); }
extern degrees_t parse_degrees(char *buf, char **end);
static void parse_site_gps(char *line, struct membuffer *str, void *_ds) static void parse_site_gps(char *line, struct membuffer *str, void *_ds)
{ {
UNUSED(str); UNUSED(str);
struct dive_site *ds = _ds; struct dive_site *ds = _ds;
ds->latitude = parse_degrees(line, &line); parse_location(line, &ds->location);
ds->longitude = parse_degrees(line, &line);
} }
static void parse_site_geo(char *line, struct membuffer *str, void *_ds) static void parse_site_geo(char *line, struct membuffer *str, void *_ds)
@ -949,8 +946,7 @@ static void parse_picture_gps(char *line, struct membuffer *str, void *_pic)
UNUSED(str); UNUSED(str);
struct picture *pic = _pic; struct picture *pic = _pic;
pic->latitude = parse_degrees(line, &line); parse_location(line, &pic->location);
pic->longitude = parse_degrees(line, &line);
} }
static void parse_picture_hash(char *line, struct membuffer *str, void *_pic) static void parse_picture_hash(char *line, struct membuffer *str, void *_pic)

View file

@ -218,6 +218,14 @@ void put_degrees(struct membuffer *b, degrees_t value, const char *pre, const ch
put_format(b, "%s%s%u.%06u%s", pre, sign, FRACTION(udeg, 1000000), post); put_format(b, "%s%s%u.%06u%s", pre, sign, FRACTION(udeg, 1000000), post);
} }
void put_location(struct membuffer *b, location_t *loc, const char *pre, const char *post)
{
if (has_location(loc)) {
put_degrees(b, loc->lat, pre, " ");
put_degrees(b, loc->lon, "", post);
}
}
void put_quoted(struct membuffer *b, const char *text, int is_attribute, int is_html) void put_quoted(struct membuffer *b, const char *text, int is_attribute, int is_html)
{ {
const char *p = text; const char *p = text;

View file

@ -109,6 +109,7 @@ extern void put_duration(struct membuffer *, duration_t, const char *, const cha
extern void put_pressure(struct membuffer *, pressure_t, const char *, const char *); extern void put_pressure(struct membuffer *, pressure_t, const char *, const char *);
extern void put_salinity(struct membuffer *, int, const char *, const char *); extern void put_salinity(struct membuffer *, int, const char *, const char *);
extern void put_degrees(struct membuffer *b, degrees_t value, const char *, const char *); extern void put_degrees(struct membuffer *b, degrees_t value, const char *, const char *);
extern void put_location(struct membuffer *b, location_t *, const char *, const char *);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -97,8 +97,7 @@ static bool parseExif(QFile &f, struct metadata *metadata)
easyexif::EXIFInfo exif; easyexif::EXIFInfo exif;
if (exif.parseFromEXIFSegment(reinterpret_cast<const unsigned char *>(data.constData()), len) != PARSE_EXIF_SUCCESS) if (exif.parseFromEXIFSegment(reinterpret_cast<const unsigned char *>(data.constData()), len) != PARSE_EXIF_SUCCESS)
return false; return false;
metadata->longitude.udeg = lrint(1000000.0 * exif.GeoLocation.Longitude); metadata->location = create_location(exif.GeoLocation.Latitude, exif.GeoLocation.Longitude);
metadata->latitude.udeg = lrint(1000000.0 * exif.GeoLocation.Latitude);
metadata->timestamp = exif.epoch(); metadata->timestamp = exif.epoch();
return true; return true;
} }
@ -521,8 +520,8 @@ extern "C" mediatype_t get_metadata(const char *filename_in, metadata *data)
{ {
data->timestamp = 0; data->timestamp = 0;
data->duration.seconds = 0; data->duration.seconds = 0;
data->latitude.udeg = 0; data->location.lat.udeg = 0;
data->longitude.udeg = 0; data->location.lon.udeg = 0;
QString filename = localFilePath(QString(filename_in)); QString filename = localFilePath(QString(filename_in));
QFile f(filename); QFile f(filename);

View file

@ -6,8 +6,7 @@
struct metadata { struct metadata {
timestamp_t timestamp; timestamp_t timestamp;
duration_t duration; duration_t duration;
degrees_t latitude; location_t location;
degrees_t longitude;
}; };
enum mediatype_t { enum mediatype_t {

View file

@ -1066,7 +1066,7 @@ static int uddf_dive_match(struct dive *dive, const char *name, char *buf)
* We don't do exponentials etc, if somebody does * We don't do exponentials etc, if somebody does
* GPS locations in that format, they are insane. * GPS locations in that format, they are insane.
*/ */
degrees_t parse_degrees(char *buf, char **end) static degrees_t parse_degrees(char *buf, char **end)
{ {
int sign = 1, decimals = 6, value = 0; int sign = 1, decimals = 6, value = 0;
degrees_t ret; degrees_t ret;
@ -1112,86 +1112,90 @@ degrees_t parse_degrees(char *buf, char **end)
static void gps_lat(char *buffer, struct dive *dive) static void gps_lat(char *buffer, struct dive *dive)
{ {
char *end; char *end;
degrees_t latitude = parse_degrees(buffer, &end); location_t location = { };
struct dive_site *ds = get_dive_site_for_dive(dive); struct dive_site *ds = get_dive_site_for_dive(dive);
location.lat = parse_degrees(buffer, &end);
if (!ds) { if (!ds) {
dive->dive_site_uuid = create_dive_site_with_gps(NULL, latitude, (degrees_t){0}, dive->when); dive->dive_site_uuid = create_dive_site_with_gps(NULL, &location, dive->when);
} else { } else {
if (ds->latitude.udeg && ds->latitude.udeg != latitude.udeg) if (ds->location.lat.udeg && ds->location.lat.udeg != location.lat.udeg)
fprintf(stderr, "Oops, changing the latitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)"); fprintf(stderr, "Oops, changing the latitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)");
ds->latitude = latitude; ds->location.lat = location.lat;
} }
} }
static void gps_long(char *buffer, struct dive *dive) static void gps_long(char *buffer, struct dive *dive)
{ {
char *end; char *end;
degrees_t longitude = parse_degrees(buffer, &end); location_t location = { };
struct dive_site *ds = get_dive_site_for_dive(dive); struct dive_site *ds = get_dive_site_for_dive(dive);
location.lon = parse_degrees(buffer, &end);
if (!ds) { if (!ds) {
dive->dive_site_uuid = create_dive_site_with_gps(NULL, (degrees_t){0}, longitude, dive->when); dive->dive_site_uuid = create_dive_site_with_gps(NULL, &location, dive->when);
} else { } else {
if (ds->longitude.udeg && ds->longitude.udeg != longitude.udeg) if (ds->location.lon.udeg && ds->location.lon.udeg != location.lon.udeg)
fprintf(stderr, "Oops, changing the longitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)"); fprintf(stderr, "Oops, changing the longitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)");
ds->longitude = longitude; ds->location.lon = location.lon;
} }
} }
static void gps_location(char *buffer, struct dive_site *ds) /* We allow either spaces or a comma between the decimal degrees */
void parse_location(char *buffer, location_t *loc)
{ {
char *end; char *end;
loc->lat = parse_degrees(buffer, &end);
if (*end == ',') end++;
loc->lon = parse_degrees(end, &end);
}
ds->latitude = parse_degrees(buffer, &end); static void gps_location(char *buffer, struct dive_site *ds)
ds->longitude = parse_degrees(end, &end); {
parse_location(buffer, &ds->location);
} }
static void gps_in_dive(char *buffer, struct dive *dive) static void gps_in_dive(char *buffer, struct dive *dive)
{ {
char *end;
struct dive_site *ds = NULL; struct dive_site *ds = NULL;
degrees_t latitude = parse_degrees(buffer, &end); location_t location;
degrees_t longitude = parse_degrees(end, &end);
uint32_t uuid = dive->dive_site_uuid; uint32_t uuid = dive->dive_site_uuid;
parse_location(buffer, &location);
if (uuid == 0) { if (uuid == 0) {
// check if we have a dive site within 20 meters of that gps fix // check if we have a dive site within 20 meters of that gps fix
uuid = get_dive_site_uuid_by_gps_proximity(latitude, longitude, 20, &ds); uuid = get_dive_site_uuid_by_gps_proximity(&location, 20, &ds);
if (ds) { if (ds) {
// found a site nearby; in case it turns out this one had a different name let's // found a site nearby; in case it turns out this one had a different name let's
// remember the original coordinates so we can create the correct dive site later // remember the original coordinates so we can create the correct dive site later
cur_latitude = latitude; cur_location = location;
cur_longitude = longitude;
dive->dive_site_uuid = uuid; dive->dive_site_uuid = uuid;
} else { } else {
dive->dive_site_uuid = create_dive_site_with_gps("", latitude, longitude, dive->when); dive->dive_site_uuid = create_dive_site_with_gps("", &location, dive->when);
ds = get_dive_site_by_uuid(dive->dive_site_uuid); ds = get_dive_site_by_uuid(dive->dive_site_uuid);
} }
} else { } else {
ds = get_dive_site_by_uuid(uuid); ds = get_dive_site_by_uuid(uuid);
if (dive_site_has_gps_location(ds) && if (dive_site_has_gps_location(ds) &&
(latitude.udeg != 0 || longitude.udeg != 0) && has_location(&location) && !same_location(&ds->location, &location)) {
(ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) {
// Houston, we have a problem // 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", 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, ds->location.lat.udeg / 1000000.0, ds->location.lon.udeg / 1000000.0,
latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); location.lat.udeg / 1000000.0, location.lon.udeg / 1000000.0);
const char *coords = printGPSCoords(latitude.udeg, longitude.udeg); const char *coords = printGPSCoords(&location);
ds->notes = add_to_string(ds->notes, translate("gettextFromC", "multiple GPS locations for this dive site; also %s\n"), coords); ds->notes = add_to_string(ds->notes, translate("gettextFromC", "multiple GPS locations for this dive site; also %s\n"), coords);
free((void *)coords); free((void *)coords);
} else { } else {
ds->latitude = latitude; ds->location = location;
ds->longitude = longitude;
} }
} }
} }
static void gps_picture_location(char *buffer, struct picture *pic) static void gps_picture_location(char *buffer, struct picture *pic)
{ {
char *end; parse_location(buffer, &pic->location);
pic->latitude = parse_degrees(buffer, &end);
pic->longitude = parse_degrees(end, &end);
} }
/* We're in the top-level dive xml. Try to convert whatever value to a dive value */ /* We're in the top-level dive xml. Try to convert whatever value to a dive value */
@ -2100,9 +2104,9 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *tabl
break; break;
case 4: case 4:
/* Measure GPS */ /* Measure GPS */
cur_latitude.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 0)); cur_location.lat.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 0));
cur_longitude.udeg = (int)((ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0)); cur_location.lon.udeg = (int)((ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0));
cur_dive->dive_site_uuid = create_dive_site_with_gps("DLF imported", cur_latitude, cur_longitude, cur_dive->when); cur_dive->dive_site_uuid = create_dive_site_with_gps("DLF imported", &cur_location, cur_dive->when);
break; break;
default: default:
break; break;

View file

@ -22,7 +22,7 @@ struct parser_settings cur_settings;
struct divecomputer *cur_dc = NULL; struct divecomputer *cur_dc = NULL;
struct dive *cur_dive = NULL; struct dive *cur_dive = NULL;
struct dive_site *cur_dive_site = NULL; struct dive_site *cur_dive_site = NULL;
degrees_t cur_latitude, cur_longitude; location_t cur_location;
dive_trip_t *cur_trip = NULL; dive_trip_t *cur_trip = NULL;
struct sample *cur_sample = NULL; struct sample *cur_sample = NULL;
struct picture *cur_picture = NULL; struct picture *cur_picture = NULL;
@ -258,8 +258,8 @@ void dive_end(void)
record_dive_to_table(cur_dive, target_table); record_dive_to_table(cur_dive, target_table);
cur_dive = NULL; cur_dive = NULL;
cur_dc = NULL; cur_dc = NULL;
cur_latitude.udeg = 0; cur_location.lat.udeg = 0;
cur_longitude.udeg = 0; cur_location.lon.udeg = 0;
cur_cylinder_index = 0; cur_cylinder_index = 0;
cur_ws_index = 0; cur_ws_index = 0;
} }
@ -442,19 +442,17 @@ void add_dive_site(char *ds_name, struct dive *dive)
// but wait, we could have gotten this one based on GPS coords and could // but wait, we could have gotten this one based on GPS coords and could
// have had two different names for the same site... so let's search the other // have had two different names for the same site... so let's search the other
// way around // way around
uint32_t exact_match_uuid = get_dive_site_uuid_by_gps_and_name(buffer, ds->latitude, ds->longitude); uint32_t exact_match_uuid = get_dive_site_uuid_by_gps_and_name(buffer, &ds->location);
if (exact_match_uuid) { if (exact_match_uuid) {
dive->dive_site_uuid = exact_match_uuid; dive->dive_site_uuid = exact_match_uuid;
} else { } else {
dive->dive_site_uuid = create_dive_site(buffer, dive->when); dive->dive_site_uuid = create_dive_site(buffer, dive->when);
struct dive_site *newds = get_dive_site_by_uuid(dive->dive_site_uuid); struct dive_site *newds = get_dive_site_by_uuid(dive->dive_site_uuid);
if (cur_latitude.udeg || cur_longitude.udeg) { if (has_location(&cur_location)) {
// we started this uuid with GPS data, so lets use those // we started this uuid with GPS data, so lets use those
newds->latitude = cur_latitude; newds->location = cur_location;
newds->longitude = cur_longitude;
} else { } else {
newds->latitude = ds->latitude; newds->location = ds->location;
newds->longitude = ds->longitude;
} }
newds->notes = add_to_string(newds->notes, translate("gettextFromC", "additional name for site: %s\n"), ds->name); newds->notes = add_to_string(newds->notes, translate("gettextFromC", "additional name for site: %s\n"), ds->name);
} }

View file

@ -18,7 +18,7 @@ extern event_allocation_t event_allocation;
extern struct divecomputer *cur_dc; extern struct divecomputer *cur_dc;
extern struct dive *cur_dive; extern struct dive *cur_dive;
extern struct dive_site *cur_dive_site; extern struct dive_site *cur_dive_site;
extern degrees_t cur_latitude, cur_longitude; extern location_t cur_location;
extern dive_trip_t *cur_trip; extern dive_trip_t *cur_trip;
extern struct sample *cur_sample; extern struct sample *cur_sample;
extern struct picture *cur_picture; extern struct picture *cur_picture;

View file

@ -75,14 +75,16 @@ QString distance_string(int distanceInMeters)
return str; return str;
} }
extern "C" const char *printGPSCoords(int lat, int lon) extern "C" const char *printGPSCoords(const location_t *loc)
{ {
int lat = loc->lat.udeg;
int lon = loc->lon.udeg;
unsigned int latdeg, londeg; unsigned int latdeg, londeg;
unsigned int latmin, lonmin; unsigned int latmin, lonmin;
double latsec, lonsec; double latsec, lonsec;
QString lath, lonh, result; QString lath, lonh, result;
if (!lat && !lon) if (!has_location(loc))
return strdup(""); return strdup("");
if (prefs.coordinates_traditional) { if (prefs.coordinates_traditional) {
@ -247,30 +249,24 @@ bool parseGpsText(const QString &gps_text, double *latitude, double *longitude)
#if 0 // we'll need something like this for the dive site management, eventually #if 0 // we'll need something like this for the dive site management, eventually
bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out) bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out)
{ {
double latitude, longitude; location_t location;
int latudeg, longudeg;
bool ignore; bool ignore;
bool *parsed = parsed_out ?: &ignore; bool *parsed = parsed_out ?: &ignore;
*parsed = true; *parsed = true;
/* if we have a master and the dive's gps address is different from it, /* if we have a master and the dive's gps address is different from it,
* don't change the dive */ * don't change the dive */
if (master && (master->latitude.udeg != dive->latitude.udeg || if (master && !same_location(&master->location, &dive->location))
master->longitude.udeg != dive->longitude.udeg))
return false; return false;
if (!(*parsed = parseGpsText(gps_text, &latitude, &longitude))) if (!(*parsed = parseGpsText(gps_text, location)))
return false; return false;
latudeg = lrint(1000000 * latitude);
longudeg = lrint(1000000 * longitude);
/* if dive gps didn't change, nothing changed */ /* if dive gps didn't change, nothing changed */
if (dive->latitude.udeg == latudeg && dive->longitude.udeg == longudeg) if (same_location(&dive->location, location))
return false; return false;
/* ok, update the dive and mark things changed */ /* ok, update the dive and mark things changed */
dive->latitude.udeg = latudeg; dive->location = location;
dive->longitude.udeg = longudeg;
return true; return true;
} }
#endif #endif

View file

@ -124,7 +124,7 @@ void moveInVector(Vector &v, int rangeBegin, int rangeEnd, int destination)
extern "C" { extern "C" {
#endif #endif
const char *printGPSCoords(int lat, int lon); const char *printGPSCoords(const location_t *loc);
bool in_planner(); bool in_planner();
bool getProxyString(char **buffer); bool getProxyString(char **buffer);
bool canReachCloudServer(); bool canReachCloudServer();

View file

@ -38,14 +38,6 @@ static void cond_put_format(int cond, struct membuffer *b, const char *fmt, ...)
#define SAVE(str, x) cond_put_format(dive->x, b, str " %d\n", dive->x) #define SAVE(str, x) cond_put_format(dive->x, b, str " %d\n", dive->x)
static void show_gps(struct membuffer *b, degrees_t latitude, degrees_t longitude)
{
if (latitude.udeg || longitude.udeg) {
put_degrees(b, latitude, "gps ", " ");
put_degrees(b, longitude, "", "\n");
}
}
static void quote(struct membuffer *b, const char *text) static void quote(struct membuffer *b, const char *text)
{ {
const char *p = text; const char *p = text;
@ -613,7 +605,7 @@ static int save_one_picture(git_repository *repo, struct dir *dir, struct pictur
unsigned h; unsigned h;
show_utf8(&buf, "filename ", pic->filename, "\n"); show_utf8(&buf, "filename ", pic->filename, "\n");
show_gps(&buf, pic->latitude, pic->longitude); put_location(&buf, &pic->location, "gps ", "\n");
/* Picture loading will load even negative offsets.. */ /* Picture loading will load even negative offsets.. */
if (offset < 0) { if (offset < 0) {
@ -921,7 +913,7 @@ static void save_divesites(git_repository *repo, struct dir *tree)
show_utf8(&b, "name ", ds->name, "\n"); show_utf8(&b, "name ", ds->name, "\n");
show_utf8(&b, "description ", ds->description, "\n"); show_utf8(&b, "description ", ds->description, "\n");
show_utf8(&b, "notes ", ds->notes, "\n"); show_utf8(&b, "notes ", ds->notes, "\n");
show_gps(&b, ds->latitude, ds->longitude); put_location(&b, &ds->location, "gps ", "\n");
for (int j = 0; j < ds->taxonomy.nr; j++) { for (int j = 0; j < ds->taxonomy.nr; j++) {
struct taxonomy *t = &ds->taxonomy.category[j]; struct taxonomy *t = &ds->taxonomy.category[j];
if (t->category != TC_NONE && t->value) { if (t->category != TC_NONE && t->value) {

View file

@ -191,8 +191,8 @@ void put_HTML_coordinates(struct membuffer *b, struct dive *dive)
struct dive_site *ds = get_dive_site_for_dive(dive); struct dive_site *ds = get_dive_site_for_dive(dive);
if (!ds) if (!ds)
return; return;
degrees_t latitude = ds->latitude; degrees_t latitude = ds->location.lat;
degrees_t longitude = ds->longitude; degrees_t longitude = ds->location.lon;
//don't put coordinates if in (0,0) //don't put coordinates if in (0,0)
if (!latitude.udeg && !longitude.udeg) if (!latitude.udeg && !longitude.udeg)

View file

@ -464,10 +464,7 @@ static void save_picture(struct membuffer *b, struct picture *pic)
} }
put_format(b, " offset='%c%u:%02u min'", sign, FRACTION(offset, 60)); put_format(b, " offset='%c%u:%02u min'", sign, FRACTION(offset, 60));
} }
if (pic->latitude.udeg || pic->longitude.udeg) { put_location(b, &pic->location, " gps='","'");
put_degrees(b, pic->latitude, " gps='", " ");
put_degrees(b, pic->longitude, "", "'");
}
put_string(b, "/>\n"); put_string(b, "/>\n");
} }
@ -630,10 +627,7 @@ void save_dives_buffer(struct membuffer *b, const bool select_only, bool anonymi
put_format(b, "<site uuid='%8x'", ds->uuid); put_format(b, "<site uuid='%8x'", ds->uuid);
show_utf8_blanked(b, ds->name, " name='", "'", 1, anonymize); show_utf8_blanked(b, ds->name, " name='", "'", 1, anonymize);
if (ds->latitude.udeg || ds->longitude.udeg) { put_location(b, &ds->location, " gps='", "'");
put_degrees(b, ds->latitude, " gps='", " ");
put_degrees(b, ds->longitude, "", "'");
}
show_utf8_blanked(b, ds->description, " description='", "'", 1, anonymize); show_utf8_blanked(b, ds->description, " description='", "'", 1, anonymize);
put_format(b, ">\n"); put_format(b, ">\n");
show_utf8_blanked(b, ds->notes, " <notes>", " </notes>\n", 0, anonymize); show_utf8_blanked(b, ds->notes, " <notes>", " </notes>\n", 0, anonymize);

View file

@ -108,7 +108,7 @@ QString DiveObjectHelper::location() const
QString DiveObjectHelper::gps() const QString DiveObjectHelper::gps() const
{ {
struct dive_site *ds = get_dive_site_by_uuid(m_dive->dive_site_uuid); struct dive_site *ds = get_dive_site_by_uuid(m_dive->dive_site_uuid);
return ds ? QString(printGPSCoords(ds->latitude.udeg, ds->longitude.udeg)) : QString(); return ds ? QString(printGPSCoords(&ds->location)) : QString();
} }
QString DiveObjectHelper::gps_decimal() const QString DiveObjectHelper::gps_decimal() const

View file

@ -173,8 +173,7 @@ void uemis_set_divelocation(int divespot, char *text, double longitude, double l
struct dive_site *ds = get_dive_site_by_uuid(hp->dive_site_uuid); struct dive_site *ds = get_dive_site_by_uuid(hp->dive_site_uuid);
if (ds) { if (ds) {
ds->name = strdup(text); ds->name = strdup(text);
ds->longitude.udeg = lrint(longitude * 1000000); ds->location = create_location(latitude, longitude);
ds->latitude.udeg = lrint(latitude * 1000000);
} }
} }
hp = hp->next; hp = hp->next;

View file

@ -134,6 +134,29 @@ typedef struct
int udeg; int udeg;
} degrees_t; } degrees_t;
typedef struct pos {
degrees_t lat, lon;
} location_t;
static inline bool has_location(const location_t *loc)
{
return loc->lat.udeg || loc->lon.udeg;
}
static inline bool same_location(const location_t *a, const location_t *b)
{
return (a->lat.udeg == b->lat.udeg) && (a->lon.udeg == b->lon.udeg);
}
static inline location_t create_location(double lat, double lon)
{
location_t location = {
{ (int) lrint(lat * 1000000) },
{ (int) lrint(lon * 1000000) }
};
return location;
}
static inline double udeg_to_radians(int udeg) static inline double udeg_to_radians(int udeg)
{ {
return (udeg * M_PI) / (1000000.0 * 180.0); return (udeg * M_PI) / (1000000.0 * 180.0);

View file

@ -35,8 +35,8 @@ void writeMarkers(struct membuffer *b, const bool selected_only)
struct dive_site *ds = get_dive_site_for_dive(dive); struct dive_site *ds = get_dive_site_for_dive(dive);
if (!ds || !dive_site_has_gps_location(ds)) if (!ds || !dive_site_has_gps_location(ds))
continue; continue;
put_degrees(b, ds->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", ""); put_degrees(b, ds->location.lat, "temp = new google.maps.Marker({position: new google.maps.LatLng(", "");
put_degrees(b, ds->longitude, ",", ")});\n"); put_degrees(b, ds->location.lon, ",", ")});\n");
put_string(b, "markers.push(temp);\ntempinfowindow = new google.maps.InfoWindow({content: '<div id=\"content\">'+'<div id=\"siteNotice\">'+'</div>'+'<div id=\"bodyContent\">"); put_string(b, "markers.push(temp);\ntempinfowindow = new google.maps.InfoWindow({content: '<div id=\"content\">'+'<div id=\"siteNotice\">'+'</div>'+'<div id=\"bodyContent\">");
snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Date:")); snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Date:"));
put_HTML_date(b, dive, pre, "</p>"); put_HTML_date(b, dive, pre, "</p>");

View file

@ -315,8 +315,8 @@ void DiveLogExportDialog::export_TeX(const char *filename, const bool selected_o
put_format(&buf, "\\def\\place{%s}\n", site ? site->name : ""); put_format(&buf, "\\def\\place{%s}\n", site ? site->name : "");
put_format(&buf, "\\def\\spot{}\n"); put_format(&buf, "\\def\\spot{}\n");
put_format(&buf, "\\def\\sitename{%s}\n", site ? site->name : ""); put_format(&buf, "\\def\\sitename{%s}\n", site ? site->name : "");
site ? put_format(&buf, "\\def\\gpslat{%f}\n", site->latitude.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslat{}\n"); site ? put_format(&buf, "\\def\\gpslat{%f}\n", site->location.lat.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslat{}\n");
site ? put_format(&buf, "\\def\\gpslon{%f}\n", site->longitude.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslon{}\n"); site ? put_format(&buf, "\\def\\gpslon{%f}\n", site->location.lon.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslon{}\n");
put_format(&buf, "\\def\\computer{%s}\n", dive->dc.model); put_format(&buf, "\\def\\computer{%s}\n", dive->dc.model);
put_format(&buf, "\\def\\country{%s}\n", qPrintable(country)); put_format(&buf, "\\def\\country{%s}\n", qPrintable(country));
put_format(&buf, "\\def\\time{%u:%02u}\n", FRACTION(dive->duration.seconds, 60)); put_format(&buf, "\\def\\time{%u:%02u}\n", FRACTION(dive->duration.seconds, 60));

View file

@ -116,8 +116,8 @@ void LocationInformationWidget::updateLabels()
ui.diveSiteNotes->setPlainText(diveSite->notes); ui.diveSiteNotes->setPlainText(diveSite->notes);
else else
ui.diveSiteNotes->clear(); ui.diveSiteNotes->clear();
if (diveSite->latitude.udeg || diveSite->longitude.udeg) { if (has_location(&diveSite->location)) {
const char *coords = printGPSCoords(diveSite->latitude.udeg, diveSite->longitude.udeg); const char *coords = printGPSCoords(&diveSite->location);
ui.diveSiteCoordinates->setText(coords); ui.diveSiteCoordinates->setText(coords);
free((void *)coords); free((void *)coords);
} else { } else {
@ -137,12 +137,13 @@ void LocationInformationWidget::clearLabels()
ui.locationTags->clear(); ui.locationTags->clear();
} }
void LocationInformationWidget::updateGpsCoordinates(degrees_t latitude, degrees_t longitude) void LocationInformationWidget::updateGpsCoordinates(const location_t &location)
{ {
QString oldText = ui.diveSiteCoordinates->text(); QString oldText = ui.diveSiteCoordinates->text();
const char *coords = printGPSCoords(latitude.udeg, longitude.udeg);
const char *coords = printGPSCoords(&location);
ui.diveSiteCoordinates->setText(coords); ui.diveSiteCoordinates->setText(coords);
enableLocationButtons(latitude.udeg || longitude.udeg); enableLocationButtons(has_location(&location));
free((void *)coords); free((void *)coords);
if (oldText != ui.diveSiteCoordinates->text()) if (oldText != ui.diveSiteCoordinates->text())
markChangedWidget(ui.diveSiteCoordinates); markChangedWidget(ui.diveSiteCoordinates);
@ -150,12 +151,11 @@ void LocationInformationWidget::updateGpsCoordinates(degrees_t latitude, degrees
// Parse GPS text into latitude and longitude. // Parse GPS text into latitude and longitude.
// On error, false is returned and the output parameters are left unmodified. // On error, false is returned and the output parameters are left unmodified.
bool parseGpsText(const QString &text, degrees_t &latitude, degrees_t &longitude) bool parseGpsText(const QString &text, location_t &location)
{ {
double lat, lon; double lat, lon;
if (parseGpsText(text, &lat, &lon)) { if (parseGpsText(text, &lat, &lon)) {
latitude.udeg = lrint(lat * 1000000.0); location = create_location(lat, lon);
longitude.udeg = lrint(lon * 1000000.0);
return true; return true;
} }
return false; return false;
@ -204,7 +204,7 @@ void LocationInformationWidget::acceptChanges()
} }
if (!ui.diveSiteCoordinates->text().isEmpty()) if (!ui.diveSiteCoordinates->text().isEmpty())
parseGpsText(ui.diveSiteCoordinates->text(), diveSite->latitude, diveSite->longitude); parseGpsText(ui.diveSiteCoordinates->text(), diveSite->location);
if (dive_site_is_empty(diveSite)) { if (dive_site_is_empty(diveSite)) {
LocationInformationModel::instance()->removeRow(get_divesite_idx(diveSite)); LocationInformationModel::instance()->removeRow(get_divesite_idx(diveSite));
displayed_dive.dive_site_uuid = 0; displayed_dive.dive_site_uuid = 0;
@ -224,7 +224,7 @@ void LocationInformationWidget::initFields(dive_site *ds)
diveSite = ds; diveSite = ds;
if (ds) { if (ds) {
copy_taxonomy(&ds->taxonomy, &taxonomy); copy_taxonomy(&ds->taxonomy, &taxonomy);
filter_model.set(ds->uuid, ds->latitude, ds->longitude); filter_model.set(ds->uuid, ds->location);
updateLabels(); updateLabels();
enableLocationButtons(dive_site_has_gps_location(ds)); enableLocationButtons(dive_site_has_gps_location(ds));
QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel *>(ui.diveSiteListView->model()); QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel *>(ui.diveSiteListView->model());
@ -233,7 +233,7 @@ void LocationInformationWidget::initFields(dive_site *ds)
m->invalidate(); m->invalidate();
} else { } else {
free_taxonomy(&taxonomy); free_taxonomy(&taxonomy);
filter_model.set(0, degrees_t{ 0 }, degrees_t{ 0 }); filter_model.set(0, location_t { degrees_t{ 0 }, degrees_t{ 0 } });
clearLabels(); clearLabels();
} }
MapWidget::instance()->prepareForGetDiveCoordinates(ds ? ds->uuid : 0); MapWidget::instance()->prepareForGetDiveCoordinates(ds ? ds->uuid : 0);
@ -276,14 +276,14 @@ void LocationInformationWidget::on_diveSiteCoordinates_textChanged(const QString
{ {
if (!diveSite) if (!diveSite)
return; return;
degrees_t latitude, longitude; location_t location;
bool ok_old = diveSite->latitude.udeg || diveSite->longitude.udeg; bool ok_old = has_location(&diveSite->location);
bool ok = parseGpsText(text, latitude, longitude); bool ok = parseGpsText(text, location);
if (ok != ok_old || latitude.udeg != diveSite->latitude.udeg || longitude.udeg != diveSite->longitude.udeg) { if (ok != ok_old || !same_location(&location, &diveSite->location)) {
if (ok) { if (ok) {
markChangedWidget(ui.diveSiteCoordinates); markChangedWidget(ui.diveSiteCoordinates);
enableLocationButtons(true); enableLocationButtons(true);
filter_model.setCoordinates(latitude, longitude); filter_model.setCoordinates(location);
} else { } else {
enableLocationButtons(false); enableLocationButtons(false);
} }
@ -326,10 +326,10 @@ void LocationInformationWidget::resetPallete()
void LocationInformationWidget::reverseGeocode() void LocationInformationWidget::reverseGeocode()
{ {
degrees_t latitude, longitude; location_t location;
if (!parseGpsText(ui.diveSiteCoordinates->text(), latitude, longitude)) if (!parseGpsText(ui.diveSiteCoordinates->text(), location))
return; return;
reverseGeoLookup(latitude, longitude, &taxonomy); reverseGeoLookup(location.lat, location.lon, &taxonomy);
ui.locationTags->setText(constructLocationTags(&taxonomy, false)); ui.locationTags->setText(constructLocationTags(&taxonomy, false));
} }
@ -337,11 +337,11 @@ void LocationInformationWidget::updateLocationOnMap()
{ {
if (!diveSite) if (!diveSite)
return; return;
degrees_t latitude, longitude; location_t location;
if (!parseGpsText(ui.diveSiteCoordinates->text(), latitude, longitude)) if (!parseGpsText(ui.diveSiteCoordinates->text(), location))
return; return;
MapWidget::instance()->updateDiveSiteCoordinates(diveSite->uuid, latitude, longitude); MapWidget::instance()->updateDiveSiteCoordinates(diveSite->uuid, location);
filter_model.setCoordinates(latitude, longitude); filter_model.setCoordinates(location);
} }
DiveLocationFilterProxyModel::DiveLocationFilterProxyModel(QObject*) DiveLocationFilterProxyModel::DiveLocationFilterProxyModel(QObject*)

View file

@ -24,7 +24,7 @@ protected:
public slots: public slots:
void acceptChanges(); void acceptChanges();
void rejectChanges(); void rejectChanges();
void updateGpsCoordinates(degrees_t latitude, degrees_t longitude); void updateGpsCoordinates(const location_t &);
void markChangedWidget(QWidget *w); void markChangedWidget(QWidget *w);
void enableEdition(); void enableEdition();
void resetState(); void resetState();

View file

@ -109,16 +109,16 @@ void MapWidget::selectedDivesChanged(QList<int> list)
skipReload = false; skipReload = false;
} }
void MapWidget::coordinatesChangedLocal(degrees_t latitude, degrees_t longitude) void MapWidget::coordinatesChangedLocal(const location_t &location)
{ {
CHECK_IS_READY_RETURN_VOID(); CHECK_IS_READY_RETURN_VOID();
emit coordinatesChanged(latitude, longitude); emit coordinatesChanged(location);
} }
void MapWidget::updateDiveSiteCoordinates(uint32_t uuid, degrees_t latitude, degrees_t longitude) void MapWidget::updateDiveSiteCoordinates(uint32_t uuid, const location_t &location)
{ {
CHECK_IS_READY_RETURN_VOID(); CHECK_IS_READY_RETURN_VOID();
m_mapHelper->updateDiveSiteCoordinates(uuid, latitude, longitude); m_mapHelper->updateDiveSiteCoordinates(uuid, location);
} }
MapWidget::~MapWidget() MapWidget::~MapWidget()

View file

@ -25,7 +25,7 @@ public:
void reload(); void reload();
signals: signals:
void coordinatesChanged(degrees_t latitude, degrees_t longitude); void coordinatesChanged(const location_t &);
public slots: public slots:
void centerOnSelectedDiveSite(); void centerOnSelectedDiveSite();
@ -35,9 +35,9 @@ public slots:
void repopulateLabels(); void repopulateLabels();
void prepareForGetDiveCoordinates(uint32_t uuid); void prepareForGetDiveCoordinates(uint32_t uuid);
void selectedDivesChanged(QList<int>); void selectedDivesChanged(QList<int>);
void coordinatesChangedLocal(degrees_t latitude, degrees_t longitude); void coordinatesChangedLocal(const location_t &);
void doneLoading(QQuickWidget::Status status); void doneLoading(QQuickWidget::Status status);
void updateDiveSiteCoordinates(uint32_t uuid, degrees_t latitude, degrees_t longitude); void updateDiveSiteCoordinates(uint32_t uuid, const location_t &);
private: private:
static MapWidget *m_instance; static MapWidget *m_instance;

View file

@ -479,7 +479,7 @@ void LocationFilterDelegate::paint(QPainter *painter, const QStyleOptionViewItem
} }
if (bottomText.isEmpty()) { if (bottomText.isEmpty()) {
const char *gpsCoords = printGPSCoords(ds->latitude.udeg, ds->longitude.udeg); const char *gpsCoords = printGPSCoords(&ds->location);
bottomText = QString(gpsCoords); bottomText = QString(gpsCoords);
free( (void*) gpsCoords); free( (void*) gpsCoords);
} }
@ -487,11 +487,10 @@ void LocationFilterDelegate::paint(QPainter *painter, const QStyleOptionViewItem
if (dive_site_has_gps_location(ds) && currentDiveSiteHasGPS) { if (dive_site_has_gps_location(ds) && currentDiveSiteHasGPS) {
// so we are showing a completion and both the current dive site and the completion // so we are showing a completion and both the current dive site and the completion
// have a GPS fix... so let's show the distance // have a GPS fix... so let's show the distance
if (ds->latitude.udeg == currentDiveSite->latitude.udeg && if (same_location(&ds->location, &currentDiveSite->location)) {
ds->longitude.udeg == currentDiveSite->longitude.udeg) {
bottomText += tr(" (same GPS fix)"); bottomText += tr(" (same GPS fix)");
} else { } else {
int distanceMeters = get_distance(ds->latitude, ds->longitude, currentDiveSite->latitude, currentDiveSite->longitude); int distanceMeters = get_distance(&ds->location, &currentDiveSite->location);
QString distance = distance_string(distanceMeters); QString distance = distance_string(distanceMeters);
int nr = nr_of_dives_at_dive_site(ds->uuid, false); int nr = nr_of_dives_at_dive_site(ds->uuid, false);
bottomText += tr(" (~%1 away").arg(distance); bottomText += tr(" (~%1 away").arg(distance);

View file

@ -204,10 +204,7 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile,
put_format(&mb, "<divelog><divesites><site uuid='%8x' name='", dive->dive_site_uuid); put_format(&mb, "<divelog><divesites><site uuid='%8x' name='", dive->dive_site_uuid);
put_quoted(&mb, ds->name, 1, 0); put_quoted(&mb, ds->name, 1, 0);
put_format(&mb, "'"); put_format(&mb, "'");
if (ds->latitude.udeg || ds->longitude.udeg) { put_location(&mb, &ds->location, " gps='", "'");
put_degrees(&mb, ds->latitude, " gps='", " ");
put_degrees(&mb, ds->longitude, "", "'");
}
put_format(&mb, ">\n"); put_format(&mb, ">\n");
if (ds->taxonomy.nr) { if (ds->taxonomy.nr) {
for (int j = 0; j < ds->taxonomy.nr; j++) { for (int j = 0; j < ds->taxonomy.nr; j++) {

View file

@ -696,9 +696,8 @@ uint32_t MainTab::updateDiveSite(uint32_t pickedUuid, dive *d)
newDs->name = copy_qstring(ui.location->text()); newDs->name = copy_qstring(ui.location->text());
newDs->uuid = pickedUuid; newDs->uuid = pickedUuid;
qDebug() << "Creating and copying dive site"; qDebug() << "Creating and copying dive site";
} else if (newDs->latitude.udeg == 0 && newDs->longitude.udeg == 0) { } else if (!has_location(&newDs->location)) {
newDs->latitude.udeg = origDs->latitude.udeg; newDs->location = origDs->location;
newDs->longitude.udeg = origDs->longitude.udeg;
qDebug() << "Copying GPS information"; qDebug() << "Copying GPS information";
} }
} }

View file

@ -28,7 +28,7 @@ QGeoCoordinate MapWidgetHelper::getCoordinatesForUUID(QVariant dive_site_uuid)
struct dive_site *ds = get_dive_site_by_uuid(uuid); struct dive_site *ds = get_dive_site_by_uuid(uuid);
if (!ds || !dive_site_has_gps_location(ds)) if (!ds || !dive_site_has_gps_location(ds))
return QGeoCoordinate(0.0, 0.0); return QGeoCoordinate(0.0, 0.0);
return QGeoCoordinate(ds->latitude.udeg * 0.000001, ds->longitude.udeg * 0.000001); return QGeoCoordinate(ds->location.lat.udeg * 0.000001, ds->location.lon.udeg * 0.000001);
} }
void MapWidgetHelper::centerOnDiveSiteUUID(QVariant dive_site_uuid) void MapWidgetHelper::centerOnDiveSiteUUID(QVariant dive_site_uuid)
@ -48,7 +48,7 @@ void MapWidgetHelper::centerOnDiveSite(struct dive_site *ds)
} else { } else {
// dive site with GPS // dive site with GPS
m_mapLocationModel->setSelectedUuid(ds->uuid, false); m_mapLocationModel->setSelectedUuid(ds->uuid, false);
QGeoCoordinate dsCoord (ds->latitude.udeg * 0.000001, ds->longitude.udeg * 0.000001); QGeoCoordinate dsCoord (ds->location.lat.udeg * 0.000001, ds->location.lon.udeg * 0.000001);
QMetaObject::invokeMethod(m_map, "centerOnCoordinate", Q_ARG(QVariant, QVariant::fromValue(dsCoord))); QMetaObject::invokeMethod(m_map, "centerOnCoordinate", Q_ARG(QVariant, QVariant::fromValue(dsCoord)));
} }
} }
@ -68,8 +68,8 @@ void MapWidgetHelper::centerOnSelectedDiveSite()
continue; continue;
// only store dive sites with GPS // only store dive sites with GPS
selDS.append(dss); selDS.append(dss);
selGC.append(QGeoCoordinate(dss->latitude.udeg * 0.000001, selGC.append(QGeoCoordinate(dss->location.lat.udeg * 0.000001,
dss->longitude.udeg * 0.000001)); dss->location.lon.udeg * 0.000001));
} }
if (selDS.isEmpty()) { if (selDS.isEmpty()) {
@ -86,8 +86,8 @@ void MapWidgetHelper::centerOnSelectedDiveSite()
qreal minLat = 0.0, minLon = 0.0, maxLat = 0.0, maxLon = 0.0; qreal minLat = 0.0, minLon = 0.0, maxLat = 0.0, maxLon = 0.0;
bool start = true; bool start = true;
for(struct dive_site *dss: selDS) { for(struct dive_site *dss: selDS) {
qreal lat = dss->latitude.udeg * 0.000001; qreal lat = dss->location.lat.udeg * 0.000001;
qreal lon = dss->longitude.udeg * 0.000001; qreal lon = dss->location.lon.udeg * 0.000001;
if (start) { if (start) {
minLat = maxLat = lat; minLat = maxLat = lat;
minLon = maxLon = lon; minLon = maxLon = lon;
@ -133,8 +133,8 @@ void MapWidgetHelper::reloadMapLocations()
struct dive_site *ds = get_dive_site_for_dive(dive); struct dive_site *ds = get_dive_site_for_dive(dive);
if (!dive_site_has_gps_location(ds) || locationUuids.contains(ds->uuid)) if (!dive_site_has_gps_location(ds) || locationUuids.contains(ds->uuid))
continue; continue;
latitude = ds->latitude.udeg * 0.000001; latitude = ds->location.lat.udeg * 0.000001;
longitude = ds->longitude.udeg * 0.000001; longitude = ds->location.lon.udeg * 0.000001;
QGeoCoordinate dsCoord(latitude, longitude); QGeoCoordinate dsCoord(latitude, longitude);
QString name(ds->name); QString name(ds->name);
// don't add dive locations with the same name, unless they are // don't add dive locations with the same name, unless they are
@ -164,8 +164,8 @@ void MapWidgetHelper::selectedLocationChanged(MapLocation *location)
if (!dive_site_has_gps_location(ds)) if (!dive_site_has_gps_location(ds))
continue; continue;
#ifndef SUBSURFACE_MOBILE #ifndef SUBSURFACE_MOBILE
const qreal latitude = ds->latitude.udeg * 0.000001; const qreal latitude = ds->location.lat.udeg * 0.000001;
const qreal longitude = ds->longitude.udeg * 0.000001; const qreal longitude = ds->location.lon.udeg * 0.000001;
QGeoCoordinate dsCoord(latitude, longitude); QGeoCoordinate dsCoord(latitude, longitude);
if (locationCoord.distanceTo(dsCoord) < m_smallCircleRadius) if (locationCoord.distanceTo(dsCoord) < m_smallCircleRadius)
m_selectedDiveIds.append(idx); m_selectedDiveIds.append(idx);
@ -194,8 +194,8 @@ void MapWidgetHelper::selectVisibleLocations()
struct dive_site *ds = get_dive_site_for_dive(dive); struct dive_site *ds = get_dive_site_for_dive(dive);
if (!dive_site_has_gps_location(ds)) if (!dive_site_has_gps_location(ds))
continue; continue;
const qreal latitude = ds->latitude.udeg * 0.000001; const qreal latitude = ds->location.lat.udeg * 0.000001;
const qreal longitude = ds->longitude.udeg * 0.000001; const qreal longitude = ds->location.lon.udeg * 0.000001;
QGeoCoordinate dsCoord(latitude, longitude); QGeoCoordinate dsCoord(latitude, longitude);
QPointF point; QPointF point;
QMetaObject::invokeMethod(m_map, "fromCoordinate", Q_RETURN_ARG(QPointF, point), QMetaObject::invokeMethod(m_map, "fromCoordinate", Q_RETURN_ARG(QPointF, point),
@ -247,14 +247,17 @@ void MapWidgetHelper::calculateSmallCircleRadius(QGeoCoordinate coord)
m_smallCircleRadius = coord2.distanceTo(coord); m_smallCircleRadius = coord2.distanceTo(coord);
} }
static location_t mk_location(QGeoCoordinate coord)
{
return create_location(coord.latitude(), coord.longitude());
}
void MapWidgetHelper::copyToClipboardCoordinates(QGeoCoordinate coord, bool formatTraditional) void MapWidgetHelper::copyToClipboardCoordinates(QGeoCoordinate coord, bool formatTraditional)
{ {
bool savep = prefs.coordinates_traditional; bool savep = prefs.coordinates_traditional;
prefs.coordinates_traditional = formatTraditional; prefs.coordinates_traditional = formatTraditional;
location_t location = mk_location(coord);
const int lat = lrint(1000000.0 * coord.latitude()); const char *coordinates = printGPSCoords(&location);
const int lon = lrint(1000000.0 * coord.longitude());
const char *coordinates = printGPSCoords(lat, lon);
QApplication::clipboard()->setText(QString(coordinates), QClipboard::Clipboard); QApplication::clipboard()->setText(QString(coordinates), QClipboard::Clipboard);
free((void *)coordinates); free((void *)coordinates);
@ -266,14 +269,14 @@ void MapWidgetHelper::updateCurrentDiveSiteCoordinatesFromMap(quint32 uuid, QGeo
MapLocation *loc = m_mapLocationModel->getMapLocationForUuid(uuid); MapLocation *loc = m_mapLocationModel->getMapLocationForUuid(uuid);
if (loc) if (loc)
loc->setCoordinate(coord); loc->setCoordinate(coord);
emit coordinatesChanged(degrees_t { (int)lrint(coord.latitude() * 1000000.0) }, location_t location = mk_location(coord);
degrees_t { (int)lrint(coord.longitude() * 1000000.0) }); emit coordinatesChanged(location);
} }
void MapWidgetHelper::updateDiveSiteCoordinates(uint32_t uuid, degrees_t latitude, degrees_t longitude) void MapWidgetHelper::updateDiveSiteCoordinates(uint32_t uuid, const location_t &location)
{ {
const qreal latitude_r = latitude.udeg * 0.000001; const qreal latitude_r = location.lat.udeg * 0.000001;
const qreal longitude_r = longitude.udeg * 0.000001; const qreal longitude_r = location.lon.udeg * 0.000001;
QGeoCoordinate coord(latitude_r, longitude_r); QGeoCoordinate coord(latitude_r, longitude_r);
m_mapLocationModel->updateMapLocationCoordinates(uuid, coord); m_mapLocationModel->updateMapLocationCoordinates(uuid, coord);
QMetaObject::invokeMethod(m_map, "centerOnCoordinate", Q_ARG(QVariant, QVariant::fromValue(coord))); QMetaObject::invokeMethod(m_map, "centerOnCoordinate", Q_ARG(QVariant, QVariant::fromValue(coord)));
@ -303,8 +306,8 @@ void MapWidgetHelper::enterEditMode(quint32 uuid)
coord = exists->coordinate(); coord = exists->coordinate();
} }
centerOnDiveSiteUUID(uuid); centerOnDiveSiteUUID(uuid);
emit coordinatesChanged(degrees_t { (int)lrint(coord.latitude() * 1000000.0) }, location_t location = mk_location(coord);
degrees_t { (int)lrint(coord.longitude() * 1000000.0) }); emit coordinatesChanged(location);
emit editModeChanged(); emit editModeChanged();
} }

View file

@ -36,7 +36,7 @@ public:
Q_INVOKABLE void calculateSmallCircleRadius(QGeoCoordinate coord); Q_INVOKABLE void calculateSmallCircleRadius(QGeoCoordinate coord);
Q_INVOKABLE void updateCurrentDiveSiteCoordinatesFromMap(quint32 uuid, QGeoCoordinate coord); Q_INVOKABLE void updateCurrentDiveSiteCoordinatesFromMap(quint32 uuid, QGeoCoordinate coord);
Q_INVOKABLE void selectVisibleLocations(); Q_INVOKABLE void selectVisibleLocations();
void updateDiveSiteCoordinates(uint32_t uuid, degrees_t latitude, degrees_t longitude); void updateDiveSiteCoordinates(uint32_t uuid, const location_t &);
void enterEditMode(uint32_t uuid); void enterEditMode(uint32_t uuid);
void exitEditMode(); void exitEditMode();
QString pluginObject(); QString pluginObject();
@ -55,7 +55,7 @@ signals:
void modelChanged(); void modelChanged();
void editModeChanged(); void editModeChanged();
void selectedDivesChanged(QList<int> list); void selectedDivesChanged(QList<int> list);
void coordinatesChanged(degrees_t latitude, degrees_t longitude); void coordinatesChanged(const location_t &);
void pluginObjectChanged(); void pluginObjectChanged();
}; };

View file

@ -754,14 +754,11 @@ void QMLManager::refreshDiveList()
static void setupDivesite(struct dive *d, struct dive_site *ds, double lat, double lon, const char *locationtext) static void setupDivesite(struct dive *d, struct dive_site *ds, double lat, double lon, const char *locationtext)
{ {
location_t location = create_location(lat, lon);
if (ds) { if (ds) {
ds->latitude.udeg = lrint(lat * 1000000); ds->location = location;
ds->longitude.udeg = lrint(lon * 1000000);
} else { } else {
degrees_t latData, lonData; d->dive_site_uuid = create_dive_site_with_gps(locationtext, &location, d->when);
latData.udeg = lrint(lat * 1000000);
lonData.udeg = lrint(lon * 1000000);
d->dive_site_uuid = create_dive_site_with_gps(locationtext, latData, lonData, d->when);
} }
} }
@ -1481,7 +1478,7 @@ QString QMLManager::getGpsFromSiteName(const QString& siteName)
uuid = get_dive_site_uuid_by_name(qPrintable(siteName), NULL); uuid = get_dive_site_uuid_by_name(qPrintable(siteName), NULL);
if (uuid) { if (uuid) {
ds = get_dive_site_by_uuid(uuid); ds = get_dive_site_by_uuid(uuid);
return QString(printGPSCoords(ds->latitude.udeg, ds->longitude.udeg)); return QString(printGPSCoords(&ds->location));
} }
return ""; return "";
} }

View file

@ -43,8 +43,8 @@ QVariant LocationInformationModel::getDiveSiteData(const struct dive_site *ds, i
switch(column) { switch(column) {
case UUID: return ds->uuid; case UUID: return ds->uuid;
case NAME: return ds->name; case NAME: return ds->name;
case LATITUDE: return ds->latitude.udeg; case LATITUDE: return ds->location.lat.udeg;
case LONGITUDE: return ds->longitude.udeg; case LONGITUDE: return ds->location.lon.udeg;
case COORDS: return "TODO"; case COORDS: return "TODO";
case DESCRIPTION: return ds->description; case DESCRIPTION: return ds->description;
case NOTES: return ds->name; case NOTES: return ds->name;
@ -123,28 +123,25 @@ bool GPSLocationInformationModel::filterAcceptsRow(int sourceRow, const QModelIn
return false; return false;
struct dive_site *ds = get_dive_site_by_uuid(uuid); struct dive_site *ds = get_dive_site_by_uuid(uuid);
return ds && ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg; return ds && same_location(&ds->location, &location);
} }
GPSLocationInformationModel::GPSLocationInformationModel(QObject *parent) : QSortFilterProxyModel(parent), GPSLocationInformationModel::GPSLocationInformationModel(QObject *parent) : QSortFilterProxyModel(parent),
ignoreUuid(0), ignoreUuid(0),
latitude({ 0 }), location({{0},{0}})
longitude({ 0 })
{ {
setSourceModel(LocationInformationModel::instance()); setSourceModel(LocationInformationModel::instance());
} }
void GPSLocationInformationModel::set(uint32_t ignoreUuidIn, degrees_t latitudeIn, degrees_t longitudeIn) void GPSLocationInformationModel::set(uint32_t ignoreUuidIn, const location_t &locationIn)
{ {
ignoreUuid = ignoreUuidIn; ignoreUuid = ignoreUuidIn;
latitude = latitudeIn; location = locationIn;
longitude = longitudeIn;
invalidate(); invalidate();
} }
void GPSLocationInformationModel::setCoordinates(degrees_t latitudeIn, degrees_t longitudeIn) void GPSLocationInformationModel::setCoordinates(const location_t &locationIn)
{ {
latitude = latitudeIn; location = locationIn;
longitude = longitudeIn;
invalidate(); invalidate();
} }

View file

@ -38,12 +38,12 @@ class GPSLocationInformationModel : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
private: private:
uint32_t ignoreUuid; uint32_t ignoreUuid;
degrees_t latitude, longitude; location_t location;
bool filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const override; bool filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const override;
public: public:
GPSLocationInformationModel(QObject *parent = nullptr); GPSLocationInformationModel(QObject *parent = nullptr);
void set(uint32_t ignoreUuid, degrees_t latitude, degrees_t longitude); void set(uint32_t ignoreUuid, const location_t &);
void setCoordinates(degrees_t latitude, degrees_t longitude); void setCoordinates(const location_t &);
}; };
class GeoReferencingOptionsModel : public QStringListModel { class GeoReferencingOptionsModel : public QStringListModel {

View file

@ -46,9 +46,9 @@ QVariant GpsListModel::data(const QModelIndex &index, int role) const
else if (role == GpsNameRole) else if (role == GpsNameRole)
return gt.name; return gt.name;
else if (role == GpsLatitudeRole) else if (role == GpsLatitudeRole)
return QString::number(gt.latitude.udeg / 1000000.0, 'f', 6); return QString::number(gt.location.lat.udeg / 1000000.0, 'f', 6);
else if (role == GpsLongitudeRole) else if (role == GpsLongitudeRole)
return QString::number(gt.longitude.udeg / 1000000.0, 'f', 6); return QString::number(gt.location.lon.udeg / 1000000.0, 'f', 6);
return QVariant(); return QVariant();
} }

View file

@ -323,7 +323,7 @@ static void smtk_build_location(MdbHandle *mdb, char *idx, timestamp_t when, uin
int i; int i;
uint32_t d; uint32_t d;
struct dive_site *ds; struct dive_site *ds;
degrees_t lat, lon; location_t loc;
char *str = NULL, *loc_idx = NULL, *site = NULL, *notes = NULL; char *str = NULL, *loc_idx = NULL, *site = NULL, *notes = NULL;
const char *site_fields[] = {QT_TRANSLATE_NOOP("gettextFromC", "Altitude"), QT_TRANSLATE_NOOP("gettextFromC", "Depth"), const char *site_fields[] = {QT_TRANSLATE_NOOP("gettextFromC", "Altitude"), QT_TRANSLATE_NOOP("gettextFromC", "Depth"),
QT_TRANSLATE_NOOP("gettextFromC", "Notes")}; QT_TRANSLATE_NOOP("gettextFromC", "Notes")};
@ -337,8 +337,7 @@ static void smtk_build_location(MdbHandle *mdb, char *idx, timestamp_t when, uin
mdb_fetch_row(table); mdb_fetch_row(table);
loc_idx = copy_string(col[2]->bind_ptr); loc_idx = copy_string(col[2]->bind_ptr);
site = copy_string(col[1]->bind_ptr); site = copy_string(col[1]->bind_ptr);
lat.udeg = lrint(strtod(col[6]->bind_ptr, NULL) * 1000000); loc = create_location(strtod(col[6]->bind_ptr, NULL), strtod(col[7]->bind_ptr, NULL));
lon.udeg = lrint(strtod(col[7]->bind_ptr, NULL) * 1000000);
for (i = 8; i < 11; i++) { for (i = 8; i < 11; i++) {
switch (i) { switch (i) {
@ -376,10 +375,10 @@ static void smtk_build_location(MdbHandle *mdb, char *idx, timestamp_t when, uin
*location = get_dive_site_uuid_by_name(str, NULL); *location = get_dive_site_uuid_by_name(str, NULL);
if (*location == 0) { if (*location == 0) {
if (lat.udeg == 0 && lon.udeg == 0) if (!has_location(&loc))
*location = create_dive_site(str, when); *location = create_dive_site(str, when);
else else
*location = create_dive_site_with_gps(str, lat, lon, when); *location = create_dive_site_with_gps(str, &loc, when);
} }
smtk_free(bound_values, table->num_cols); smtk_free(bound_values, table->num_cols);

View file

@ -40,8 +40,8 @@ void TestPicture::addPicture()
// 1st appearing at time 21:01 // 1st appearing at time 21:01
// 2nd appearing at time 22:01 // 2nd appearing at time 22:01
QVERIFY(pic1->offset.seconds == 1261); QVERIFY(pic1->offset.seconds == 1261);
QVERIFY(pic1->latitude.udeg == 47934500); QVERIFY(pic1->location.lat.udeg == 47934500);
QVERIFY(pic1->longitude.udeg == 11334500); QVERIFY(pic1->location.lon.udeg == 11334500);
QVERIFY(pic2->offset.seconds == 1321); QVERIFY(pic2->offset.seconds == 1321);
learnPictureFilename(pic1->filename, PIC1_NAME); learnPictureFilename(pic1->filename, PIC1_NAME);