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();
picture->filename = strdup(filename);
picture->offset.seconds = metadata.timestamp - dive->when + shift_time;
picture->longitude = metadata.longitude;
picture->latitude = metadata.latitude;
picture->location = metadata.location;
dive_add_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)
{
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) {
ds->latitude = picture->latitude;
ds->longitude = picture->longitude;
ds->location = picture->location;
} 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);
}
}
@ -4428,7 +4426,7 @@ int get_idx_by_uniq_id(int id)
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)

View file

@ -363,8 +363,7 @@ extern enum divemode_t get_divemode_at_time(const struct divecomputer *dc, int d
struct picture {
char *filename;
offset_t offset;
degrees_t latitude;
degrees_t longitude;
location_t location;
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 */
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;
struct dive_site *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)
*dsp = ds;
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
* 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 */
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;
struct dive_site *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 0;
}
// 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 lat_d_r = udeg_to_radians(lat2.udeg-lat1.udeg);
double lon_d_r = udeg_to_radians(lon2.udeg-lon1.udeg);
double lat2_r = udeg_to_radians(loc2->lat.udeg);
double lat_d_r = udeg_to_radians(loc2->lat.udeg - loc1->lat.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) +
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 */
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 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;
for_each_dive_site (i, 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;
uuid = ds->uuid;
if (dsp)
@ -232,13 +232,12 @@ uint32_t create_dive_site_from_current_dive(const char *name)
}
/* 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);
struct dive_site *ds = alloc_or_get_dive_site(uuid);
ds->name = copy_string(name);
ds->latitude = latitude;
ds->longitude = longitude;
ds->location = *loc;
return ds->uuid;
}
@ -250,8 +249,7 @@ bool dive_site_is_empty(struct dive_site *ds)
(empty_string(ds->name) &&
empty_string(ds->description) &&
empty_string(ds->notes) &&
ds->latitude.udeg == 0 &&
ds->longitude.udeg == 0);
!has_location(&ds->location));
}
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->description);
copy->latitude = orig->latitude;
copy->longitude = orig->longitude;
copy->location = orig->location;
copy->name = copy_string(orig->name);
copy->notes = copy_string(orig->notes);
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)
{
if (!a->latitude.udeg) a->latitude.udeg = b->latitude.udeg;
if (!a->longitude.udeg) a->longitude.udeg = b->longitude.udeg;
if (!has_location(&a->location)) a->location = b->location;
merge_string(&a->name, &b->name);
merge_string(&a->notes, &b->notes);
merge_string(&a->description, &b->description);
@ -310,8 +306,8 @@ void clear_dive_site(struct dive_site *ds)
ds->name = NULL;
ds->notes = NULL;
ds->description = NULL;
ds->latitude.udeg = 0;
ds->longitude.udeg = 0;
ds->location.lat.udeg = 0;
ds->location.lon.udeg = 0;
ds->uuid = 0;
ds->taxonomy.nr = 0;
free_taxonomy(&ds->taxonomy);

View file

@ -18,7 +18,7 @@ struct dive_site
{
uint32_t uuid;
char *name;
degrees_t latitude, longitude;
location_t location;
char *description;
char *notes;
struct taxonomy_data taxonomy;
@ -60,17 +60,17 @@ void free_dive_site(struct dive_site *ds);
void delete_dive_site(uint32_t id);
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_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_gps(degrees_t latitude, degrees_t longitude, 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_proximity(degrees_t latitude, degrees_t longitude, int distance, 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, const location_t *);
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);
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 merge_dive_site(struct dive_site *a, struct dive_site *b);
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);
void merge_dive_sites(uint32_t ref, uint32_t *uuids, int count);

View file

@ -137,7 +137,7 @@ QString GpsLocation::currentPosition()
if (delta < 300) {
// we can simply use the last position that we tracked
gpsTracker gt = m_trackers.last();
QString gpsString = printGPSCoords(gt.latitude.udeg, gt.longitude.udeg);
QString gpsString = printGPSCoords(&gt.location);
qDebug() << "returning last position" << gpsString;
return gpsString;
} else {
@ -159,8 +159,8 @@ void GpsLocation::newPosition(QGeoPositionInfo pos)
int nr = m_trackers.count();
if (nr) {
gpsTracker gt = m_trackers.last();
lastCoord.setLatitude(gt.latitude.udeg / 1000000.0);
lastCoord.setLongitude(gt.longitude.udeg / 1000000.0);
lastCoord.setLatitude(gt.location.lat.udeg / 1000000.0);
lastCoord.setLongitude(gt.location.lon.udeg / 1000000.0);
lastTime = gt.when;
}
// if we are waiting for a position update or
@ -176,8 +176,7 @@ void GpsLocation::newPosition(QGeoPositionInfo pos)
gpsTracker gt;
gt.when = pos.timestamp().toTime_t();
gt.when += gettimezoneoffset(gt.when);
gt.latitude.udeg = lrint(pos.coordinate().latitude() * 1000000);
gt.longitude.udeg = lrint(pos.coordinate().longitude() * 1000000);
gt.location = create_location(pos.coordinate().latitude(), pos.coordinate().longitude());
addFixToStorage(gt);
gpsTracker gtNew = m_trackers.last();
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);
ds = get_dive_site_by_uuid(d->dive_site_uuid);
}
ds->latitude = gps.latitude;
ds->longitude = gps.longitude;
ds->location = gps.location;
}
#define SAME_GROUP 6 * 3600 /* six hours */
@ -331,8 +329,8 @@ void GpsLocation::loadFromStorage()
for (int i = 0; i < nr; i++) {
struct gpsTracker gt;
gt.when = geoSettings->value(QString("gpsFix%1_time").arg(i)).toLongLong();
gt.latitude.udeg = geoSettings->value(QString("gpsFix%1_lat").arg(i)).toInt();
gt.longitude.udeg = geoSettings->value(QString("gpsFix%1_lon").arg(i)).toInt();
gt.location.lat.udeg = geoSettings->value(QString("gpsFix%1_lat").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.idx = i;
m_trackers.insert(gt.when, gt);
@ -347,11 +345,10 @@ void GpsLocation::replaceFixToStorage(gpsTracker &gt)
}
gpsTracker replacedTracker = m_trackers.value(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_lon").arg(replacedTracker.idx), gt.longitude.udeg);
geoSettings->setValue(QString("gpsFix%1_lat").arg(replacedTracker.idx), gt.location.lat.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);
replacedTracker.latitude = gt.latitude;
replacedTracker.longitude = gt.longitude;
replacedTracker.location = gt.location;
replacedTracker.name = gt.name;
}
@ -360,8 +357,8 @@ void GpsLocation::addFixToStorage(gpsTracker &gt)
int nr = m_trackers.count();
geoSettings->setValue("count", nr + 1);
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_lon").arg(nr), gt.longitude.udeg);
geoSettings->setValue(QString("gpsFix%1_lat").arg(nr), gt.location.lat.udeg);
geoSettings->setValue(QString("gpsFix%1_lon").arg(nr), gt.location.lon.udeg);
geoSettings->setValue(QString("gpsFix%1_name").arg(nr), gt.name);
gt.idx = nr;
geoSettings->sync();
@ -389,8 +386,8 @@ void GpsLocation::deleteFixFromStorage(gpsTracker &gt)
m_trackers.remove(movedTracker.when);
m_trackers.insert(movedTracker.when, movedTracker);
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_lon").arg(movedTracker.idx), movedTracker.longitude.udeg);
geoSettings->setValue(QString("gpsFix%1_lat").arg(movedTracker.idx), movedTracker.location.lat.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->remove(QString("gpsFix%1_lat").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")
struct gpsTracker {
degrees_t latitude;
degrees_t longitude;
location_t location;
qint64 when;
QString name;
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);
}
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)
{
@ -591,14 +591,12 @@ static void parse_string_field(struct dive *dive, dc_field_string_t *str)
/* GPS data? */
if (!strncmp(str->desc, "GPS", 3)) {
char *line = (char *) str->value;
degrees_t latitude, longitude;
location_t location;
latitude = parse_degrees(line, &line);
if (*line == ',') line++;
longitude = parse_degrees(line, &line);
parse_location(line, &location);
if (latitude.udeg && longitude.udeg)
dive->dive_site_uuid = create_dive_site_with_gps(str->value, latitude, longitude, time(NULL));
if (location.lat.udeg && location.lon.udeg)
dive->dive_site_uuid = create_dive_site_with_gps(str->value, &location, time(NULL));
}
}
#endif

View file

@ -31,7 +31,7 @@ struct keyword_action {
};
#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);
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);
uint32_t uuid;
degrees_t latitude = parse_degrees(line, &line);
degrees_t longitude = parse_degrees(line, &line);
location_t location;
struct dive *dive = _dive;
struct dive_site *ds = get_dive_site_for_dive(dive);
parse_location(line, &location);
if (!ds) {
uuid = get_dive_site_uuid_by_gps(latitude, longitude, NULL);
uuid = get_dive_site_uuid_by_gps(&location, NULL);
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;
} else {
if (dive_site_has_gps_location(ds) &&
(ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) {
const char *coords = printGPSCoords(latitude.udeg, longitude.udeg);
if (dive_site_has_gps_location(ds) && !same_location(&ds->location, &location)) {
const char *coords = printGPSCoords(&location);
// 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);
free((void *)coords);
}
ds->latitude = latitude;
ds->longitude = longitude;
ds->location = location;
}
}
@ -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)
{ 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)
{
UNUSED(str);
struct dive_site *ds = _ds;
ds->latitude = parse_degrees(line, &line);
ds->longitude = parse_degrees(line, &line);
parse_location(line, &ds->location);
}
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);
struct picture *pic = _pic;
pic->latitude = parse_degrees(line, &line);
pic->longitude = parse_degrees(line, &line);
parse_location(line, &pic->location);
}
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);
}
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)
{
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_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_location(struct membuffer *b, location_t *, const char *, const char *);
#ifdef __cplusplus
}

View file

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

View file

@ -6,8 +6,7 @@
struct metadata {
timestamp_t timestamp;
duration_t duration;
degrees_t latitude;
degrees_t longitude;
location_t location;
};
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
* 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;
degrees_t ret;
@ -1112,86 +1112,90 @@ degrees_t parse_degrees(char *buf, char **end)
static void gps_lat(char *buffer, struct dive *dive)
{
char *end;
degrees_t latitude = parse_degrees(buffer, &end);
location_t location = { };
struct dive_site *ds = get_dive_site_for_dive(dive);
location.lat = parse_degrees(buffer, &end);
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 {
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)");
ds->latitude = latitude;
ds->location.lat = location.lat;
}
}
static void gps_long(char *buffer, struct dive *dive)
{
char *end;
degrees_t longitude = parse_degrees(buffer, &end);
location_t location = { };
struct dive_site *ds = get_dive_site_for_dive(dive);
location.lon = parse_degrees(buffer, &end);
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 {
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)");
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;
loc->lat = parse_degrees(buffer, &end);
if (*end == ',') end++;
loc->lon = parse_degrees(end, &end);
}
ds->latitude = parse_degrees(buffer, &end);
ds->longitude = parse_degrees(end, &end);
static void gps_location(char *buffer, struct dive_site *ds)
{
parse_location(buffer, &ds->location);
}
static void gps_in_dive(char *buffer, struct dive *dive)
{
char *end;
struct dive_site *ds = NULL;
degrees_t latitude = parse_degrees(buffer, &end);
degrees_t longitude = parse_degrees(end, &end);
location_t location;
uint32_t uuid = dive->dive_site_uuid;
parse_location(buffer, &location);
if (uuid == 0) {
// 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) {
// 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
cur_latitude = latitude;
cur_longitude = longitude;
cur_location = location;
dive->dive_site_uuid = uuid;
} 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);
}
} else {
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)) {
has_location(&location) && !same_location(&ds->location, &location)) {
// 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);
const char *coords = printGPSCoords(latitude.udeg, longitude.udeg);
ds->location.lat.udeg / 1000000.0, ds->location.lon.udeg / 1000000.0,
location.lat.udeg / 1000000.0, location.lon.udeg / 1000000.0);
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);
free((void *)coords);
} else {
ds->latitude = latitude;
ds->longitude = longitude;
ds->location = location;
}
}
}
static void gps_picture_location(char *buffer, struct picture *pic)
{
char *end;
pic->latitude = parse_degrees(buffer, &end);
pic->longitude = parse_degrees(end, &end);
parse_location(buffer, &pic->location);
}
/* 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;
case 4:
/* Measure GPS */
cur_latitude.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_dive->dive_site_uuid = create_dive_site_with_gps("DLF imported", cur_latitude, cur_longitude, cur_dive->when);
cur_location.lat.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 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_location, cur_dive->when);
break;
default:
break;

View file

@ -22,7 +22,7 @@ struct parser_settings cur_settings;
struct divecomputer *cur_dc = NULL;
struct dive *cur_dive = NULL;
struct dive_site *cur_dive_site = NULL;
degrees_t cur_latitude, cur_longitude;
location_t cur_location;
dive_trip_t *cur_trip = NULL;
struct sample *cur_sample = NULL;
struct picture *cur_picture = NULL;
@ -258,8 +258,8 @@ void dive_end(void)
record_dive_to_table(cur_dive, target_table);
cur_dive = NULL;
cur_dc = NULL;
cur_latitude.udeg = 0;
cur_longitude.udeg = 0;
cur_location.lat.udeg = 0;
cur_location.lon.udeg = 0;
cur_cylinder_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
// have had two different names for the same site... so let's search the other
// 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) {
dive->dive_site_uuid = exact_match_uuid;
} else {
dive->dive_site_uuid = create_dive_site(buffer, dive->when);
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
newds->latitude = cur_latitude;
newds->longitude = cur_longitude;
newds->location = cur_location;
} else {
newds->latitude = ds->latitude;
newds->longitude = ds->longitude;
newds->location = ds->location;
}
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 dive *cur_dive;
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 struct sample *cur_sample;
extern struct picture *cur_picture;

View file

@ -75,14 +75,16 @@ QString distance_string(int distanceInMeters)
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 latmin, lonmin;
double latsec, lonsec;
QString lath, lonh, result;
if (!lat && !lon)
if (!has_location(loc))
return strdup("");
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
bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out)
{
double latitude, longitude;
int latudeg, longudeg;
location_t location;
bool ignore;
bool *parsed = parsed_out ?: &ignore;
*parsed = true;
/* if we have a master and the dive's gps address is different from it,
* don't change the dive */
if (master && (master->latitude.udeg != dive->latitude.udeg ||
master->longitude.udeg != dive->longitude.udeg))
if (master && !same_location(&master->location, &dive->location))
return false;
if (!(*parsed = parseGpsText(gps_text, &latitude, &longitude)))
if (!(*parsed = parseGpsText(gps_text, location)))
return false;
latudeg = lrint(1000000 * latitude);
longudeg = lrint(1000000 * longitude);
/* 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;
/* ok, update the dive and mark things changed */
dive->latitude.udeg = latudeg;
dive->longitude.udeg = longudeg;
dive->location = location;
return true;
}
#endif

View file

@ -124,7 +124,7 @@ void moveInVector(Vector &v, int rangeBegin, int rangeEnd, int destination)
extern "C" {
#endif
const char *printGPSCoords(int lat, int lon);
const char *printGPSCoords(const location_t *loc);
bool in_planner();
bool getProxyString(char **buffer);
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)
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)
{
const char *p = text;
@ -613,7 +605,7 @@ static int save_one_picture(git_repository *repo, struct dir *dir, struct pictur
unsigned h;
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.. */
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, "description ", ds->description, "\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++) {
struct taxonomy *t = &ds->taxonomy.category[j];
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);
if (!ds)
return;
degrees_t latitude = ds->latitude;
degrees_t longitude = ds->longitude;
degrees_t latitude = ds->location.lat;
degrees_t longitude = ds->location.lon;
//don't put coordinates if in (0,0)
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));
}
if (pic->latitude.udeg || pic->longitude.udeg) {
put_degrees(b, pic->latitude, " gps='", " ");
put_degrees(b, pic->longitude, "", "'");
}
put_location(b, &pic->location, " gps='","'");
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);
show_utf8_blanked(b, ds->name, " name='", "'", 1, anonymize);
if (ds->latitude.udeg || ds->longitude.udeg) {
put_degrees(b, ds->latitude, " gps='", " ");
put_degrees(b, ds->longitude, "", "'");
}
put_location(b, &ds->location, " gps='", "'");
show_utf8_blanked(b, ds->description, " description='", "'", 1, anonymize);
put_format(b, ">\n");
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
{
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

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);
if (ds) {
ds->name = strdup(text);
ds->longitude.udeg = lrint(longitude * 1000000);
ds->latitude.udeg = lrint(latitude * 1000000);
ds->location = create_location(latitude, longitude);
}
}
hp = hp->next;

View file

@ -134,6 +134,29 @@ typedef struct
int udeg;
} 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)
{
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);
if (!ds || !dive_site_has_gps_location(ds))
continue;
put_degrees(b, ds->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", "");
put_degrees(b, ds->longitude, ",", ")});\n");
put_degrees(b, ds->location.lat, "temp = new google.maps.Marker({position: new google.maps.LatLng(", "");
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\">");
snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Date:"));
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\\spot{}\n");
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\\gpslon{%f}\n", site->longitude.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslon{}\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->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\\country{%s}\n", qPrintable(country));
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);
else
ui.diveSiteNotes->clear();
if (diveSite->latitude.udeg || diveSite->longitude.udeg) {
const char *coords = printGPSCoords(diveSite->latitude.udeg, diveSite->longitude.udeg);
if (has_location(&diveSite->location)) {
const char *coords = printGPSCoords(&diveSite->location);
ui.diveSiteCoordinates->setText(coords);
free((void *)coords);
} else {
@ -137,12 +137,13 @@ void LocationInformationWidget::clearLabels()
ui.locationTags->clear();
}
void LocationInformationWidget::updateGpsCoordinates(degrees_t latitude, degrees_t longitude)
void LocationInformationWidget::updateGpsCoordinates(const location_t &location)
{
QString oldText = ui.diveSiteCoordinates->text();
const char *coords = printGPSCoords(latitude.udeg, longitude.udeg);
const char *coords = printGPSCoords(&location);
ui.diveSiteCoordinates->setText(coords);
enableLocationButtons(latitude.udeg || longitude.udeg);
enableLocationButtons(has_location(&location));
free((void *)coords);
if (oldText != ui.diveSiteCoordinates->text())
markChangedWidget(ui.diveSiteCoordinates);
@ -150,12 +151,11 @@ void LocationInformationWidget::updateGpsCoordinates(degrees_t latitude, degrees
// Parse GPS text into latitude and longitude.
// 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;
if (parseGpsText(text, &lat, &lon)) {
latitude.udeg = lrint(lat * 1000000.0);
longitude.udeg = lrint(lon * 1000000.0);
location = create_location(lat, lon);
return true;
}
return false;
@ -204,7 +204,7 @@ void LocationInformationWidget::acceptChanges()
}
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)) {
LocationInformationModel::instance()->removeRow(get_divesite_idx(diveSite));
displayed_dive.dive_site_uuid = 0;
@ -224,7 +224,7 @@ void LocationInformationWidget::initFields(dive_site *ds)
diveSite = ds;
if (ds) {
copy_taxonomy(&ds->taxonomy, &taxonomy);
filter_model.set(ds->uuid, ds->latitude, ds->longitude);
filter_model.set(ds->uuid, ds->location);
updateLabels();
enableLocationButtons(dive_site_has_gps_location(ds));
QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel *>(ui.diveSiteListView->model());
@ -233,7 +233,7 @@ void LocationInformationWidget::initFields(dive_site *ds)
m->invalidate();
} else {
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();
}
MapWidget::instance()->prepareForGetDiveCoordinates(ds ? ds->uuid : 0);
@ -276,14 +276,14 @@ void LocationInformationWidget::on_diveSiteCoordinates_textChanged(const QString
{
if (!diveSite)
return;
degrees_t latitude, longitude;
bool ok_old = diveSite->latitude.udeg || diveSite->longitude.udeg;
bool ok = parseGpsText(text, latitude, longitude);
if (ok != ok_old || latitude.udeg != diveSite->latitude.udeg || longitude.udeg != diveSite->longitude.udeg) {
location_t location;
bool ok_old = has_location(&diveSite->location);
bool ok = parseGpsText(text, location);
if (ok != ok_old || !same_location(&location, &diveSite->location)) {
if (ok) {
markChangedWidget(ui.diveSiteCoordinates);
enableLocationButtons(true);
filter_model.setCoordinates(latitude, longitude);
filter_model.setCoordinates(location);
} else {
enableLocationButtons(false);
}
@ -326,10 +326,10 @@ void LocationInformationWidget::resetPallete()
void LocationInformationWidget::reverseGeocode()
{
degrees_t latitude, longitude;
if (!parseGpsText(ui.diveSiteCoordinates->text(), latitude, longitude))
location_t location;
if (!parseGpsText(ui.diveSiteCoordinates->text(), location))
return;
reverseGeoLookup(latitude, longitude, &taxonomy);
reverseGeoLookup(location.lat, location.lon, &taxonomy);
ui.locationTags->setText(constructLocationTags(&taxonomy, false));
}
@ -337,11 +337,11 @@ void LocationInformationWidget::updateLocationOnMap()
{
if (!diveSite)
return;
degrees_t latitude, longitude;
if (!parseGpsText(ui.diveSiteCoordinates->text(), latitude, longitude))
location_t location;
if (!parseGpsText(ui.diveSiteCoordinates->text(), location))
return;
MapWidget::instance()->updateDiveSiteCoordinates(diveSite->uuid, latitude, longitude);
filter_model.setCoordinates(latitude, longitude);
MapWidget::instance()->updateDiveSiteCoordinates(diveSite->uuid, location);
filter_model.setCoordinates(location);
}
DiveLocationFilterProxyModel::DiveLocationFilterProxyModel(QObject*)

View file

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

View file

@ -109,16 +109,16 @@ void MapWidget::selectedDivesChanged(QList<int> list)
skipReload = false;
}
void MapWidget::coordinatesChangedLocal(degrees_t latitude, degrees_t longitude)
void MapWidget::coordinatesChangedLocal(const location_t &location)
{
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();
m_mapHelper->updateDiveSiteCoordinates(uuid, latitude, longitude);
m_mapHelper->updateDiveSiteCoordinates(uuid, location);
}
MapWidget::~MapWidget()

View file

@ -25,7 +25,7 @@ public:
void reload();
signals:
void coordinatesChanged(degrees_t latitude, degrees_t longitude);
void coordinatesChanged(const location_t &);
public slots:
void centerOnSelectedDiveSite();
@ -35,9 +35,9 @@ public slots:
void repopulateLabels();
void prepareForGetDiveCoordinates(uint32_t uuid);
void selectedDivesChanged(QList<int>);
void coordinatesChangedLocal(degrees_t latitude, degrees_t longitude);
void coordinatesChangedLocal(const location_t &);
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:
static MapWidget *m_instance;

View file

@ -479,7 +479,7 @@ void LocationFilterDelegate::paint(QPainter *painter, const QStyleOptionViewItem
}
if (bottomText.isEmpty()) {
const char *gpsCoords = printGPSCoords(ds->latitude.udeg, ds->longitude.udeg);
const char *gpsCoords = printGPSCoords(&ds->location);
bottomText = QString(gpsCoords);
free( (void*) gpsCoords);
}
@ -487,11 +487,10 @@ void LocationFilterDelegate::paint(QPainter *painter, const QStyleOptionViewItem
if (dive_site_has_gps_location(ds) && currentDiveSiteHasGPS) {
// 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
if (ds->latitude.udeg == currentDiveSite->latitude.udeg &&
ds->longitude.udeg == currentDiveSite->longitude.udeg) {
if (same_location(&ds->location, &currentDiveSite->location)) {
bottomText += tr(" (same GPS fix)");
} 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);
int nr = nr_of_dives_at_dive_site(ds->uuid, false);
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_quoted(&mb, ds->name, 1, 0);
put_format(&mb, "'");
if (ds->latitude.udeg || ds->longitude.udeg) {
put_degrees(&mb, ds->latitude, " gps='", " ");
put_degrees(&mb, ds->longitude, "", "'");
}
put_location(&mb, &ds->location, " gps='", "'");
put_format(&mb, ">\n");
if (ds->taxonomy.nr) {
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->uuid = pickedUuid;
qDebug() << "Creating and copying dive site";
} else if (newDs->latitude.udeg == 0 && newDs->longitude.udeg == 0) {
newDs->latitude.udeg = origDs->latitude.udeg;
newDs->longitude.udeg = origDs->longitude.udeg;
} else if (!has_location(&newDs->location)) {
newDs->location = origDs->location;
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);
if (!ds || !dive_site_has_gps_location(ds))
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)
@ -48,7 +48,7 @@ void MapWidgetHelper::centerOnDiveSite(struct dive_site *ds)
} else {
// dive site with GPS
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)));
}
}
@ -68,8 +68,8 @@ void MapWidgetHelper::centerOnSelectedDiveSite()
continue;
// only store dive sites with GPS
selDS.append(dss);
selGC.append(QGeoCoordinate(dss->latitude.udeg * 0.000001,
dss->longitude.udeg * 0.000001));
selGC.append(QGeoCoordinate(dss->location.lat.udeg * 0.000001,
dss->location.lon.udeg * 0.000001));
}
if (selDS.isEmpty()) {
@ -86,8 +86,8 @@ void MapWidgetHelper::centerOnSelectedDiveSite()
qreal minLat = 0.0, minLon = 0.0, maxLat = 0.0, maxLon = 0.0;
bool start = true;
for(struct dive_site *dss: selDS) {
qreal lat = dss->latitude.udeg * 0.000001;
qreal lon = dss->longitude.udeg * 0.000001;
qreal lat = dss->location.lat.udeg * 0.000001;
qreal lon = dss->location.lon.udeg * 0.000001;
if (start) {
minLat = maxLat = lat;
minLon = maxLon = lon;
@ -133,8 +133,8 @@ void MapWidgetHelper::reloadMapLocations()
struct dive_site *ds = get_dive_site_for_dive(dive);
if (!dive_site_has_gps_location(ds) || locationUuids.contains(ds->uuid))
continue;
latitude = ds->latitude.udeg * 0.000001;
longitude = ds->longitude.udeg * 0.000001;
latitude = ds->location.lat.udeg * 0.000001;
longitude = ds->location.lon.udeg * 0.000001;
QGeoCoordinate dsCoord(latitude, longitude);
QString name(ds->name);
// 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))
continue;
#ifndef SUBSURFACE_MOBILE
const qreal latitude = ds->latitude.udeg * 0.000001;
const qreal longitude = ds->longitude.udeg * 0.000001;
const qreal latitude = ds->location.lat.udeg * 0.000001;
const qreal longitude = ds->location.lon.udeg * 0.000001;
QGeoCoordinate dsCoord(latitude, longitude);
if (locationCoord.distanceTo(dsCoord) < m_smallCircleRadius)
m_selectedDiveIds.append(idx);
@ -194,8 +194,8 @@ void MapWidgetHelper::selectVisibleLocations()
struct dive_site *ds = get_dive_site_for_dive(dive);
if (!dive_site_has_gps_location(ds))
continue;
const qreal latitude = ds->latitude.udeg * 0.000001;
const qreal longitude = ds->longitude.udeg * 0.000001;
const qreal latitude = ds->location.lat.udeg * 0.000001;
const qreal longitude = ds->location.lon.udeg * 0.000001;
QGeoCoordinate dsCoord(latitude, longitude);
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);
}
static location_t mk_location(QGeoCoordinate coord)
{
return create_location(coord.latitude(), coord.longitude());
}
void MapWidgetHelper::copyToClipboardCoordinates(QGeoCoordinate coord, bool formatTraditional)
{
bool savep = prefs.coordinates_traditional;
prefs.coordinates_traditional = formatTraditional;
const int lat = lrint(1000000.0 * coord.latitude());
const int lon = lrint(1000000.0 * coord.longitude());
const char *coordinates = printGPSCoords(lat, lon);
location_t location = mk_location(coord);
const char *coordinates = printGPSCoords(&location);
QApplication::clipboard()->setText(QString(coordinates), QClipboard::Clipboard);
free((void *)coordinates);
@ -266,14 +269,14 @@ void MapWidgetHelper::updateCurrentDiveSiteCoordinatesFromMap(quint32 uuid, QGeo
MapLocation *loc = m_mapLocationModel->getMapLocationForUuid(uuid);
if (loc)
loc->setCoordinate(coord);
emit coordinatesChanged(degrees_t { (int)lrint(coord.latitude() * 1000000.0) },
degrees_t { (int)lrint(coord.longitude() * 1000000.0) });
location_t location = mk_location(coord);
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 longitude_r = longitude.udeg * 0.000001;
const qreal latitude_r = location.lat.udeg * 0.000001;
const qreal longitude_r = location.lon.udeg * 0.000001;
QGeoCoordinate coord(latitude_r, longitude_r);
m_mapLocationModel->updateMapLocationCoordinates(uuid, coord);
QMetaObject::invokeMethod(m_map, "centerOnCoordinate", Q_ARG(QVariant, QVariant::fromValue(coord)));
@ -303,8 +306,8 @@ void MapWidgetHelper::enterEditMode(quint32 uuid)
coord = exists->coordinate();
}
centerOnDiveSiteUUID(uuid);
emit coordinatesChanged(degrees_t { (int)lrint(coord.latitude() * 1000000.0) },
degrees_t { (int)lrint(coord.longitude() * 1000000.0) });
location_t location = mk_location(coord);
emit coordinatesChanged(location);
emit editModeChanged();
}

View file

@ -36,7 +36,7 @@ public:
Q_INVOKABLE void calculateSmallCircleRadius(QGeoCoordinate coord);
Q_INVOKABLE void updateCurrentDiveSiteCoordinatesFromMap(quint32 uuid, QGeoCoordinate coord);
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 exitEditMode();
QString pluginObject();
@ -55,7 +55,7 @@ signals:
void modelChanged();
void editModeChanged();
void selectedDivesChanged(QList<int> list);
void coordinatesChanged(degrees_t latitude, degrees_t longitude);
void coordinatesChanged(const location_t &);
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)
{
location_t location = create_location(lat, lon);
if (ds) {
ds->latitude.udeg = lrint(lat * 1000000);
ds->longitude.udeg = lrint(lon * 1000000);
ds->location = location;
} else {
degrees_t latData, lonData;
latData.udeg = lrint(lat * 1000000);
lonData.udeg = lrint(lon * 1000000);
d->dive_site_uuid = create_dive_site_with_gps(locationtext, latData, lonData, d->when);
d->dive_site_uuid = create_dive_site_with_gps(locationtext, &location, d->when);
}
}
@ -1481,7 +1478,7 @@ QString QMLManager::getGpsFromSiteName(const QString& siteName)
uuid = get_dive_site_uuid_by_name(qPrintable(siteName), NULL);
if (uuid) {
ds = get_dive_site_by_uuid(uuid);
return QString(printGPSCoords(ds->latitude.udeg, ds->longitude.udeg));
return QString(printGPSCoords(&ds->location));
}
return "";
}

View file

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

View file

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

View file

@ -46,9 +46,9 @@ QVariant GpsListModel::data(const QModelIndex &index, int role) const
else if (role == GpsNameRole)
return gt.name;
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)
return QString::number(gt.longitude.udeg / 1000000.0, 'f', 6);
return QString::number(gt.location.lon.udeg / 1000000.0, 'f', 6);
return QVariant();
}

View file

@ -323,7 +323,7 @@ static void smtk_build_location(MdbHandle *mdb, char *idx, timestamp_t when, uin
int i;
uint32_t d;
struct dive_site *ds;
degrees_t lat, lon;
location_t loc;
char *str = NULL, *loc_idx = NULL, *site = NULL, *notes = NULL;
const char *site_fields[] = {QT_TRANSLATE_NOOP("gettextFromC", "Altitude"), QT_TRANSLATE_NOOP("gettextFromC", "Depth"),
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);
loc_idx = copy_string(col[2]->bind_ptr);
site = copy_string(col[1]->bind_ptr);
lat.udeg = lrint(strtod(col[6]->bind_ptr, NULL) * 1000000);
lon.udeg = lrint(strtod(col[7]->bind_ptr, NULL) * 1000000);
loc = create_location(strtod(col[6]->bind_ptr, NULL), strtod(col[7]->bind_ptr, NULL));
for (i = 8; i < 11; 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);
if (*location == 0) {
if (lat.udeg == 0 && lon.udeg == 0)
if (!has_location(&loc))
*location = create_dive_site(str, when);
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);

View file

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