mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Merge branch 'divesites'
This brings in the dive site infrastructure and initial UI work
This commit is contained in:
commit
56de6b73f6
33 changed files with 1062 additions and 368 deletions
24
dive.c
24
dive.c
|
@ -13,6 +13,7 @@
|
||||||
* it's used in the UI, but it seems to make the most sense to have it
|
* it's used in the UI, but it seems to make the most sense to have it
|
||||||
* here */
|
* here */
|
||||||
struct dive displayed_dive;
|
struct dive displayed_dive;
|
||||||
|
struct dive_site displayed_dive_site;
|
||||||
|
|
||||||
struct tag_entry *g_tag_list = NULL;
|
struct tag_entry *g_tag_list = NULL;
|
||||||
|
|
||||||
|
@ -437,7 +438,6 @@ void clear_dive(struct dive *d)
|
||||||
/* free the strings */
|
/* free the strings */
|
||||||
free(d->buddy);
|
free(d->buddy);
|
||||||
free(d->divemaster);
|
free(d->divemaster);
|
||||||
free(d->location);
|
|
||||||
free(d->notes);
|
free(d->notes);
|
||||||
free(d->suit);
|
free(d->suit);
|
||||||
/* free tags, additional dive computers, and pictures */
|
/* free tags, additional dive computers, and pictures */
|
||||||
|
@ -463,7 +463,6 @@ void copy_dive(struct dive *s, struct dive *d)
|
||||||
*d = *s;
|
*d = *s;
|
||||||
d->buddy = copy_string(s->buddy);
|
d->buddy = copy_string(s->buddy);
|
||||||
d->divemaster = copy_string(s->divemaster);
|
d->divemaster = copy_string(s->divemaster);
|
||||||
d->location = copy_string(s->location);
|
|
||||||
d->notes = copy_string(s->notes);
|
d->notes = copy_string(s->notes);
|
||||||
d->suit = copy_string(s->suit);
|
d->suit = copy_string(s->suit);
|
||||||
for (int i = 0; i < MAX_CYLINDERS; i++)
|
for (int i = 0; i < MAX_CYLINDERS; i++)
|
||||||
|
@ -500,7 +499,6 @@ void selective_copy_dive(struct dive *s, struct dive *d, struct dive_components
|
||||||
{
|
{
|
||||||
if (clear)
|
if (clear)
|
||||||
clear_dive(d);
|
clear_dive(d);
|
||||||
CONDITIONAL_COPY_STRING(location);
|
|
||||||
CONDITIONAL_COPY_STRING(notes);
|
CONDITIONAL_COPY_STRING(notes);
|
||||||
CONDITIONAL_COPY_STRING(divemaster);
|
CONDITIONAL_COPY_STRING(divemaster);
|
||||||
CONDITIONAL_COPY_STRING(buddy);
|
CONDITIONAL_COPY_STRING(buddy);
|
||||||
|
@ -509,10 +507,8 @@ void selective_copy_dive(struct dive *s, struct dive *d, struct dive_components
|
||||||
d->rating = s->rating;
|
d->rating = s->rating;
|
||||||
if (what.visibility)
|
if (what.visibility)
|
||||||
d->visibility = s->visibility;
|
d->visibility = s->visibility;
|
||||||
if (what.gps) {
|
if (what.divesite)
|
||||||
d->longitude = s->longitude;
|
d->dive_site_uuid = s->dive_site_uuid;
|
||||||
d->latitude = s->latitude;
|
|
||||||
}
|
|
||||||
if (what.tags)
|
if (what.tags)
|
||||||
STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl);
|
STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl);
|
||||||
if (what.cylinders)
|
if (what.cylinders)
|
||||||
|
@ -2699,7 +2695,7 @@ int count_dives_with_location(const char *location)
|
||||||
struct dive *d;
|
struct dive *d;
|
||||||
|
|
||||||
for_each_dive (i, d) {
|
for_each_dive (i, d) {
|
||||||
if (same_string(d->location, location))
|
if (same_string(get_dive_location(d), location))
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
return counter;
|
return counter;
|
||||||
|
@ -2744,9 +2740,6 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer
|
||||||
res->when = dl ? dl->when : a->when;
|
res->when = dl ? dl->when : a->when;
|
||||||
res->selected = a->selected || b->selected;
|
res->selected = a->selected || b->selected;
|
||||||
merge_trip(res, a, b);
|
merge_trip(res, a, b);
|
||||||
MERGE_NONZERO(res, a, b, latitude.udeg);
|
|
||||||
MERGE_NONZERO(res, a, b, longitude.udeg);
|
|
||||||
MERGE_TXT(res, a, b, location);
|
|
||||||
MERGE_TXT(res, a, b, notes);
|
MERGE_TXT(res, a, b, notes);
|
||||||
MERGE_TXT(res, a, b, buddy);
|
MERGE_TXT(res, a, b, buddy);
|
||||||
MERGE_TXT(res, a, b, divemaster);
|
MERGE_TXT(res, a, b, divemaster);
|
||||||
|
@ -2766,7 +2759,7 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer
|
||||||
interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset);
|
interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset);
|
||||||
else
|
else
|
||||||
join_dive_computers(&res->dc, &a->dc, &b->dc, 0);
|
join_dive_computers(&res->dc, &a->dc, &b->dc, 0);
|
||||||
|
res->dive_site_uuid = a->dive_site_uuid ?: b->dive_site_uuid;
|
||||||
fixup_dive(res);
|
fixup_dive(res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -2931,9 +2924,10 @@ unsigned int dive_get_picture_count(struct dive *d)
|
||||||
|
|
||||||
void dive_set_geodata_from_picture(struct dive *d, struct picture *pic)
|
void dive_set_geodata_from_picture(struct dive *d, struct picture *pic)
|
||||||
{
|
{
|
||||||
if (!d->latitude.udeg && pic->latitude.udeg) {
|
struct dive_site *ds = get_dive_site_by_uuid(d->dive_site_uuid);
|
||||||
d->latitude = pic->latitude;
|
if (!dive_site_has_gps_location(ds) && (pic->latitude.udeg || pic->longitude.udeg)) {
|
||||||
d->longitude = pic->longitude;
|
ds->latitude = pic->latitude;
|
||||||
|
ds->longitude = pic->longitude;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
58
dive.h
58
dive.h
|
@ -8,6 +8,7 @@
|
||||||
#include <zip.h>
|
#include <zip.h>
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "divesite.h"
|
||||||
|
|
||||||
/* Windows has no MIN/MAX macros - so let's just roll our own */
|
/* Windows has no MIN/MAX macros - so let's just roll our own */
|
||||||
#define MIN(x, y) ({ \
|
#define MIN(x, y) ({ \
|
||||||
|
@ -47,6 +48,8 @@ extern "C" {
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern int last_xml_version;
|
||||||
|
|
||||||
enum dive_comp_type {OC, CCR, PSCR, FREEDIVE, NUM_DC_TYPE}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type
|
enum dive_comp_type {OC, CCR, PSCR, FREEDIVE, NUM_DC_TYPE}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type
|
||||||
enum cylinderuse {OC_GAS, DILUENT, OXYGEN, NUM_GAS_USE}; // The different uses for cylinders
|
enum cylinderuse {OC_GAS, DILUENT, OXYGEN, NUM_GAS_USE}; // The different uses for cylinders
|
||||||
|
|
||||||
|
@ -318,11 +321,10 @@ struct dive {
|
||||||
bool hidden_by_filter;
|
bool hidden_by_filter;
|
||||||
bool downloaded;
|
bool downloaded;
|
||||||
timestamp_t when;
|
timestamp_t when;
|
||||||
char *location;
|
uint32_t dive_site_uuid;
|
||||||
char *notes;
|
char *notes;
|
||||||
char *divemaster, *buddy;
|
char *divemaster, *buddy;
|
||||||
int rating;
|
int rating;
|
||||||
degrees_t latitude, longitude;
|
|
||||||
int visibility; /* 0 - 5 star rating */
|
int visibility; /* 0 - 5 star rating */
|
||||||
cylinder_t cylinder[MAX_CYLINDERS];
|
cylinder_t cylinder[MAX_CYLINDERS];
|
||||||
weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS];
|
weightsystem_t weightsystem[MAX_WEIGHTSYSTEMS];
|
||||||
|
@ -347,14 +349,13 @@ extern int get_cylinder_idx_by_use(struct dive *dive, enum cylinderuse cylinder_
|
||||||
|
|
||||||
/* when selectively copying dive information, which parts should be copied? */
|
/* when selectively copying dive information, which parts should be copied? */
|
||||||
struct dive_components {
|
struct dive_components {
|
||||||
unsigned int location : 1;
|
unsigned int divesite : 1;
|
||||||
unsigned int notes : 1;
|
unsigned int notes : 1;
|
||||||
unsigned int divemaster : 1;
|
unsigned int divemaster : 1;
|
||||||
unsigned int buddy : 1;
|
unsigned int buddy : 1;
|
||||||
unsigned int suit : 1;
|
unsigned int suit : 1;
|
||||||
unsigned int rating : 1;
|
unsigned int rating : 1;
|
||||||
unsigned int visibility : 1;
|
unsigned int visibility : 1;
|
||||||
unsigned int gps : 1;
|
|
||||||
unsigned int tags : 1;
|
unsigned int tags : 1;
|
||||||
unsigned int cylinders : 1;
|
unsigned int cylinders : 1;
|
||||||
unsigned int weights : 1;
|
unsigned int weights : 1;
|
||||||
|
@ -386,22 +387,6 @@ extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic);
|
||||||
|
|
||||||
extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc);
|
extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc);
|
||||||
|
|
||||||
static inline int dive_has_gps_location(struct dive *dive)
|
|
||||||
{
|
|
||||||
return dive->latitude.udeg || dive->longitude.udeg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void copy_gps_location(struct dive *from, struct dive *to)
|
|
||||||
{
|
|
||||||
if (from && to) {
|
|
||||||
to->latitude.udeg = from->latitude.udeg;
|
|
||||||
to->longitude.udeg = from->longitude.udeg;
|
|
||||||
if (!to->location) {
|
|
||||||
to->location = strdup(from->location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null)
|
static inline int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null)
|
||||||
{
|
{
|
||||||
int mbar = dive->surface_pressure.mbar;
|
int mbar = dive->surface_pressure.mbar;
|
||||||
|
@ -489,18 +474,12 @@ struct dive_table {
|
||||||
|
|
||||||
extern struct dive_table dive_table;
|
extern struct dive_table dive_table;
|
||||||
extern struct dive displayed_dive;
|
extern struct dive displayed_dive;
|
||||||
|
extern struct dive_site displayed_dive_site;
|
||||||
extern int selected_dive;
|
extern int selected_dive;
|
||||||
extern unsigned int dc_number;
|
extern unsigned int dc_number;
|
||||||
#define current_dive (get_dive(selected_dive))
|
#define current_dive (get_dive(selected_dive))
|
||||||
#define current_dc (get_dive_dc(current_dive, dc_number))
|
#define current_dc (get_dive_dc(current_dive, dc_number))
|
||||||
|
|
||||||
static inline struct dive *get_gps_location(int nr, struct dive_table *table)
|
|
||||||
{
|
|
||||||
if (nr >= table->nr || nr < 0)
|
|
||||||
return NULL;
|
|
||||||
return table->dives[nr];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct dive *get_dive(int nr)
|
static inline struct dive *get_dive(int nr)
|
||||||
{
|
{
|
||||||
if (nr >= dive_table.nr || nr < 0)
|
if (nr >= dive_table.nr || nr < 0)
|
||||||
|
@ -515,6 +494,21 @@ static inline struct dive *get_dive_from_table(int nr, struct dive_table *dt)
|
||||||
return dt->dives[nr];
|
return dt->dives[nr];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct dive_site *get_dive_site_for_dive(struct dive *dive)
|
||||||
|
{
|
||||||
|
if (dive)
|
||||||
|
return get_dive_site_by_uuid(dive->dive_site_uuid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *get_dive_location(struct dive *dive)
|
||||||
|
{
|
||||||
|
struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid);
|
||||||
|
if (ds && ds->name)
|
||||||
|
return ds->name;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned int number_of_computers(struct dive *dive)
|
static inline unsigned int number_of_computers(struct dive *dive)
|
||||||
{
|
{
|
||||||
unsigned int total_number = 0;
|
unsigned int total_number = 0;
|
||||||
|
@ -613,6 +607,16 @@ static inline int get_idx_by_uniq_id(int id)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool dive_site_has_gps_location(struct dive_site *ds)
|
||||||
|
{
|
||||||
|
return ds && (ds->latitude.udeg || ds->longitude.udeg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dive_has_gps_location(struct dive *dive)
|
||||||
|
{
|
||||||
|
return dive_site_has_gps_location(get_dive_site_by_uuid(dive->dive_site_uuid));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -678,9 +678,9 @@ void add_dive_to_trip(struct dive *dive, dive_trip_t *trip)
|
||||||
dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive)
|
dive_trip_t *create_and_hookup_trip_from_dive(struct dive *dive)
|
||||||
{
|
{
|
||||||
dive_trip_t *dive_trip = calloc(1, sizeof(dive_trip_t));
|
dive_trip_t *dive_trip = calloc(1, sizeof(dive_trip_t));
|
||||||
|
|
||||||
dive_trip->when = dive->when;
|
dive_trip->when = dive->when;
|
||||||
if (dive->location)
|
dive_trip->location = copy_string(get_dive_location(dive));
|
||||||
dive_trip->location = strdup(dive->location);
|
|
||||||
insert_trip(&dive_trip);
|
insert_trip(&dive_trip);
|
||||||
|
|
||||||
dive->tripflag = IN_TRIP;
|
dive->tripflag = IN_TRIP;
|
||||||
|
@ -713,8 +713,8 @@ void autogroup_dives(void)
|
||||||
if (lastdive && dive->when < lastdive->when + TRIP_THRESHOLD) {
|
if (lastdive && dive->when < lastdive->when + TRIP_THRESHOLD) {
|
||||||
dive_trip_t *trip = lastdive->divetrip;
|
dive_trip_t *trip = lastdive->divetrip;
|
||||||
add_dive_to_trip(dive, trip);
|
add_dive_to_trip(dive, trip);
|
||||||
if (dive->location && !trip->location)
|
if (get_dive_location(dive) && !trip->location)
|
||||||
trip->location = strdup(dive->location);
|
trip->location = copy_string(get_dive_location(dive));
|
||||||
lastdive = dive;
|
lastdive = dive;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -745,7 +745,6 @@ void delete_single_dive(int idx)
|
||||||
dive_table.dives[--dive_table.nr] = NULL;
|
dive_table.dives[--dive_table.nr] = NULL;
|
||||||
/* free all allocations */
|
/* free all allocations */
|
||||||
free(dive->dc.sample);
|
free(dive->dc.sample);
|
||||||
free((void *)dive->location);
|
|
||||||
free((void *)dive->notes);
|
free((void *)dive->notes);
|
||||||
free((void *)dive->divemaster);
|
free((void *)dive->divemaster);
|
||||||
free((void *)dive->buddy);
|
free((void *)dive->buddy);
|
||||||
|
|
118
divesite.c
Normal file
118
divesite.c
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/* divesite.c */
|
||||||
|
#include "divesite.h"
|
||||||
|
#include "dive.h"
|
||||||
|
|
||||||
|
struct dive_site_table dive_site_table;
|
||||||
|
|
||||||
|
/* there could be multiple sites of the same name - return the first one */
|
||||||
|
uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct dive_site *ds;
|
||||||
|
for_each_dive_site (i, ds) {
|
||||||
|
if (same_string(ds->name, name)) {
|
||||||
|
if (dsp)
|
||||||
|
*dsp = ds;
|
||||||
|
return ds->uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct dive_site *ds;
|
||||||
|
for_each_dive_site (i, ds) {
|
||||||
|
if (ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg) {
|
||||||
|
if (dsp)
|
||||||
|
*dsp = ds;
|
||||||
|
return ds->uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to create a uniqe ID - fingers crossed */
|
||||||
|
static uint32_t dive_site_getUniqId()
|
||||||
|
{
|
||||||
|
uint32_t id = 0;
|
||||||
|
|
||||||
|
while (id == 0 || get_dive_site_by_uuid(id))
|
||||||
|
id = random() + random();
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dive_site *alloc_dive_site()
|
||||||
|
{
|
||||||
|
int nr = dive_site_table.nr, allocated = dive_site_table.allocated;
|
||||||
|
struct dive_site **sites = dive_site_table.dive_sites;
|
||||||
|
|
||||||
|
if (nr >= allocated) {
|
||||||
|
allocated = (nr + 32) * 3 / 2;
|
||||||
|
sites = realloc(sites, allocated * sizeof(struct dive_site *));
|
||||||
|
if (!sites)
|
||||||
|
exit(1);
|
||||||
|
dive_site_table.dive_sites = sites;
|
||||||
|
dive_site_table.allocated = allocated;
|
||||||
|
}
|
||||||
|
struct dive_site *ds = calloc(1, sizeof(*ds));
|
||||||
|
if (!ds)
|
||||||
|
exit(1);
|
||||||
|
sites[nr] = ds;
|
||||||
|
dive_site_table.nr = nr + 1;
|
||||||
|
ds->uuid = dive_site_getUniqId();
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void delete_dive_site(uint32_t id)
|
||||||
|
{
|
||||||
|
int nr = dive_site_table.nr;
|
||||||
|
for (int i = 0; i < nr; i++) {
|
||||||
|
struct dive_site *ds = get_dive_site(i);
|
||||||
|
if (ds->uuid == id) {
|
||||||
|
free(ds->name);
|
||||||
|
free(ds->notes);
|
||||||
|
free(ds);
|
||||||
|
if (nr - 1 > i)
|
||||||
|
memmove(&dive_site_table.dive_sites[i],
|
||||||
|
&dive_site_table.dive_sites[i+1],
|
||||||
|
(nr - 1 - i) * sizeof(dive_site_table.dive_sites[0]));
|
||||||
|
dive_site_table.nr = nr - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a new site and add it to the table */
|
||||||
|
uint32_t create_dive_site(const char *name)
|
||||||
|
{
|
||||||
|
struct dive_site *ds = alloc_dive_site();
|
||||||
|
ds->name = copy_string(name);
|
||||||
|
|
||||||
|
return ds->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* same as before, but with GPS data */
|
||||||
|
uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude)
|
||||||
|
{
|
||||||
|
struct dive_site *ds = alloc_dive_site();
|
||||||
|
ds->uuid = dive_site_getUniqId();
|
||||||
|
ds->name = copy_string(name);
|
||||||
|
ds->latitude = latitude;
|
||||||
|
ds->longitude = longitude;
|
||||||
|
|
||||||
|
return ds->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* a uuid is always present - but if all the other fields are empty, the dive site is pointless */
|
||||||
|
bool dive_site_is_empty(struct dive_site *ds)
|
||||||
|
{
|
||||||
|
return same_string(ds->name, "") &&
|
||||||
|
same_string(ds->description, "") &&
|
||||||
|
same_string(ds->notes, "") &&
|
||||||
|
ds->latitude.udeg == 0 &&
|
||||||
|
ds->longitude.udeg == 0;
|
||||||
|
}
|
61
divesite.h
Normal file
61
divesite.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#ifndef DIVESITE_H
|
||||||
|
#define DIVESITE_H
|
||||||
|
|
||||||
|
#include "units.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#else
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct dive_site
|
||||||
|
{
|
||||||
|
uint32_t uuid;
|
||||||
|
char *name;
|
||||||
|
degrees_t latitude, longitude;
|
||||||
|
char *description;
|
||||||
|
char *notes;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dive_site_table {
|
||||||
|
int nr, allocated;
|
||||||
|
struct dive_site **dive_sites;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct dive_site_table dive_site_table;
|
||||||
|
|
||||||
|
static inline struct dive_site *get_dive_site(int nr)
|
||||||
|
{
|
||||||
|
if (nr >= dive_site_table.nr || nr < 0)
|
||||||
|
return NULL;
|
||||||
|
return dive_site_table.dive_sites[nr];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iterate over each dive site */
|
||||||
|
#define for_each_dive_site(_i, _x) \
|
||||||
|
for ((_i) = 0; ((_x) = get_dive_site(_i)) != NULL; (_i)++)
|
||||||
|
|
||||||
|
static inline struct dive_site *get_dive_site_by_uuid(uint32_t uuid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct dive_site *ds;
|
||||||
|
for_each_dive_site (i, ds)
|
||||||
|
if (ds->uuid == uuid)
|
||||||
|
return get_dive_site(i);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dive_site *alloc_dive_site();
|
||||||
|
void delete_dive_site(uint32_t id);
|
||||||
|
uint32_t create_dive_site(const char *name);
|
||||||
|
uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude);
|
||||||
|
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);
|
||||||
|
bool dive_site_is_empty(struct dive_site *ds);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // DIVESITE_H
|
|
@ -121,21 +121,24 @@ static void parse_dives (int log_version, const unsigned char *buf, unsigned int
|
||||||
|
|
||||||
// Dive location, assemble Location and Place
|
// Dive location, assemble Location and Place
|
||||||
unsigned int len, place_len;
|
unsigned int len, place_len;
|
||||||
|
char *location;
|
||||||
len = array_uint32_le(buf + ptr);
|
len = array_uint32_le(buf + ptr);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
place_len = array_uint32_le(buf + ptr + len);
|
place_len = array_uint32_le(buf + ptr + len);
|
||||||
|
|
||||||
if (len && place_len) {
|
if (len && place_len) {
|
||||||
dive->location = malloc(len + place_len + 4);
|
location = malloc(len + place_len + 4);
|
||||||
memset(dive->location, 0, len + place_len + 4);
|
memset(location, 0, len + place_len + 4);
|
||||||
memcpy(dive->location, buf + ptr, len);
|
memcpy(location, buf + ptr, len);
|
||||||
memcpy(dive->location + len, ", ", 2);
|
memcpy(location + len, ", ", 2);
|
||||||
memcpy(dive->location + len + 2, buf + ptr + len + 4, place_len);
|
memcpy(location + len + 2, buf + ptr + len + 4, place_len);
|
||||||
} else if (len) {
|
} else if (len) {
|
||||||
dive->location = strndup(buf + ptr, len);
|
location = strndup(buf + ptr, len);
|
||||||
} else if (place_len) {
|
} else if (place_len) {
|
||||||
dive->location = strndup(buf + ptr + len + 4, place_len);
|
location = strndup(buf + ptr + len + 4, place_len);
|
||||||
}
|
}
|
||||||
|
dive->dive_site_uuid = create_dive_site(location);
|
||||||
|
free(location);
|
||||||
|
|
||||||
ptr += len + 4 + place_len;
|
ptr += len + 4 + place_len;
|
||||||
|
|
||||||
|
|
102
load-git.c
102
load-git.c
|
@ -23,13 +23,6 @@ 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 degrees_t parse_degrees(char *buf, char **end);
|
||||||
static void parse_dive_gps(char *line, struct membuffer *str, void *_dive)
|
|
||||||
{
|
|
||||||
struct dive *dive = _dive;
|
|
||||||
|
|
||||||
dive->latitude = parse_degrees(line, &line);
|
|
||||||
dive->longitude = parse_degrees(line, &line);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *get_utf8(struct membuffer *b)
|
static char *get_utf8(struct membuffer *b)
|
||||||
{
|
{
|
||||||
|
@ -145,8 +138,43 @@ static int get_index(const char *line)
|
||||||
static int get_hex(const char *line)
|
static int get_hex(const char *line)
|
||||||
{ return strtoul(line, NULL, 16); }
|
{ return strtoul(line, NULL, 16); }
|
||||||
|
|
||||||
|
static void parse_dive_gps(char *line, struct membuffer *str, void *_dive)
|
||||||
|
{
|
||||||
|
uint32_t uuid;
|
||||||
|
degrees_t latitude = parse_degrees(line, &line);
|
||||||
|
degrees_t longitude = parse_degrees(line, &line);
|
||||||
|
struct dive *dive = _dive;
|
||||||
|
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||||
|
if (!ds) {
|
||||||
|
uuid = get_dive_site_uuid_by_gps(latitude, longitude, NULL);
|
||||||
|
if (!uuid)
|
||||||
|
uuid = create_dive_site_with_gps("", latitude, longitude);
|
||||||
|
dive->dive_site_uuid = uuid;
|
||||||
|
} else {
|
||||||
|
ds->latitude = latitude;
|
||||||
|
ds->longitude = longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_dive_location(char *line, struct membuffer *str, void *_dive)
|
static void parse_dive_location(char *line, struct membuffer *str, void *_dive)
|
||||||
{ struct dive *dive = _dive; dive->location = get_utf8(str); }
|
{
|
||||||
|
uint32_t uuid;
|
||||||
|
char *name = get_utf8(str);
|
||||||
|
struct dive *dive = _dive;
|
||||||
|
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||||
|
fprintf(stderr, "looking for a site named {%s} ", name);
|
||||||
|
if (!ds) {
|
||||||
|
uuid = get_dive_site_uuid_by_name(name, NULL);
|
||||||
|
if (!uuid) { fprintf(stderr, "found none, creating\n");
|
||||||
|
uuid = create_dive_site(name);
|
||||||
|
} else { fprintf(stderr, "found one with uuid %8x\n", uuid); }
|
||||||
|
dive->dive_site_uuid = uuid;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "dive had site with uuid %8x and name {%s}\n", ds->uuid, ds->name);
|
||||||
|
ds->name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_dive_divemaster(char *line, struct membuffer *str, void *_dive)
|
static void parse_dive_divemaster(char *line, struct membuffer *str, void *_dive)
|
||||||
{ struct dive *dive = _dive; dive->divemaster = get_utf8(str); }
|
{ struct dive *dive = _dive; dive->divemaster = get_utf8(str); }
|
||||||
|
@ -160,6 +188,9 @@ static void parse_dive_suit(char *line, struct membuffer *str, void *_dive)
|
||||||
static void parse_dive_notes(char *line, struct membuffer *str, void *_dive)
|
static void parse_dive_notes(char *line, struct membuffer *str, void *_dive)
|
||||||
{ struct dive *dive = _dive; dive->notes = get_utf8(str); }
|
{ struct dive *dive = _dive; dive->notes = get_utf8(str); }
|
||||||
|
|
||||||
|
static void parse_dive_divesiteid(char *line, struct membuffer *str, void *_dive)
|
||||||
|
{ struct dive *dive = _dive; dive->dive_site_uuid = get_hex(line); }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can have multiple tags in the membuffer. They are separated by
|
* We can have multiple tags in the membuffer. They are separated by
|
||||||
* NUL bytes.
|
* NUL bytes.
|
||||||
|
@ -205,6 +236,24 @@ static void parse_dive_visibility(char *line, struct membuffer *str, void *_dive
|
||||||
static void parse_dive_notrip(char *line, struct membuffer *str, void *_dive)
|
static void parse_dive_notrip(char *line, struct membuffer *str, void *_dive)
|
||||||
{ struct dive *dive = _dive; dive->tripflag = NO_TRIP; }
|
{ struct dive *dive = _dive; dive->tripflag = NO_TRIP; }
|
||||||
|
|
||||||
|
static void parse_site_description(char *line, struct membuffer *str, void *_ds)
|
||||||
|
{ struct dive_site *ds = _ds; ds->description = strdup(mb_cstring(str)); }
|
||||||
|
|
||||||
|
static void parse_site_name(char *line, struct membuffer *str, void *_ds)
|
||||||
|
{ struct dive_site *ds = _ds; ds->name = strdup(mb_cstring(str)); }
|
||||||
|
|
||||||
|
static void parse_site_notes(char *line, struct membuffer *str, void *_ds)
|
||||||
|
{ 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)
|
||||||
|
{
|
||||||
|
struct dive_site *ds = _ds;
|
||||||
|
|
||||||
|
ds->latitude = parse_degrees(line, &line);
|
||||||
|
ds->longitude = parse_degrees(line, &line);
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse key=val parts of samples and cylinders etc */
|
/* Parse key=val parts of samples and cylinders etc */
|
||||||
static char *parse_keyvalue_entry(void (*fn)(void *, const char *, const char *), void *fndata, char *line)
|
static char *parse_keyvalue_entry(void (*fn)(void *, const char *, const char *), void *fndata, char *line)
|
||||||
{
|
{
|
||||||
|
@ -672,7 +721,7 @@ static void parse_settings_userid(char *line, struct membuffer *str, void *_unus
|
||||||
* *can* do some day. And if we do change the version, this warning will show if
|
* *can* do some day. And if we do change the version, this warning will show if
|
||||||
* you read with a version of subsurface that doesn't know about it.
|
* you read with a version of subsurface that doesn't know about it.
|
||||||
*/
|
*/
|
||||||
#define VERSION 2
|
#define VERSION 3
|
||||||
static void parse_settings_version(char *line, struct membuffer *str, void *_unused)
|
static void parse_settings_version(char *line, struct membuffer *str, void *_unused)
|
||||||
{
|
{
|
||||||
int version = atoi(line);
|
int version = atoi(line);
|
||||||
|
@ -783,7 +832,7 @@ static void divecomputer_parser(char *line, struct membuffer *str, void *_dc)
|
||||||
struct keyword_action dive_action[] = {
|
struct keyword_action dive_action[] = {
|
||||||
#undef D
|
#undef D
|
||||||
#define D(x) { #x, parse_dive_ ## x }
|
#define D(x) { #x, parse_dive_ ## x }
|
||||||
D(airtemp), D(buddy), D(cylinder), D(divemaster), D(duration),
|
D(airtemp), D(buddy), D(cylinder), D(divemaster), D(divesiteid), D(duration),
|
||||||
D(gps), D(location), D(notes), D(notrip), D(rating), D(suit),
|
D(gps), D(location), D(notes), D(notrip), D(rating), D(suit),
|
||||||
D(tags), D(visibility), D(watertemp), D(weightsystem)
|
D(tags), D(visibility), D(watertemp), D(weightsystem)
|
||||||
};
|
};
|
||||||
|
@ -793,6 +842,18 @@ static void dive_parser(char *line, struct membuffer *str, void *_dive)
|
||||||
match_action(line, str, _dive, dive_action, ARRAY_SIZE(dive_action));
|
match_action(line, str, _dive, dive_action, ARRAY_SIZE(dive_action));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* These need to be sorted! */
|
||||||
|
struct keyword_action site_action[] = {
|
||||||
|
#undef D
|
||||||
|
#define D(x) { #x, parse_site_ ## x }
|
||||||
|
D(description), D(gps), D(name), D(notes)
|
||||||
|
};
|
||||||
|
|
||||||
|
static void site_parser(char *line, struct membuffer *str, void *_ds)
|
||||||
|
{
|
||||||
|
match_action(line, str, _ds, site_action, ARRAY_SIZE(site_action));
|
||||||
|
}
|
||||||
|
|
||||||
/* These need to be sorted! */
|
/* These need to be sorted! */
|
||||||
struct keyword_action trip_action[] = {
|
struct keyword_action trip_action[] = {
|
||||||
#undef D
|
#undef D
|
||||||
|
@ -1190,6 +1251,9 @@ static int walk_tree_directory(const char *root, const git_tree_entry *entry)
|
||||||
if (!strcmp(name, "Pictures"))
|
if (!strcmp(name, "Pictures"))
|
||||||
return picture_directory(root, name);
|
return picture_directory(root, name);
|
||||||
|
|
||||||
|
if (!strcmp(name, "01-Divesites"))
|
||||||
|
return GIT_WALK_OK;
|
||||||
|
|
||||||
while (isdigit(c = name[digits]))
|
while (isdigit(c = name[digits]))
|
||||||
digits++;
|
digits++;
|
||||||
|
|
||||||
|
@ -1284,6 +1348,20 @@ static int parse_dive_entry(git_repository *repo, const git_tree_entry *entry, c
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_site_entry(git_repository *repo, const git_tree_entry *entry, const char *suffix)
|
||||||
|
{
|
||||||
|
if (*suffix == '\0')
|
||||||
|
return report_error("Dive site without uuid");
|
||||||
|
struct dive_site *ds = alloc_dive_site();
|
||||||
|
ds->uuid = strtol(suffix, NULL, 16);
|
||||||
|
git_blob *blob = git_tree_entry_blob(repo, entry);
|
||||||
|
if (!blob)
|
||||||
|
return report_error("Unable to read dive site file");
|
||||||
|
for_each_line(blob, site_parser, ds);
|
||||||
|
git_blob_free(blob);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_trip_entry(git_repository *repo, const git_tree_entry *entry)
|
static int parse_trip_entry(git_repository *repo, const git_tree_entry *entry)
|
||||||
{
|
{
|
||||||
git_blob *blob = git_tree_entry_blob(repo, entry);
|
git_blob *blob = git_tree_entry_blob(repo, entry);
|
||||||
|
@ -1343,7 +1421,6 @@ static int walk_tree_file(const char *root, const git_tree_entry *entry, git_rep
|
||||||
struct dive *dive = active_dive;
|
struct dive *dive = active_dive;
|
||||||
dive_trip_t *trip = active_trip;
|
dive_trip_t *trip = active_trip;
|
||||||
const char *name = git_tree_entry_name(entry);
|
const char *name = git_tree_entry_name(entry);
|
||||||
|
|
||||||
switch (*name) {
|
switch (*name) {
|
||||||
/* Picture file? They are saved as time offsets in the dive */
|
/* Picture file? They are saved as time offsets in the dive */
|
||||||
case '-': case '+':
|
case '-': case '+':
|
||||||
|
@ -1356,6 +1433,9 @@ static int walk_tree_file(const char *root, const git_tree_entry *entry, git_rep
|
||||||
if (dive && !strncmp(name, "Dive", 4))
|
if (dive && !strncmp(name, "Dive", 4))
|
||||||
return parse_dive_entry(repo, entry, name+4);
|
return parse_dive_entry(repo, entry, name+4);
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
if (!strncmp(name, "Site", 4))
|
||||||
|
return parse_site_entry(repo, entry, name + 5);
|
||||||
case '0':
|
case '0':
|
||||||
if (trip && !strcmp(name, "00-Trip"))
|
if (trip && !strcmp(name, "00-Trip"))
|
||||||
return parse_trip_entry(repo, entry);
|
return parse_trip_entry(repo, entry);
|
||||||
|
|
205
parse-xml.c
205
parse-xml.c
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
int verbose, quit;
|
int verbose, quit;
|
||||||
int metric = 1;
|
int metric = 1;
|
||||||
|
int last_xml_version = -1;
|
||||||
|
|
||||||
static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params);
|
static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params);
|
||||||
|
|
||||||
|
@ -128,6 +129,7 @@ const struct units IMPERIAL_units = IMPERIAL_UNITS;
|
||||||
#define MAX_EVENT_NAME 128
|
#define MAX_EVENT_NAME 128
|
||||||
static struct divecomputer *cur_dc;
|
static struct divecomputer *cur_dc;
|
||||||
static struct dive *cur_dive;
|
static struct dive *cur_dive;
|
||||||
|
static struct dive_site *cur_dive_site;
|
||||||
static dive_trip_t *cur_trip = NULL;
|
static dive_trip_t *cur_trip = NULL;
|
||||||
static struct sample *cur_sample;
|
static struct sample *cur_sample;
|
||||||
static struct picture *cur_picture;
|
static struct picture *cur_picture;
|
||||||
|
@ -933,10 +935,8 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu
|
||||||
return;
|
return;
|
||||||
if (MATCH("sensor3.sample", double_to_o2pressure, &sample->o2sensor[2])) // up to 3 CCR sensors
|
if (MATCH("sensor3.sample", double_to_o2pressure, &sample->o2sensor[2])) // up to 3 CCR sensors
|
||||||
return;
|
return;
|
||||||
if (MATCH("po2.sample", double_to_o2pressure, &sample->setpoint)) {
|
if (MATCH("po2.sample", double_to_o2pressure, &sample->setpoint))
|
||||||
cur_dive->dc.divemode = CCR;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (MATCH("heartbeat", get_uint8, &sample->heartbeat))
|
if (MATCH("heartbeat", get_uint8, &sample->heartbeat))
|
||||||
return;
|
return;
|
||||||
if (MATCH("bearing", get_bearing, &sample->bearing))
|
if (MATCH("bearing", get_bearing, &sample->bearing))
|
||||||
|
@ -968,22 +968,21 @@ void try_to_fill_userid(const char *name, char *buf)
|
||||||
|
|
||||||
static const char *country, *city;
|
static const char *country, *city;
|
||||||
|
|
||||||
static void divinglog_place(char *place, char **location)
|
static void divinglog_place(char *place, uint32_t *uuid)
|
||||||
{
|
{
|
||||||
char buffer[1024], *p;
|
char buffer[1024], *p;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = snprintf(buffer, sizeof(buffer),
|
snprintf(buffer, sizeof(buffer),
|
||||||
"%s%s%s%s%s",
|
"%s%s%s%s%s",
|
||||||
place,
|
place,
|
||||||
city ? ", " : "",
|
city ? ", " : "",
|
||||||
city ? city : "",
|
city ? city : "",
|
||||||
country ? ", " : "",
|
country ? ", " : "",
|
||||||
country ? country : "");
|
country ? country : "");
|
||||||
|
*uuid = get_dive_site_uuid_by_name(buffer, NULL);
|
||||||
p = malloc(len + 1);
|
if (*uuid == 0)
|
||||||
memcpy(p, buffer, len + 1);
|
*uuid = create_dive_site(buffer);
|
||||||
*location = p;
|
|
||||||
|
|
||||||
city = NULL;
|
city = NULL;
|
||||||
country = NULL;
|
country = NULL;
|
||||||
|
@ -1005,7 +1004,7 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf)
|
||||||
MATCH("names.buddy", utf8_string, &dive->buddy) ||
|
MATCH("names.buddy", utf8_string, &dive->buddy) ||
|
||||||
MATCH("name.country", utf8_string, &country) ||
|
MATCH("name.country", utf8_string, &country) ||
|
||||||
MATCH("name.city", utf8_string, &city) ||
|
MATCH("name.city", utf8_string, &city) ||
|
||||||
MATCH("name.place", divinglog_place, &dive->location) ||
|
MATCH("name.place", divinglog_place, &dive->dive_site_uuid) ||
|
||||||
0;
|
0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,23 +1126,112 @@ 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);
|
||||||
dive->latitude = parse_degrees(buffer, &end);
|
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||||
|
if (!ds) {
|
||||||
|
dive->dive_site_uuid = create_dive_site_with_gps(NULL, latitude, (degrees_t){0});
|
||||||
|
} else {
|
||||||
|
if (ds->latitude.udeg && ds->latitude.udeg != latitude.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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||||
|
if (!ds) {
|
||||||
|
dive->dive_site_uuid = create_dive_site_with_gps(NULL, (degrees_t){0}, longitude);
|
||||||
|
} else {
|
||||||
|
if (ds->longitude.udeg && ds->longitude.udeg != longitude.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;
|
||||||
|
}
|
||||||
|
|
||||||
dive->longitude = parse_degrees(buffer, &end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gps_location(char *buffer, struct dive *dive)
|
static void gps_location(char *buffer, struct dive_site *ds)
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
dive->latitude = parse_degrees(buffer, &end);
|
ds->latitude = parse_degrees(buffer, &end);
|
||||||
dive->longitude = parse_degrees(end, &end);
|
ds->longitude = parse_degrees(end, &end);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
fprintf(stderr, "got lat %f lon %f\n", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0);
|
||||||
|
uint32_t uuid = dive->dive_site_uuid;
|
||||||
|
if (uuid == 0) {
|
||||||
|
uuid = get_dive_site_uuid_by_gps(latitude, longitude, &ds);
|
||||||
|
if (ds) {
|
||||||
|
fprintf(stderr, "found dive site {%s} with these coordinates\n", ds->name);
|
||||||
|
dive->dive_site_uuid = uuid;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "found no uuid in dive, no existing dive site with these coordinates, creating a new divesite without name and above GPS\n");
|
||||||
|
dive->dive_site_uuid = create_dive_site_with_gps("", latitude, longitude);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "found uuid in dive, checking to see if we should add GPS\n");
|
||||||
|
struct dive_site *ds = get_dive_site_by_uuid(uuid);
|
||||||
|
if (dive_site_has_gps_location(ds) &&
|
||||||
|
(latitude.udeg != 0 || longitude.udeg != 0) &&
|
||||||
|
(ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) {
|
||||||
|
// Houston, we have a problem
|
||||||
|
fprintf(stderr, "dive site uuid in dive, but gps location (%10.6f/%10.6f) different from dive location (%10.6f/%10.6f)\n",
|
||||||
|
ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0,
|
||||||
|
latitude.udeg / 1000000.0, longitude.udeg / 1000000.0);
|
||||||
|
int len = ds->notes ? strlen(ds->notes) : 0;
|
||||||
|
len += sizeof("\nalternative coordinates") + 24;
|
||||||
|
char *notes = malloc(len);
|
||||||
|
snprintf(notes, len, "%s\nalternative coordinates %11.6f/%11.6f",
|
||||||
|
ds->notes ?: "", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0);
|
||||||
|
free(ds->notes);
|
||||||
|
ds->notes = notes;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "let's add the gps coordinates to divesite with uuid %8x and name %s\n", ds->uuid, ds->name ?: "(none)");
|
||||||
|
ds->latitude = latitude;
|
||||||
|
ds->longitude = longitude;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_dive_site(char *buffer, struct dive *dive)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "add_dive_site with name %s\n", buffer);
|
||||||
|
int size = trimspace(buffer);
|
||||||
|
if(size) {
|
||||||
|
uint32_t uuid = dive->dive_site_uuid;
|
||||||
|
struct dive_site *ds = get_dive_site_by_uuid(uuid);
|
||||||
|
if (uuid && !ds) {
|
||||||
|
// that's strange - we have a uuid but it doesn't exist - let's just ignore it
|
||||||
|
fprintf(stderr, "dive contains a non-existing dive site uuid %x\n", dive->dive_site_uuid);
|
||||||
|
uuid = 0;
|
||||||
|
}
|
||||||
|
if (!uuid)
|
||||||
|
// if the dive doesn't have a uuid, check if there's already a dive site by this name
|
||||||
|
uuid = get_dive_site_uuid_by_name(buffer, &ds);
|
||||||
|
if (ds) {
|
||||||
|
// we have a uuid, let's hope there isn't a different name
|
||||||
|
fprintf(stderr, "have existing site with name {%s} gps %f/%f ", ds->name, ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0);
|
||||||
|
if (same_string(ds->name, "")) {
|
||||||
|
fprintf(stderr, "so now add name {%s}\n", buffer);
|
||||||
|
ds->name = copy_string(buffer);
|
||||||
|
} else if (!same_string(ds->name, buffer)) {
|
||||||
|
// coin toss, let's just keep the first name we found
|
||||||
|
fprintf(stderr, "which means the dive already links to dive site of different name {%s} / {%s}\n", ds->name, buffer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "no uuid, create new dive site with name {%s}\n", buffer);
|
||||||
|
dive->dive_site_uuid = create_dive_site(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gps_picture_location(char *buffer, struct picture *pic)
|
static void gps_picture_location(char *buffer, struct picture *pic)
|
||||||
|
@ -1173,7 +1261,8 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (MATCH("divesiteid", hex_value, &dive->dive_site_uuid))
|
||||||
|
return;
|
||||||
if (MATCH("number", get_index, &dive->number))
|
if (MATCH("number", get_index, &dive->number))
|
||||||
return;
|
return;
|
||||||
if (MATCH("tags", divetags, &dive->tag_list))
|
if (MATCH("tags", divetags, &dive->tag_list))
|
||||||
|
@ -1203,9 +1292,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
|
||||||
return;
|
return;
|
||||||
if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end))
|
if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end))
|
||||||
return;
|
return;
|
||||||
if (MATCH("gps", gps_location, dive))
|
if (MATCH("gps", gps_in_dive, dive))
|
||||||
return;
|
return;
|
||||||
if (MATCH("Place", gps_location, dive))
|
if (MATCH("Place", gps_in_dive, dive))
|
||||||
return;
|
return;
|
||||||
if (MATCH("latitude", gps_lat, dive))
|
if (MATCH("latitude", gps_lat, dive))
|
||||||
return;
|
return;
|
||||||
|
@ -1219,9 +1308,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
|
||||||
return;
|
return;
|
||||||
if (MATCH("lon", gps_long, dive))
|
if (MATCH("lon", gps_long, dive))
|
||||||
return;
|
return;
|
||||||
if (MATCH("location", utf8_string, &dive->location))
|
if (MATCH("location", add_dive_site, dive))
|
||||||
return;
|
return;
|
||||||
if (MATCH("name.dive", utf8_string, &dive->location))
|
if (MATCH("name.dive", add_dive_site, dive))
|
||||||
return;
|
return;
|
||||||
if (MATCH("suit", utf8_string, &dive->suit))
|
if (MATCH("suit", utf8_string, &dive->suit))
|
||||||
return;
|
return;
|
||||||
|
@ -1290,6 +1379,27 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char *
|
||||||
nonmatch("trip", name, buf);
|
nonmatch("trip", name, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We're processing a divesite entry - try to fill the components */
|
||||||
|
static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, char *buf)
|
||||||
|
{
|
||||||
|
start_match("divesite", name, buf);
|
||||||
|
|
||||||
|
struct dive_site *ds = *ds_p;
|
||||||
|
|
||||||
|
if (MATCH("uuid", hex_value, &ds->uuid))
|
||||||
|
return;
|
||||||
|
if (MATCH("name", utf8_string, &ds->name))
|
||||||
|
return;
|
||||||
|
if (MATCH("description", utf8_string, &ds->description))
|
||||||
|
return;
|
||||||
|
if (MATCH("notes", utf8_string, &ds->notes))
|
||||||
|
return;
|
||||||
|
if (MATCH("gps", gps_location, ds))
|
||||||
|
return;
|
||||||
|
|
||||||
|
nonmatch("divesite", name, buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* While in some formats file boundaries are dive boundaries, in many
|
* While in some formats file boundaries are dive boundaries, in many
|
||||||
* others (as for example in our native format) there are
|
* others (as for example in our native format) there are
|
||||||
|
@ -1305,7 +1415,7 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char *
|
||||||
static bool is_dive(void)
|
static bool is_dive(void)
|
||||||
{
|
{
|
||||||
return (cur_dive &&
|
return (cur_dive &&
|
||||||
(cur_dive->location || cur_dive->when || cur_dive->dc.samples));
|
(cur_dive->dive_site_uuid || cur_dive->when || cur_dive->dc.samples));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reset_dc_info(struct divecomputer *dc)
|
static void reset_dc_info(struct divecomputer *dc)
|
||||||
|
@ -1349,6 +1459,32 @@ static void dc_settings_end(void)
|
||||||
reset_dc_settings();
|
reset_dc_settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dive_site_start(void)
|
||||||
|
{
|
||||||
|
if (cur_dive_site)
|
||||||
|
return;
|
||||||
|
cur_dive_site = calloc(1, sizeof(struct dive_site));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dive_site_end(void)
|
||||||
|
{
|
||||||
|
if (!cur_dive_site)
|
||||||
|
return;
|
||||||
|
if (cur_dive_site->uuid) {
|
||||||
|
uint32_t tmp = create_dive_site_with_gps(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude);
|
||||||
|
struct dive_site *ds = get_dive_site_by_uuid(tmp);
|
||||||
|
ds->uuid = cur_dive_site->uuid;
|
||||||
|
ds->notes = cur_dive_site->notes;
|
||||||
|
ds->description = cur_dive_site->description;
|
||||||
|
if (verbose > 3)
|
||||||
|
printf("completed dive site uuid %x8 name {%s}\n", ds->uuid, ds->name);
|
||||||
|
}
|
||||||
|
free(cur_dive_site);
|
||||||
|
cur_dive_site = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we need to add the code to parse the parts of the divesite enry
|
||||||
|
|
||||||
static void dive_start(void)
|
static void dive_start(void)
|
||||||
{
|
{
|
||||||
if (cur_dive)
|
if (cur_dive)
|
||||||
|
@ -1529,6 +1665,9 @@ static void userid_stop(void)
|
||||||
|
|
||||||
static void entry(const char *name, char *buf)
|
static void entry(const char *name, char *buf)
|
||||||
{
|
{
|
||||||
|
if (!strncmp(name, "version.program", sizeof("version.program") - 1) ||
|
||||||
|
!strncmp(name, "version.divelog", sizeof("version.divelog") - 1))
|
||||||
|
last_xml_version = atoi(buf);
|
||||||
if (in_userid) {
|
if (in_userid) {
|
||||||
try_to_fill_userid(name, buf);
|
try_to_fill_userid(name, buf);
|
||||||
return;
|
return;
|
||||||
|
@ -1538,6 +1677,10 @@ static void entry(const char *name, char *buf)
|
||||||
try_to_match_autogroup(name, buf);
|
try_to_match_autogroup(name, buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (cur_dive_site) {
|
||||||
|
try_to_fill_dive_site(&cur_dive_site, name, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!cur_event.deleted) {
|
if (!cur_event.deleted) {
|
||||||
try_to_fill_event(name, buf);
|
try_to_fill_event(name, buf);
|
||||||
return;
|
return;
|
||||||
|
@ -1666,6 +1809,7 @@ static struct nesting {
|
||||||
} nesting[] = {
|
} nesting[] = {
|
||||||
{ "divecomputerid", dc_settings_start, dc_settings_end },
|
{ "divecomputerid", dc_settings_start, dc_settings_end },
|
||||||
{ "settings", settings_start, settings_end },
|
{ "settings", settings_start, settings_end },
|
||||||
|
{ "site", dive_site_start, dive_site_end },
|
||||||
{ "dive", dive_start, dive_end },
|
{ "dive", dive_start, dive_end },
|
||||||
{ "Dive", dive_start, dive_end },
|
{ "Dive", dive_start, dive_end },
|
||||||
{ "trip", trip_start, trip_end },
|
{ "trip", trip_start, trip_end },
|
||||||
|
@ -2291,7 +2435,7 @@ extern int shearwater_dive(void *param, int columns, char **data, char **column)
|
||||||
cur_dive->when = (time_t)(atol(data[1]));
|
cur_dive->when = (time_t)(atol(data[1]));
|
||||||
|
|
||||||
if (data[2])
|
if (data[2])
|
||||||
utf8_string(data[2], &cur_dive->location);
|
add_dive_site(data[2], cur_dive);
|
||||||
if (data[3])
|
if (data[3])
|
||||||
utf8_string(data[3], &cur_dive->buddy);
|
utf8_string(data[3], &cur_dive->buddy);
|
||||||
if (data[4])
|
if (data[4])
|
||||||
|
@ -2388,19 +2532,20 @@ extern int cobalt_visibility(void *handle, int columns, char **data, char **colu
|
||||||
|
|
||||||
extern int cobalt_location(void *handle, int columns, char **data, char **column)
|
extern int cobalt_location(void *handle, int columns, char **data, char **column)
|
||||||
{
|
{
|
||||||
|
static char *location = NULL;
|
||||||
if (data[0]) {
|
if (data[0]) {
|
||||||
if (cur_dive->location) {
|
if (location) {
|
||||||
char *tmp = malloc(strlen(cur_dive->location) + strlen(data[0]) + 4);
|
char *tmp = malloc(strlen(location) + strlen(data[0]) + 4);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return -1;
|
return -1;
|
||||||
sprintf(tmp, "%s / %s", cur_dive->location, data[0]);
|
sprintf(tmp, "%s / %s", location, data[0]);
|
||||||
free(cur_dive->location);
|
free(location);
|
||||||
cur_dive->location = tmp;
|
location = NULL;
|
||||||
|
cur_dive->dive_site_uuid = create_dive_site(tmp);
|
||||||
} else {
|
} else {
|
||||||
utf8_string(data[0], &cur_dive->location);
|
location = strdup(data[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,21 @@
|
||||||
|
|
||||||
CREATE_CSV_UPDATE_METHOD(BuddyCompletionModel, buddy);
|
CREATE_CSV_UPDATE_METHOD(BuddyCompletionModel, buddy);
|
||||||
CREATE_CSV_UPDATE_METHOD(DiveMasterCompletionModel, divemaster);
|
CREATE_CSV_UPDATE_METHOD(DiveMasterCompletionModel, divemaster);
|
||||||
CREATE_UPDATE_METHOD(LocationCompletionModel, location);
|
|
||||||
CREATE_UPDATE_METHOD(SuitCompletionModel, suit);
|
CREATE_UPDATE_METHOD(SuitCompletionModel, suit);
|
||||||
|
|
||||||
|
void LocationCompletionModel::updateModel()
|
||||||
|
{
|
||||||
|
QStringList list;
|
||||||
|
struct dive_site *ds;
|
||||||
|
int i = 0;
|
||||||
|
for_each_dive_site(i, ds) {
|
||||||
|
if (!list.contains(ds->name))
|
||||||
|
list.append(ds->name);
|
||||||
|
}
|
||||||
|
std::sort(list.begin(), list.end());
|
||||||
|
setStringList(list);
|
||||||
|
}
|
||||||
|
|
||||||
void TagCompletionModel::updateModel()
|
void TagCompletionModel::updateModel()
|
||||||
{
|
{
|
||||||
if (g_tag_list == NULL)
|
if (g_tag_list == NULL)
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>308</width>
|
<width>401</width>
|
||||||
<height>263</height>
|
<height>317</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -41,9 +41,9 @@
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="location">
|
<widget class="QCheckBox" name="divesite">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Location</string>
|
<string>Dive site</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -54,34 +54,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QCheckBox" name="gps">
|
|
||||||
<property name="text">
|
|
||||||
<string>GPS coordinates</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QCheckBox" name="divemaster">
|
|
||||||
<property name="text">
|
|
||||||
<string>Divemaster</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QCheckBox" name="buddy">
|
|
||||||
<property name="text">
|
|
||||||
<string>Buddy</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QCheckBox" name="rating">
|
|
||||||
<property name="text">
|
|
||||||
<string>Rating</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QCheckBox" name="visibility">
|
<widget class="QCheckBox" name="visibility">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -117,6 +89,27 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="divemaster">
|
||||||
|
<property name="text">
|
||||||
|
<string>Divemaster</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="buddy">
|
||||||
|
<property name="text">
|
||||||
|
<string>Buddy</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="rating">
|
||||||
|
<property name="text">
|
||||||
|
<string>Rating</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -249,7 +249,7 @@ bool LocationFilterModel::doFilter(struct dive *d, QModelIndex &index0, QAbstrac
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Checked means 'Show', Unchecked means 'Hide'.
|
// Checked means 'Show', Unchecked means 'Hide'.
|
||||||
QString location(d->location);
|
QString location(get_dive_location(d));
|
||||||
// only show empty location dives if the user checked that.
|
// only show empty location dives if the user checked that.
|
||||||
if (location.isEmpty()) {
|
if (location.isEmpty()) {
|
||||||
if (rowCount() > 0)
|
if (rowCount() > 0)
|
||||||
|
@ -277,7 +277,7 @@ void LocationFilterModel::repopulate()
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for_each_dive (i, dive) {
|
for_each_dive (i, dive) {
|
||||||
QString location(dive->location);
|
QString location(get_dive_location(dive));
|
||||||
if (!location.isEmpty() && !list.contains(location)) {
|
if (!location.isEmpty() && !list.contains(location)) {
|
||||||
list.append(location);
|
list.append(location);
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,10 +164,11 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit)
|
||||||
QList<int> selectedDiveIds;
|
QList<int> selectedDiveIds;
|
||||||
for_each_dive (idx, dive) {
|
for_each_dive (idx, dive) {
|
||||||
long lat_diff, lon_diff;
|
long lat_diff, lon_diff;
|
||||||
if (!dive_has_gps_location(dive))
|
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||||
|
if (!dive_site_has_gps_location(ds))
|
||||||
continue;
|
continue;
|
||||||
lat_diff = labs(dive->latitude.udeg - lat_udeg);
|
lat_diff = labs(ds->latitude.udeg - lat_udeg);
|
||||||
lon_diff = labs(dive->longitude.udeg - lon_udeg);
|
lon_diff = labs(ds->longitude.udeg - lon_udeg);
|
||||||
if (lat_diff > 180000000)
|
if (lat_diff > 180000000)
|
||||||
lat_diff = 360000000 - lat_diff;
|
lat_diff = 360000000 - lat_diff;
|
||||||
if (lon_diff > 180000000)
|
if (lon_diff > 180000000)
|
||||||
|
@ -186,6 +187,7 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit)
|
||||||
|
|
||||||
void GlobeGPS::repopulateLabels()
|
void GlobeGPS::repopulateLabels()
|
||||||
{
|
{
|
||||||
|
struct dive_site *ds;
|
||||||
if (loadedDives) {
|
if (loadedDives) {
|
||||||
model()->treeModel()->removeDocument(loadedDives);
|
model()->treeModel()->removeDocument(loadedDives);
|
||||||
delete loadedDives;
|
delete loadedDives;
|
||||||
|
@ -204,12 +206,16 @@ void GlobeGPS::repopulateLabels()
|
||||||
// don't show that flag, it's either already shown as displayed_dive
|
// don't show that flag, it's either already shown as displayed_dive
|
||||||
// or it's the one that we are moving right now...
|
// or it's the one that we are moving right now...
|
||||||
continue;
|
continue;
|
||||||
if (dive_has_gps_location(dive)) {
|
if (idx == -1)
|
||||||
GeoDataPlacemark *place = new GeoDataPlacemark(dive->location);
|
ds = &displayed_dive_site;
|
||||||
place->setCoordinate(dive->longitude.udeg / 1000000.0, dive->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree);
|
else
|
||||||
|
ds = get_dive_site_for_dive(dive);
|
||||||
|
if (dive_site_has_gps_location(ds)) {
|
||||||
|
GeoDataPlacemark *place = new GeoDataPlacemark(ds->name);
|
||||||
|
place->setCoordinate(ds->longitude.udeg / 1000000.0, ds->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree);
|
||||||
// don't add dive locations twice, unless they are at least 50m apart
|
// don't add dive locations twice, unless they are at least 50m apart
|
||||||
if (locationMap[QString(dive->location)]) {
|
if (locationMap[QString(ds->name)]) {
|
||||||
GeoDataCoordinates existingLocation = locationMap[QString(dive->location)]->coordinate();
|
GeoDataCoordinates existingLocation = locationMap[QString(ds->name)]->coordinate();
|
||||||
GeoDataLineString segment = GeoDataLineString();
|
GeoDataLineString segment = GeoDataLineString();
|
||||||
segment.append(existingLocation);
|
segment.append(existingLocation);
|
||||||
GeoDataCoordinates newLocation = place->coordinate();
|
GeoDataCoordinates newLocation = place->coordinate();
|
||||||
|
@ -220,7 +226,7 @@ void GlobeGPS::repopulateLabels()
|
||||||
if (dist < 0.05)
|
if (dist < 0.05)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
locationMap[QString(dive->location)] = place;
|
locationMap[QString(ds->name)] = place;
|
||||||
loadedDives->append(place);
|
loadedDives->append(place);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,23 +242,23 @@ void GlobeGPS::reload()
|
||||||
|
|
||||||
void GlobeGPS::centerOnCurrentDive()
|
void GlobeGPS::centerOnCurrentDive()
|
||||||
{
|
{
|
||||||
struct dive *dive = current_dive;
|
struct dive_site *ds = get_dive_site_for_dive(current_dive);
|
||||||
// dive has changed, if we had the 'editingDive', hide it.
|
// dive has changed, if we had the 'editingDive', hide it.
|
||||||
if (messageWidget->isVisible() && (!dive || dive_has_gps_location(dive) || amount_selected != 1))
|
if (messageWidget->isVisible() && (!ds || dive_site_has_gps_location(ds) || amount_selected != 1))
|
||||||
messageWidget->hide();
|
messageWidget->hide();
|
||||||
|
|
||||||
editingDiveLocation = false;
|
editingDiveLocation = false;
|
||||||
if (!dive)
|
if (!ds)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qreal longitude = dive->longitude.udeg / 1000000.0;
|
qreal longitude = ds->longitude.udeg / 1000000.0;
|
||||||
qreal latitude = dive->latitude.udeg / 1000000.0;
|
qreal latitude = ds->latitude.udeg / 1000000.0;
|
||||||
|
|
||||||
if ((!dive_has_gps_location(dive) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) {
|
if ((!dive_site_has_gps_location(ds) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) {
|
||||||
prepareForGetDiveCoordinates();
|
prepareForGetDiveCoordinates();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!dive_has_gps_location(dive)) {
|
if (!dive_site_has_gps_location(ds)) {
|
||||||
zoomOutForNoGPS();
|
zoomOutForNoGPS();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -309,8 +315,10 @@ void GlobeGPS::prepareForGetDiveCoordinates()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This needs to update the dive site, not just this dive
|
||||||
void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::Unit unit)
|
void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::Unit unit)
|
||||||
{
|
{
|
||||||
|
struct dive_site *ds;
|
||||||
messageWidget->hide();
|
messageWidget->hide();
|
||||||
|
|
||||||
if (MainWindow::instance()->dive_list()->selectionModel()->selection().isEmpty())
|
if (MainWindow::instance()->dive_list()->selectionModel()->selection().isEmpty())
|
||||||
|
@ -324,8 +332,8 @@ void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::U
|
||||||
centerOn(lon, lat, true);
|
centerOn(lon, lat, true);
|
||||||
|
|
||||||
// change the location of the displayed_dive and put the UI in edit mode
|
// change the location of the displayed_dive and put the UI in edit mode
|
||||||
displayed_dive.latitude.udeg = lrint(lat * 1000000.0);
|
displayed_dive_site.latitude.udeg = lrint(lat * 1000000.0);
|
||||||
displayed_dive.longitude.udeg = lrint(lon * 1000000.0);
|
displayed_dive_site.longitude.udeg = lrint(lon * 1000000.0);
|
||||||
emit(coordinatesChanged());
|
emit(coordinatesChanged());
|
||||||
repopulateLabels();
|
repopulateLabels();
|
||||||
editingDiveLocation = false;
|
editingDiveLocation = false;
|
||||||
|
@ -341,7 +349,12 @@ void GlobeGPS::mousePressEvent(QMouseEvent *event)
|
||||||
|
|
||||||
// there could be two scenarios that got us here; let's check if we are editing a dive
|
// there could be two scenarios that got us here; let's check if we are editing a dive
|
||||||
if (MainWindow::instance()->information()->isEditing() && clickOnGlobe) {
|
if (MainWindow::instance()->information()->isEditing() && clickOnGlobe) {
|
||||||
MainWindow::instance()->information()->updateCoordinatesText(lat, lon);
|
//
|
||||||
|
// FIXME
|
||||||
|
// TODO
|
||||||
|
//
|
||||||
|
// this needs to do this on the dive site screen
|
||||||
|
// MainWindow::instance()->information()->updateCoordinatesText(lat, lon);
|
||||||
repopulateLabels();
|
repopulateLabels();
|
||||||
} else if (clickOnGlobe) {
|
} else if (clickOnGlobe) {
|
||||||
changeDiveGeoPosition(lon, lat, GeoDataCoordinates::Degree);
|
changeDiveGeoPosition(lon, lat, GeoDataCoordinates::Degree);
|
||||||
|
|
75
qt-ui/locationInformation.ui
Normal file
75
qt-ui/locationInformation.ui
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>LocationInformation</class>
|
||||||
|
<widget class="QGroupBox" name="LocationInformation">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>GroupBox</string>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Dive Site</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="KMessageWidget" name="diveSiteMessage" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Name</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="diveSiteName"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Coordinates</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="diveSiteCoordinates"/>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Description</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="diveSiteDescription"/>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Notes</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QPlainTextEdit" name="diveSiteNotes"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>KMessageWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>kmessagewidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -49,18 +49,19 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
|
||||||
ui.extraData->setModel(extraDataModel);
|
ui.extraData->setModel(extraDataModel);
|
||||||
closeMessage();
|
closeMessage();
|
||||||
|
|
||||||
|
connect(ui.manageDiveSite, SIGNAL(clicked()), this, SLOT(prepareDiveSiteEdit()));
|
||||||
|
|
||||||
QAction *action = new QAction(tr("Apply changes"), this);
|
QAction *action = new QAction(tr("Apply changes"), this);
|
||||||
connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges()));
|
connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges()));
|
||||||
addMessageAction(action);
|
addMessageAction(action);
|
||||||
|
|
||||||
action = new QAction(tr("Discard changes"), this);
|
action = new QAction(tr("Discard changes"), this);
|
||||||
connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges()));
|
connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges()));
|
||||||
|
addMessageAction(action);
|
||||||
|
|
||||||
QShortcut *closeKey = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
QShortcut *closeKey = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||||
connect(closeKey, SIGNAL(activated()), this, SLOT(escDetected()));
|
connect(closeKey, SIGNAL(activated()), this, SLOT(escDetected()));
|
||||||
|
|
||||||
addMessageAction(action);
|
|
||||||
|
|
||||||
if (qApp->style()->objectName() == "oxygen")
|
if (qApp->style()->objectName() == "oxygen")
|
||||||
setDocumentMode(true);
|
setDocumentMode(true);
|
||||||
else
|
else
|
||||||
|
@ -71,7 +72,6 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
|
|
||||||
ui.location->installEventFilter(this);
|
ui.location->installEventFilter(this);
|
||||||
ui.coordinates->installEventFilter(this);
|
|
||||||
ui.divemaster->installEventFilter(this);
|
ui.divemaster->installEventFilter(this);
|
||||||
ui.buddy->installEventFilter(this);
|
ui.buddy->installEventFilter(this);
|
||||||
ui.suit->installEventFilter(this);
|
ui.suit->installEventFilter(this);
|
||||||
|
@ -212,6 +212,10 @@ MainTab::~MainTab()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainTab::prepareDiveSiteEdit() {
|
||||||
|
emit requestDiveSiteEdit(displayed_dive.dive_site_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
void MainTab::toggleTriggeredColumn()
|
void MainTab::toggleTriggeredColumn()
|
||||||
{
|
{
|
||||||
QAction *action = qobject_cast<QAction *>(sender());
|
QAction *action = qobject_cast<QAction *>(sender());
|
||||||
|
@ -391,6 +395,11 @@ bool MainTab::isEditing()
|
||||||
return editMode != NONE;
|
return editMode != NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainTab::showLocation()
|
||||||
|
{
|
||||||
|
ui.location->setText(get_dive_location(&displayed_dive));
|
||||||
|
}
|
||||||
|
|
||||||
void MainTab::updateDiveInfo(bool clear)
|
void MainTab::updateDiveInfo(bool clear)
|
||||||
{
|
{
|
||||||
// don't execute this while adding / planning a dive
|
// don't execute this while adding / planning a dive
|
||||||
|
@ -424,9 +433,7 @@ void MainTab::updateDiveInfo(bool clear)
|
||||||
else
|
else
|
||||||
ui.notes->setPlainText(tmp);
|
ui.notes->setPlainText(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
UPDATE_TEXT(displayed_dive, notes);
|
UPDATE_TEXT(displayed_dive, notes);
|
||||||
UPDATE_TEXT(displayed_dive, location);
|
|
||||||
UPDATE_TEXT(displayed_dive, suit);
|
UPDATE_TEXT(displayed_dive, suit);
|
||||||
UPDATE_TEXT(displayed_dive, divemaster);
|
UPDATE_TEXT(displayed_dive, divemaster);
|
||||||
UPDATE_TEXT(displayed_dive, buddy);
|
UPDATE_TEXT(displayed_dive, buddy);
|
||||||
|
@ -435,7 +442,11 @@ void MainTab::updateDiveInfo(bool clear)
|
||||||
ui.DiveType->setCurrentIndex(displayed_dive.dc.divemode);
|
ui.DiveType->setCurrentIndex(displayed_dive.dc.divemode);
|
||||||
|
|
||||||
if (!clear) {
|
if (!clear) {
|
||||||
updateGpsCoordinates();
|
struct dive_site *ds = get_dive_site_by_uuid(displayed_dive.dive_site_uuid);
|
||||||
|
if (ds)
|
||||||
|
ui.location->setText(ds->name);
|
||||||
|
else
|
||||||
|
ui.location->clear();
|
||||||
// Subsurface always uses "local time" as in "whatever was the local time at the location"
|
// Subsurface always uses "local time" as in "whatever was the local time at the location"
|
||||||
// so all time stamps have no time zone information and are in UTC
|
// so all time stamps have no time zone information and are in UTC
|
||||||
QDateTime localTime = QDateTime::fromTime_t(displayed_dive.when - gettimezoneoffset(displayed_dive.when));
|
QDateTime localTime = QDateTime::fromTime_t(displayed_dive.when - gettimezoneoffset(displayed_dive.when));
|
||||||
|
@ -446,8 +457,6 @@ void MainTab::updateDiveInfo(bool clear)
|
||||||
setTabText(0, tr("Trip notes"));
|
setTabText(0, tr("Trip notes"));
|
||||||
currentTrip = *MainWindow::instance()->dive_list()->selectedTrips().begin();
|
currentTrip = *MainWindow::instance()->dive_list()->selectedTrips().begin();
|
||||||
// only use trip relevant fields
|
// only use trip relevant fields
|
||||||
ui.coordinates->setVisible(false);
|
|
||||||
ui.CoordinatedLabel->setVisible(false);
|
|
||||||
ui.divemaster->setVisible(false);
|
ui.divemaster->setVisible(false);
|
||||||
ui.DivemasterLabel->setVisible(false);
|
ui.DivemasterLabel->setVisible(false);
|
||||||
ui.buddy->setVisible(false);
|
ui.buddy->setVisible(false);
|
||||||
|
@ -477,8 +486,6 @@ void MainTab::updateDiveInfo(bool clear)
|
||||||
setTabText(0, tr("Dive notes"));
|
setTabText(0, tr("Dive notes"));
|
||||||
currentTrip = NULL;
|
currentTrip = NULL;
|
||||||
// make all the fields visible writeable
|
// make all the fields visible writeable
|
||||||
ui.coordinates->setVisible(true);
|
|
||||||
ui.CoordinatedLabel->setVisible(true);
|
|
||||||
ui.divemaster->setVisible(true);
|
ui.divemaster->setVisible(true);
|
||||||
ui.buddy->setVisible(true);
|
ui.buddy->setVisible(true);
|
||||||
ui.suit->setVisible(true);
|
ui.suit->setVisible(true);
|
||||||
|
@ -647,8 +654,8 @@ void MainTab::updateDiveInfo(bool clear)
|
||||||
clearStats();
|
clearStats();
|
||||||
clearEquipment();
|
clearEquipment();
|
||||||
ui.rating->setCurrentStars(0);
|
ui.rating->setCurrentStars(0);
|
||||||
ui.coordinates->clear();
|
|
||||||
ui.visibility->setCurrentStars(0);
|
ui.visibility->setCurrentStars(0);
|
||||||
|
ui.location->clear();
|
||||||
}
|
}
|
||||||
editMode = NONE;
|
editMode = NONE;
|
||||||
ui.cylinders->view()->hideColumn(CylindersModel::DEPTH);
|
ui.cylinders->view()->hideColumn(CylindersModel::DEPTH);
|
||||||
|
@ -756,8 +763,6 @@ void MainTab::acceptChanges()
|
||||||
copy_samples(&displayed_dive.dc, ¤t_dive->dc);
|
copy_samples(&displayed_dive.dc, ¤t_dive->dc);
|
||||||
}
|
}
|
||||||
struct dive *cd = current_dive;
|
struct dive *cd = current_dive;
|
||||||
//Reset coordinates field, in case it contains garbage.
|
|
||||||
updateGpsCoordinates();
|
|
||||||
// now check if something has changed and if yes, edit the selected dives that
|
// now check if something has changed and if yes, edit the selected dives that
|
||||||
// were identical with the master dive shown (and mark the divelist as changed)
|
// were identical with the master dive shown (and mark the divelist as changed)
|
||||||
if (!same_string(displayed_dive.buddy, cd->buddy))
|
if (!same_string(displayed_dive.buddy, cd->buddy))
|
||||||
|
@ -785,17 +790,6 @@ void MainTab::acceptChanges()
|
||||||
time_t offset = cd->when - displayed_dive.when;
|
time_t offset = cd->when - displayed_dive.when;
|
||||||
MODIFY_SELECTED_DIVES(mydive->when -= offset;);
|
MODIFY_SELECTED_DIVES(mydive->when -= offset;);
|
||||||
}
|
}
|
||||||
if (displayed_dive.latitude.udeg != cd->latitude.udeg ||
|
|
||||||
displayed_dive.longitude.udeg != cd->longitude.udeg)
|
|
||||||
MODIFY_SELECTED_DIVES(
|
|
||||||
if (copyPaste ||
|
|
||||||
(same_string(mydive->location, cd->location) &&
|
|
||||||
mydive->latitude.udeg == cd->latitude.udeg &&
|
|
||||||
mydive->longitude.udeg == cd->longitude.udeg))
|
|
||||||
gpsHasChanged(mydive, cd, ui.coordinates->text(), 0);
|
|
||||||
);
|
|
||||||
if (!same_string(displayed_dive.location, cd->location))
|
|
||||||
MODIFY_SELECTED_DIVES(EDIT_TEXT(location));
|
|
||||||
|
|
||||||
saveTags();
|
saveTags();
|
||||||
|
|
||||||
|
@ -901,7 +895,6 @@ void MainTab::resetPallete()
|
||||||
ui.buddy->setPalette(p);
|
ui.buddy->setPalette(p);
|
||||||
ui.notes->setPalette(p);
|
ui.notes->setPalette(p);
|
||||||
ui.location->setPalette(p);
|
ui.location->setPalette(p);
|
||||||
ui.coordinates->setPalette(p);
|
|
||||||
ui.divemaster->setPalette(p);
|
ui.divemaster->setPalette(p);
|
||||||
ui.suit->setPalette(p);
|
ui.suit->setPalette(p);
|
||||||
ui.airtemp->setPalette(p);
|
ui.airtemp->setPalette(p);
|
||||||
|
@ -1139,8 +1132,17 @@ void MainTab::on_location_textChanged(const QString &text)
|
||||||
free(displayedTrip.location);
|
free(displayedTrip.location);
|
||||||
displayedTrip.location = strdup(ui.location->text().toUtf8().data());
|
displayedTrip.location = strdup(ui.location->text().toUtf8().data());
|
||||||
} else {
|
} else {
|
||||||
free(displayed_dive.location);
|
// this means we switched dive sites... this requires a lot more thinking
|
||||||
displayed_dive.location = strdup(ui.location->text().toUtf8().data());
|
//
|
||||||
|
//
|
||||||
|
// FIXME
|
||||||
|
//
|
||||||
|
// TODO
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// free(displayed_dive.location);
|
||||||
|
// displayed_dive.location = strdup(ui.location->text().toUtf8().data());
|
||||||
}
|
}
|
||||||
markChangedWidget(ui.location);
|
markChangedWidget(ui.location);
|
||||||
}
|
}
|
||||||
|
@ -1148,25 +1150,12 @@ void MainTab::on_location_textChanged(const QString &text)
|
||||||
// If we have GPS data for the location entered, add it.
|
// If we have GPS data for the location entered, add it.
|
||||||
void MainTab::on_location_editingFinished()
|
void MainTab::on_location_editingFinished()
|
||||||
{
|
{
|
||||||
// if we have a location and no GPS data, look up the GPS data;
|
// find the dive site or create it
|
||||||
// but if the GPS data was intentionally cleared then don't
|
const char *name = ui.location->text().toUtf8().data();
|
||||||
if (!currentTrip &&
|
uint32_t uuid = get_dive_site_uuid_by_name(name, NULL);
|
||||||
!same_string(displayed_dive.location, "") &&
|
if (!uuid)
|
||||||
ui.coordinates->text().trimmed().isEmpty() &&
|
uuid = create_dive_site(name);
|
||||||
!(editMode == DIVE && dive_has_gps_location(current_dive))) {
|
displayed_dive.dive_site_uuid = uuid;
|
||||||
struct dive *dive;
|
|
||||||
int i = 0;
|
|
||||||
for_each_dive (i, dive) {
|
|
||||||
if (same_string(displayed_dive.location, dive->location) &&
|
|
||||||
(dive->latitude.udeg || dive->longitude.udeg)) {
|
|
||||||
displayed_dive.latitude = dive->latitude;
|
|
||||||
displayed_dive.longitude = dive->longitude;
|
|
||||||
MainWindow::instance()->globe()->reload();
|
|
||||||
updateGpsCoordinates();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainTab::on_suit_textChanged(const QString &text)
|
void MainTab::on_suit_textChanged(const QString &text)
|
||||||
|
@ -1199,6 +1188,7 @@ void MainTab::on_notes_textChanged()
|
||||||
markChangedWidget(ui.notes);
|
markChangedWidget(ui.notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 // we'll need something like this for the dive site management
|
||||||
void MainTab::on_coordinates_textChanged(const QString &text)
|
void MainTab::on_coordinates_textChanged(const QString &text)
|
||||||
{
|
{
|
||||||
if (editMode == IGNORE || acceptingEdit == true)
|
if (editMode == IGNORE || acceptingEdit == true)
|
||||||
|
@ -1215,6 +1205,7 @@ void MainTab::on_coordinates_textChanged(const QString &text)
|
||||||
ui.coordinates->setPalette(p); // marks things red
|
ui.coordinates->setPalette(p); // marks things red
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void MainTab::on_rating_valueChanged(int value)
|
void MainTab::on_rating_valueChanged(int value)
|
||||||
{
|
{
|
||||||
|
@ -1266,6 +1257,7 @@ void MainTab::editWeightWidget(const QModelIndex &index)
|
||||||
ui.weights->edit(index);
|
ui.weights->edit(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 // we'll need this for dive sites
|
||||||
void MainTab::updateCoordinatesText(qreal lat, qreal lon)
|
void MainTab::updateCoordinatesText(qreal lat, qreal lon)
|
||||||
{
|
{
|
||||||
int ulat = rint(lat * 1000000);
|
int ulat = rint(lat * 1000000);
|
||||||
|
@ -1278,9 +1270,16 @@ void MainTab::updateGpsCoordinates()
|
||||||
if (editMode == NONE)
|
if (editMode == NONE)
|
||||||
enableEdition();
|
enableEdition();
|
||||||
|
|
||||||
ui.coordinates->setText(printGPSCoords(displayed_dive.latitude.udeg, displayed_dive.longitude.udeg));
|
struct dive_site *ds = get_dive_site_by_uuid(displayed_dive.dive_site_uuid);
|
||||||
ui.coordinates->setModified(displayed_dive.latitude.udeg || displayed_dive.longitude.udeg);
|
if (ds && dive_site_has_gps_location(ds)) {
|
||||||
|
ui.coordinates->setText(printGPSCoords(ds->latitude.udeg, ds->longitude.udeg));
|
||||||
|
ui.coordinates->setModified(true);
|
||||||
|
} else if (!ui.coordinates->text().isEmpty()) {
|
||||||
|
ui.coordinates->setModified(true);
|
||||||
|
ui.coordinates->clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void MainTab::escDetected()
|
void MainTab::escDetected()
|
||||||
{
|
{
|
||||||
|
@ -1312,7 +1311,6 @@ void MainTab::showAndTriggerEditSelective(struct dive_components what)
|
||||||
// take the data in our copyPasteDive and apply it to selected dives
|
// take the data in our copyPasteDive and apply it to selected dives
|
||||||
enableEdition();
|
enableEdition();
|
||||||
copyPaste = true;
|
copyPaste = true;
|
||||||
SHOW_SELECTIVE(location);
|
|
||||||
SHOW_SELECTIVE(buddy);
|
SHOW_SELECTIVE(buddy);
|
||||||
SHOW_SELECTIVE(divemaster);
|
SHOW_SELECTIVE(divemaster);
|
||||||
SHOW_SELECTIVE(suit);
|
SHOW_SELECTIVE(suit);
|
||||||
|
@ -1327,8 +1325,8 @@ void MainTab::showAndTriggerEditSelective(struct dive_components what)
|
||||||
ui.rating->setCurrentStars(displayed_dive.rating);
|
ui.rating->setCurrentStars(displayed_dive.rating);
|
||||||
if (what.visibility)
|
if (what.visibility)
|
||||||
ui.visibility->setCurrentStars(displayed_dive.visibility);
|
ui.visibility->setCurrentStars(displayed_dive.visibility);
|
||||||
if (what.gps)
|
if (what.divesite)
|
||||||
updateGpsCoordinates();
|
ui.location->setText(get_dive_location(&displayed_dive));
|
||||||
if (what.tags) {
|
if (what.tags) {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
taglist_get_tagstring(displayed_dive.tag_list, buf, 1024);
|
taglist_get_tagstring(displayed_dive.tag_list, buf, 1024);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
#include "ui_maintab.h"
|
#include "ui_maintab.h"
|
||||||
#include "completionmodels.h"
|
#include "completionmodels.h"
|
||||||
|
@ -55,7 +56,7 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void addDiveFinished();
|
void addDiveFinished();
|
||||||
void dateTimeChanged();
|
void dateTimeChanged();
|
||||||
|
void requestDiveSiteEdit(uint32_t uuid);
|
||||||
public
|
public
|
||||||
slots:
|
slots:
|
||||||
void addCylinder_clicked();
|
void addCylinder_clicked();
|
||||||
|
@ -65,7 +66,6 @@ slots:
|
||||||
void rejectChanges();
|
void rejectChanges();
|
||||||
void on_location_textChanged(const QString &text);
|
void on_location_textChanged(const QString &text);
|
||||||
void on_location_editingFinished();
|
void on_location_editingFinished();
|
||||||
void on_coordinates_textChanged(const QString &text);
|
|
||||||
void on_divemaster_textChanged();
|
void on_divemaster_textChanged();
|
||||||
void on_buddy_textChanged();
|
void on_buddy_textChanged();
|
||||||
void on_suit_textChanged(const QString &text);
|
void on_suit_textChanged(const QString &text);
|
||||||
|
@ -92,7 +92,8 @@ slots:
|
||||||
void escDetected(void);
|
void escDetected(void);
|
||||||
void photoDoubleClicked(const QString filePath);
|
void photoDoubleClicked(const QString filePath);
|
||||||
void removeSelectedPhotos();
|
void removeSelectedPhotos();
|
||||||
void updateGpsCoordinates();
|
void prepareDiveSiteEdit();
|
||||||
|
void showLocation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainTab ui;
|
Ui::MainTab ui;
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="KMessageWidget" name="diveNotesMessage" native="true"/>
|
<widget class="KMessageWidget" name="diveNotesMessage" native="true">
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QScrollArea" name="scrollArea">
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
@ -40,8 +41,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>443</width>
|
<width>441</width>
|
||||||
<height>758</height>
|
<height>753</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
@ -131,7 +132,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="pushButton">
|
<widget class="QPushButton" name="manageDiveSite">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>manage</string>
|
<string>manage</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -139,40 +140,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="CoordinatedLabel">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Coordinates</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLabel" name="TypeLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Dive mode</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLineEdit" name="coordinates">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QComboBox" name="DiveType"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
|
@ -276,13 +243,25 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="DiveType"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="TagLabel">
|
<widget class="QLabel" name="TagLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Tags</string>
|
<string>Tags</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="TypeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Dive mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
<widget class="TagWidget" name="tagWidget">
|
<widget class="TagWidget" name="tagWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
@ -307,6 +286,8 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="NotesLabel">
|
<widget class="QLabel" name="NotesLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -400,8 +381,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>454</width>
|
<width>68</width>
|
||||||
<height>752</height>
|
<height>40</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="equipmentTabScrollAreaLayout">
|
<layout class="QGridLayout" name="equipmentTabScrollAreaLayout">
|
||||||
|
@ -456,8 +437,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>454</width>
|
<width>441</width>
|
||||||
<height>752</height>
|
<height>363</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="diveInfoScrollAreaLayout">
|
<layout class="QGridLayout" name="diveInfoScrollAreaLayout">
|
||||||
|
@ -773,8 +754,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>454</width>
|
<width>446</width>
|
||||||
<height>752</height>
|
<height>215</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="statsScrollAreaLayout">
|
<layout class="QGridLayout" name="statsScrollAreaLayout">
|
||||||
|
@ -1036,7 +1017,6 @@
|
||||||
<tabstop>rating</tabstop>
|
<tabstop>rating</tabstop>
|
||||||
<tabstop>visibility</tabstop>
|
<tabstop>visibility</tabstop>
|
||||||
<tabstop>suit</tabstop>
|
<tabstop>suit</tabstop>
|
||||||
<tabstop>tagWidget</tabstop>
|
|
||||||
<tabstop>notes</tabstop>
|
<tabstop>notes</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
|
@ -67,12 +67,15 @@ MainWindow::MainWindow() : QMainWindow(),
|
||||||
PlannerSettingsWidget *plannerSettings = new PlannerSettingsWidget();
|
PlannerSettingsWidget *plannerSettings = new PlannerSettingsWidget();
|
||||||
DivePlannerWidget *plannerWidget = new DivePlannerWidget();
|
DivePlannerWidget *plannerWidget = new DivePlannerWidget();
|
||||||
PlannerDetails *plannerDetails = new PlannerDetails();
|
PlannerDetails *plannerDetails = new PlannerDetails();
|
||||||
|
LocationInformationWidget *locationInformation = new LocationInformationWidget();
|
||||||
|
|
||||||
registerApplicationState("Default", mainTab, profileWidget, diveListView, globeGps );
|
registerApplicationState("Default", mainTab, profileWidget, diveListView, globeGps );
|
||||||
registerApplicationState("AddDive", mainTab, profileWidget, diveListView, globeGps );
|
registerApplicationState("AddDive", mainTab, profileWidget, diveListView, globeGps );
|
||||||
registerApplicationState("EditDive", mainTab, profileWidget, diveListView, globeGps );
|
registerApplicationState("EditDive", mainTab, profileWidget, diveListView, globeGps );
|
||||||
registerApplicationState("PlanDive", plannerWidget, profileWidget, plannerSettings, plannerDetails );
|
registerApplicationState("PlanDive", plannerWidget, profileWidget, plannerSettings, plannerDetails );
|
||||||
registerApplicationState("EditPlannedDive", plannerWidget, profileWidget, diveListView, globeGps );
|
registerApplicationState("EditPlannedDive", plannerWidget, profileWidget, diveListView, globeGps );
|
||||||
|
registerApplicationState("EditDiveSite",locationInformation, profileWidget, diveListView, globeGps );
|
||||||
|
|
||||||
setApplicationState("Default");
|
setApplicationState("Default");
|
||||||
|
|
||||||
ui.multiFilter->hide();
|
ui.multiFilter->hide();
|
||||||
|
@ -108,6 +111,11 @@ MainWindow::MainWindow() : QMainWindow(),
|
||||||
connect(DivePlannerPointsModel::instance(), SIGNAL(planCreated()), this, SLOT(planCreated()));
|
connect(DivePlannerPointsModel::instance(), SIGNAL(planCreated()), this, SLOT(planCreated()));
|
||||||
connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled()));
|
connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled()));
|
||||||
connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan()));
|
connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan()));
|
||||||
|
connect(mainTab, SIGNAL(requestDiveSiteEdit(uint32_t)), this, SLOT(enableDiveSiteEdit(uint32_t)));
|
||||||
|
connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(setDefaultState()));
|
||||||
|
connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(refreshDisplay()));
|
||||||
|
connect(locationInformation, SIGNAL(informationManagementEnded()), information(), SLOT(showLocation()));
|
||||||
|
|
||||||
#ifdef NO_PRINTING
|
#ifdef NO_PRINTING
|
||||||
ui.printPlan->hide();
|
ui.printPlan->hide();
|
||||||
ui.menuFile->removeAction(ui.actionPrint);
|
ui.menuFile->removeAction(ui.actionPrint);
|
||||||
|
@ -128,7 +136,7 @@ MainWindow::MainWindow() : QMainWindow(),
|
||||||
#ifdef NO_MARBLE
|
#ifdef NO_MARBLE
|
||||||
ui.menuView->removeAction(ui.actionViewGlobe);
|
ui.menuView->removeAction(ui.actionViewGlobe);
|
||||||
#else
|
#else
|
||||||
connect(globe(), SIGNAL(coordinatesChanged()), information(), SLOT(updateGpsCoordinates()));
|
connect(globe(), SIGNAL(coordinatesChanged()), locationInformation, SLOT(updateGpsCoordinates()));
|
||||||
#endif
|
#endif
|
||||||
#ifdef NO_USERMANUAL
|
#ifdef NO_USERMANUAL
|
||||||
ui.menuHelp->removeAction(ui.actionUserManual);
|
ui.menuHelp->removeAction(ui.actionUserManual);
|
||||||
|
@ -205,6 +213,18 @@ PlannerSettingsWidget *MainWindow::divePlannerSettingsWidget() {
|
||||||
return qobject_cast<PlannerSettingsWidget*>(applicationState["PlanDive"].bottomLeft);
|
return qobject_cast<PlannerSettingsWidget*>(applicationState["PlanDive"].bottomLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocationInformationWidget *MainWindow::locationInformationWidget() {
|
||||||
|
return qobject_cast<LocationInformationWidget*>(applicationState["EditDiveSite"].topLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::enableDiveSiteEdit(uint32_t id) {
|
||||||
|
setApplicationState("EditDiveSite");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::setDefaultState() {
|
||||||
|
setApplicationState("Default");
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::setLoadedWithFiles(bool f)
|
void MainWindow::setLoadedWithFiles(bool f)
|
||||||
{
|
{
|
||||||
filesAsArguments = f;
|
filesAsArguments = f;
|
||||||
|
@ -255,6 +275,7 @@ void MainWindow::current_dive_changed(int divenr)
|
||||||
}
|
}
|
||||||
graphics()->plotDive();
|
graphics()->plotDive();
|
||||||
information()->updateDiveInfo();
|
information()->updateDiveInfo();
|
||||||
|
locationInformationWidget()->setLocationId(displayed_dive.dive_site_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionNew_triggered()
|
void MainWindow::on_actionNew_triggered()
|
||||||
|
@ -334,6 +355,8 @@ void MainWindow::closeCurrentFile()
|
||||||
clear_git_id();
|
clear_git_id();
|
||||||
while (dive_table.nr)
|
while (dive_table.nr)
|
||||||
delete_single_dive(0);
|
delete_single_dive(0);
|
||||||
|
while (dive_site_table.nr)
|
||||||
|
delete_dive_site(get_dive_site(0)->uuid);
|
||||||
|
|
||||||
free((void *)existing_filename);
|
free((void *)existing_filename);
|
||||||
existing_filename = NULL;
|
existing_filename = NULL;
|
||||||
|
@ -532,6 +555,7 @@ void MainWindow::setupForAddAndPlan(const char *model)
|
||||||
// setup the dive cylinders
|
// setup the dive cylinders
|
||||||
DivePlannerPointsModel::instance()->clear();
|
DivePlannerPointsModel::instance()->clear();
|
||||||
DivePlannerPointsModel::instance()->setupCylinders();
|
DivePlannerPointsModel::instance()->setupCylinders();
|
||||||
|
locationInformationWidget()->setLocationId(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionReplanDive_triggered()
|
void MainWindow::on_actionReplanDive_triggered()
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ public:
|
||||||
GlobeGPS *globe();
|
GlobeGPS *globe();
|
||||||
DivePlannerWidget *divePlannerWidget();
|
DivePlannerWidget *divePlannerWidget();
|
||||||
PlannerSettingsWidget *divePlannerSettingsWidget();
|
PlannerSettingsWidget *divePlannerSettingsWidget();
|
||||||
|
LocationInformationWidget *locationInformationWidget();
|
||||||
void showError(QString message);
|
void showError(QString message);
|
||||||
void setTitle(enum MainWindowTitleFormat format);
|
void setTitle(enum MainWindowTitleFormat format);
|
||||||
|
|
||||||
|
@ -159,6 +160,8 @@ slots:
|
||||||
void on_paste_triggered();
|
void on_paste_triggered();
|
||||||
void on_actionFilterTags_triggered();
|
void on_actionFilterTags_triggered();
|
||||||
void on_actionConfigure_Dive_Computer_triggered();
|
void on_actionConfigure_Dive_Computer_triggered();
|
||||||
|
void enableDiveSiteEdit(uint32_t id);
|
||||||
|
void setDefaultState();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *);
|
void closeEvent(QCloseEvent *);
|
||||||
|
|
|
@ -1191,7 +1191,7 @@ QVariant DiveItem::data(int column, int role) const
|
||||||
retVal = dive->maxcns;
|
retVal = dive->maxcns;
|
||||||
break;
|
break;
|
||||||
case LOCATION:
|
case LOCATION:
|
||||||
retVal = QString(dive->location);
|
retVal = QString(get_dive_location(dive));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1232,7 +1232,7 @@ QVariant DiveItem::data(int column, int role) const
|
||||||
retVal = dive->maxcns;
|
retVal = dive->maxcns;
|
||||||
break;
|
break;
|
||||||
case LOCATION:
|
case LOCATION:
|
||||||
retVal = QString(dive->location);
|
retVal = QString(get_dive_location(dive));
|
||||||
break;
|
break;
|
||||||
case GAS:
|
case GAS:
|
||||||
const char *gas_string = get_dive_gas_string(dive);
|
const char *gas_string = get_dive_gas_string(dive);
|
||||||
|
@ -2110,7 +2110,7 @@ QVariant ProfilePrintModel::data(const QModelIndex &index, int role) const
|
||||||
}
|
}
|
||||||
if (row == 1) {
|
if (row == 1) {
|
||||||
if (col == 0)
|
if (col == 0)
|
||||||
return QString(dive->location);
|
return QString(get_dive_location(dive));
|
||||||
if (col == 3)
|
if (col == 3)
|
||||||
return QString(tr("Duration: %1 min")).arg(di.displayDuration());
|
return QString(tr("Duration: %1 min")).arg(di.displayDuration());
|
||||||
}
|
}
|
||||||
|
|
|
@ -462,7 +462,7 @@ void PrintLayout::addTablePrintDataRow(TablePrintModel *model, int row, struct d
|
||||||
model->setData(model->index(row, 3), di.displayDuration(), Qt::DisplayRole);
|
model->setData(model->index(row, 3), di.displayDuration(), Qt::DisplayRole);
|
||||||
model->setData(model->index(row, 4), dive->divemaster, Qt::DisplayRole);
|
model->setData(model->index(row, 4), dive->divemaster, Qt::DisplayRole);
|
||||||
model->setData(model->index(row, 5), dive->buddy, Qt::DisplayRole);
|
model->setData(model->index(row, 5), dive->buddy, Qt::DisplayRole);
|
||||||
model->setData(model->index(row, 6), dive->location, Qt::DisplayRole);
|
model->setData(model->index(row, 6), get_dive_location(dive), Qt::DisplayRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintLayout::addTablePrintHeadingRow(TablePrintModel *model, int row) const
|
void PrintLayout::addTablePrintHeadingRow(TablePrintModel *model, int row) const
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
#include <QCalendarWidget>
|
#include <QCalendarWidget>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QAction>
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
@ -456,8 +457,7 @@ DiveComponentSelection::DiveComponentSelection(QWidget *parent, struct dive *tar
|
||||||
{
|
{
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
what = _what;
|
what = _what;
|
||||||
UI_FROM_COMPONENT(location);
|
UI_FROM_COMPONENT(divesite);
|
||||||
UI_FROM_COMPONENT(gps);
|
|
||||||
UI_FROM_COMPONENT(divemaster);
|
UI_FROM_COMPONENT(divemaster);
|
||||||
UI_FROM_COMPONENT(buddy);
|
UI_FROM_COMPONENT(buddy);
|
||||||
UI_FROM_COMPONENT(rating);
|
UI_FROM_COMPONENT(rating);
|
||||||
|
@ -477,8 +477,7 @@ DiveComponentSelection::DiveComponentSelection(QWidget *parent, struct dive *tar
|
||||||
void DiveComponentSelection::buttonClicked(QAbstractButton *button)
|
void DiveComponentSelection::buttonClicked(QAbstractButton *button)
|
||||||
{
|
{
|
||||||
if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
|
if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
|
||||||
COMPONENT_FROM_UI(location);
|
COMPONENT_FROM_UI(divesite);
|
||||||
COMPONENT_FROM_UI(gps);
|
|
||||||
COMPONENT_FROM_UI(divemaster);
|
COMPONENT_FROM_UI(divemaster);
|
||||||
COMPONENT_FROM_UI(buddy);
|
COMPONENT_FROM_UI(buddy);
|
||||||
COMPONENT_FROM_UI(rating);
|
COMPONENT_FROM_UI(rating);
|
||||||
|
@ -646,3 +645,93 @@ void MultiFilter::closeFilter()
|
||||||
MultiFilterSortModel::instance()->clearFilter();
|
MultiFilterSortModel::instance()->clearFilter();
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QShowEvent>
|
||||||
|
|
||||||
|
LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent)
|
||||||
|
{
|
||||||
|
ui.setupUi(this);
|
||||||
|
ui.diveSiteMessage->setText("You are editing the Dive Site");
|
||||||
|
ui.diveSiteMessage->setCloseButtonVisible(false);
|
||||||
|
|
||||||
|
QAction *action = new QAction(tr("Apply changes"), this);
|
||||||
|
connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges()));
|
||||||
|
ui.diveSiteMessage->addAction(action);
|
||||||
|
|
||||||
|
action = new QAction(tr("Discard changes"), this);
|
||||||
|
connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges()));
|
||||||
|
ui.diveSiteMessage->addAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationInformationWidget::setLocationId(uint32_t uuid)
|
||||||
|
{
|
||||||
|
currentDs = get_dive_site_by_uuid(uuid);
|
||||||
|
|
||||||
|
if (!currentDs) {
|
||||||
|
currentDs = get_dive_site_by_uuid(create_dive_site(""));
|
||||||
|
displayed_dive.dive_site_uuid = currentDs->uuid;
|
||||||
|
ui.diveSiteName->clear();
|
||||||
|
ui.diveSiteDescription->clear();
|
||||||
|
ui.diveSiteNotes->clear();
|
||||||
|
ui.diveSiteCoordinates->clear();
|
||||||
|
}
|
||||||
|
displayed_dive_site = *currentDs;
|
||||||
|
ui.diveSiteName->setText(displayed_dive_site.name);
|
||||||
|
ui.diveSiteDescription->setText(displayed_dive_site.description);
|
||||||
|
ui.diveSiteNotes->setPlainText(displayed_dive_site.notes);
|
||||||
|
ui.diveSiteCoordinates->setText(printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationInformationWidget::updateGpsCoordinates()
|
||||||
|
{
|
||||||
|
ui.diveSiteCoordinates->setText(printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg));
|
||||||
|
MainWindow::instance()->setApplicationState("EditDiveSite");
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationInformationWidget::acceptChanges()
|
||||||
|
{
|
||||||
|
char *uiString;
|
||||||
|
currentDs->latitude = displayed_dive_site.latitude;
|
||||||
|
currentDs->longitude = displayed_dive_site.longitude;
|
||||||
|
uiString = ui.diveSiteName->text().toUtf8().data();
|
||||||
|
if (!same_string(uiString, currentDs->name)) {
|
||||||
|
free(currentDs->name);
|
||||||
|
currentDs->name = copy_string(uiString);
|
||||||
|
}
|
||||||
|
uiString = ui.diveSiteDescription->text().toUtf8().data();
|
||||||
|
if (!same_string(uiString, currentDs->description)) {
|
||||||
|
free(currentDs->description);
|
||||||
|
currentDs->description = copy_string(uiString);
|
||||||
|
}
|
||||||
|
uiString = ui.diveSiteNotes->document()->toPlainText().toUtf8().data();
|
||||||
|
if (!same_string(uiString, currentDs->notes)) {
|
||||||
|
free(currentDs->notes);
|
||||||
|
currentDs->notes = copy_string(uiString);
|
||||||
|
}
|
||||||
|
if (dive_site_is_empty(currentDs)) {
|
||||||
|
delete_dive_site(currentDs->uuid);
|
||||||
|
displayed_dive.dive_site_uuid = 0;
|
||||||
|
setLocationId(0);
|
||||||
|
} else {
|
||||||
|
setLocationId(currentDs->uuid);
|
||||||
|
}
|
||||||
|
mark_divelist_changed(true);
|
||||||
|
emit informationManagementEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationInformationWidget::rejectChanges()
|
||||||
|
{
|
||||||
|
Q_ASSERT(currentDs != NULL);
|
||||||
|
if (dive_site_is_empty(currentDs)) {
|
||||||
|
delete_dive_site(currentDs->uuid);
|
||||||
|
displayed_dive.dive_site_uuid = 0;
|
||||||
|
setLocationId(0);
|
||||||
|
} else {
|
||||||
|
setLocationId(currentDs->uuid);
|
||||||
|
}
|
||||||
|
emit informationManagementEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocationInformationWidget::showEvent(QShowEvent *ev) {
|
||||||
|
ui.diveSiteMessage->setCloseButtonVisible(false);
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ class QAbstractButton;
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QGroupBox>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -214,6 +215,30 @@ private:
|
||||||
Ui::FilterWidget ui;
|
Ui::FilterWidget ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "ui_locationInformation.h"
|
||||||
|
|
||||||
|
class LocationInformationWidget : public QGroupBox {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LocationInformationWidget(QWidget *parent = 0);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void acceptChanges();
|
||||||
|
void rejectChanges();
|
||||||
|
|
||||||
|
void showEvent(QShowEvent *);
|
||||||
|
|
||||||
|
void setLocationId(uint32_t uuid);
|
||||||
|
void updateGpsCoordinates(void);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void informationManagementEnded();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct dive_site *currentDs;
|
||||||
|
Ui::LocationInformation ui;
|
||||||
|
};
|
||||||
|
|
||||||
bool isGnome3Session();
|
bool isGnome3Session();
|
||||||
QImage grayImage(const QImage &coloredImg);
|
QImage grayImage(const QImage &coloredImg);
|
||||||
|
|
||||||
|
|
|
@ -302,7 +302,7 @@ void SocialNetworkDialog::selectionChanged()
|
||||||
tr("min", "abbreviation for minutes")));
|
tr("min", "abbreviation for minutes")));
|
||||||
}
|
}
|
||||||
if (ui->Location->isChecked()) {
|
if (ui->Location->isChecked()) {
|
||||||
fullText += tr("Dive location: %1 \n").arg(d->location);
|
fullText += tr("Dive location: %1 \n").arg(get_dive_location(d));
|
||||||
}
|
}
|
||||||
if (ui->Buddy->isChecked()) {
|
if (ui->Buddy->isChecked()) {
|
||||||
fullText += tr("Buddy: %1 \n").arg(d->buddy);
|
fullText += tr("Buddy: %1 \n").arg(d->buddy);
|
||||||
|
|
|
@ -29,7 +29,25 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct dive_table gps_location_table;
|
struct dive_table gps_location_table;
|
||||||
static bool merge_locations_into_dives(void);
|
|
||||||
|
// we don't overwrite any existing GPS info in the dive
|
||||||
|
// so get the dive site and if there is none or there is one without GPS fix, add it
|
||||||
|
static void copy_gps_location(struct dive *from, struct dive *to)
|
||||||
|
{
|
||||||
|
struct dive_site *ds = get_dive_site_for_dive(to);
|
||||||
|
if (!ds || !dive_site_has_gps_location(ds)) {
|
||||||
|
struct dive_site *gds = get_dive_site_for_dive(from);
|
||||||
|
if (!ds) {
|
||||||
|
// simply link to the one created for the fake dive
|
||||||
|
to->dive_site_uuid = gds->uuid;
|
||||||
|
} else {
|
||||||
|
ds->latitude = gds->latitude;
|
||||||
|
ds->longitude = gds->longitude;
|
||||||
|
if (same_string(ds->name, ""))
|
||||||
|
ds->name = copy_string(gds->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define SAME_GROUP 6 * 3600 // six hours
|
#define SAME_GROUP 6 * 3600 // six hours
|
||||||
//TODO: C Code. static functions are not good if we plan to have a test for them.
|
//TODO: C Code. static functions are not good if we plan to have a test for them.
|
||||||
|
@ -42,14 +60,14 @@ static bool merge_locations_into_dives(void)
|
||||||
|
|
||||||
for_each_dive (i, dive) {
|
for_each_dive (i, dive) {
|
||||||
if (!dive_has_gps_location(dive)) {
|
if (!dive_has_gps_location(dive)) {
|
||||||
for (j = tracer; (gpsfix = get_gps_location(j, &gps_location_table)) !=NULL; j++) {
|
for (j = tracer; (gpsfix = get_dive_from_table(j, &gps_location_table)) !=NULL; j++) {
|
||||||
if (dive_within_time_range (dive, gpsfix->when, SAME_GROUP)) {
|
if (dive_within_time_range (dive, gpsfix->when, SAME_GROUP)) {
|
||||||
/*
|
/*
|
||||||
* If position is fixed during dive. This is the good one.
|
* If position is fixed during dive. This is the good one.
|
||||||
* Asign and mark position, and end gps_location loop
|
* Asign and mark position, and end gps_location loop
|
||||||
*/
|
*/
|
||||||
if ((dive->when <= gpsfix->when && gpsfix->when <= dive->when + dive->duration.seconds)) {
|
if ((dive->when <= gpsfix->when && gpsfix->when <= dive->when + dive->duration.seconds)) {
|
||||||
copy_gps_location(gpsfix,dive);
|
copy_gps_location(gpsfix, dive);
|
||||||
changed++;
|
changed++;
|
||||||
tracer = j;
|
tracer = j;
|
||||||
break;
|
break;
|
||||||
|
@ -57,7 +75,7 @@ static bool merge_locations_into_dives(void)
|
||||||
/*
|
/*
|
||||||
* If it is not, check if there are more position fixes in SAME_GROUP range
|
* If it is not, check if there are more position fixes in SAME_GROUP range
|
||||||
*/
|
*/
|
||||||
if ((nextgpsfix = get_gps_location(j+1,&gps_location_table)) &&
|
if ((nextgpsfix = get_dive_from_table(j+1,&gps_location_table)) &&
|
||||||
dive_within_time_range (dive, nextgpsfix->when, SAME_GROUP)) {
|
dive_within_time_range (dive, nextgpsfix->when, SAME_GROUP)) {
|
||||||
/*
|
/*
|
||||||
* If distance from gpsfix to end of dive is shorter than distance between
|
* If distance from gpsfix to end of dive is shorter than distance between
|
||||||
|
@ -65,7 +83,7 @@ static bool merge_locations_into_dives(void)
|
||||||
* If not, simply fail and nextgpsfix will be evaluated in next iteration.
|
* If not, simply fail and nextgpsfix will be evaluated in next iteration.
|
||||||
*/
|
*/
|
||||||
if ((dive->when + dive->duration.seconds - gpsfix->when) < (nextgpsfix->when - gpsfix->when)) {
|
if ((dive->when + dive->duration.seconds - gpsfix->when) < (nextgpsfix->when - gpsfix->when)) {
|
||||||
copy_gps_location(gpsfix,dive);
|
copy_gps_location(gpsfix, dive);
|
||||||
tracer = j;
|
tracer = j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +91,7 @@ static bool merge_locations_into_dives(void)
|
||||||
* If no more positions in range, the actual is the one. Asign, mark and end loop.
|
* If no more positions in range, the actual is the one. Asign, mark and end loop.
|
||||||
*/
|
*/
|
||||||
} else {
|
} else {
|
||||||
copy_gps_location(gpsfix,dive);
|
copy_gps_location(gpsfix, dive);
|
||||||
changed++;
|
changed++;
|
||||||
tracer = j;
|
tracer = j;
|
||||||
break;
|
break;
|
||||||
|
@ -329,10 +347,19 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton *button)
|
||||||
ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
|
ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
|
||||||
switch (ui.buttonBox->buttonRole(button)) {
|
switch (ui.buttonBox->buttonRole(button)) {
|
||||||
case QDialogButtonBox::ApplyRole: {
|
case QDialogButtonBox::ApplyRole: {
|
||||||
|
int i;
|
||||||
|
struct dive *d;
|
||||||
|
struct dive_site *ds;
|
||||||
clear_table(&gps_location_table);
|
clear_table(&gps_location_table);
|
||||||
QByteArray url = tr("Webservice").toLocal8Bit();
|
QByteArray url = tr("Webservice").toLocal8Bit();
|
||||||
parse_xml_buffer(url.data(), downloadedData.data(), downloadedData.length(), &gps_location_table, NULL);
|
parse_xml_buffer(url.data(), downloadedData.data(), downloadedData.length(), &gps_location_table, NULL);
|
||||||
|
// make sure we mark all the dive sites that were created
|
||||||
|
for (i = 0; i < gps_location_table.nr; i++) {
|
||||||
|
d = get_dive_from_table(i, &gps_location_table);
|
||||||
|
ds = get_dive_site_by_uuid(d->dive_site_uuid);
|
||||||
|
if (ds)
|
||||||
|
ds->notes = strdup("SubsurfaceWebservice");
|
||||||
|
}
|
||||||
/* now merge the data in the gps_location table into the dive_table */
|
/* now merge the data in the gps_location table into the dive_table */
|
||||||
if (merge_locations_into_dives()) {
|
if (merge_locations_into_dives()) {
|
||||||
mark_divelist_changed(true);
|
mark_divelist_changed(true);
|
||||||
|
@ -361,6 +388,16 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton *button)
|
||||||
hide();
|
hide();
|
||||||
close();
|
close();
|
||||||
resetState();
|
resetState();
|
||||||
|
/* and now clean up and remove all the extra dive sites that were created */
|
||||||
|
QSet<uint32_t> usedUuids;
|
||||||
|
for_each_dive(i, d) {
|
||||||
|
if (d->dive_site_uuid)
|
||||||
|
usedUuids.insert(d->dive_site_uuid);
|
||||||
|
}
|
||||||
|
for_each_dive_site(i, ds) {
|
||||||
|
if (!usedUuids.contains(ds->uuid) && same_string(ds->notes, "SubsurfaceWebservice"))
|
||||||
|
delete_dive_site(ds->uuid);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case QDialogButtonBox::RejectRole:
|
case QDialogButtonBox::RejectRole:
|
||||||
if (reply != NULL && reply->isOpen()) {
|
if (reply != NULL && reply->isOpen()) {
|
||||||
|
|
|
@ -165,6 +165,7 @@ bool parseGpsText(const QString &gps_text, double *latitude, double *longitude)
|
||||||
pos == gps_text.size();
|
pos == gps_text.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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;
|
double latitude, longitude;
|
||||||
|
@ -193,6 +194,7 @@ bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_te
|
||||||
dive->longitude.udeg = longudeg;
|
dive->longitude.udeg = longudeg;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QList<int> getDivesInTrip(dive_trip_t *trip)
|
QList<int> getDivesInTrip(dive_trip_t *trip)
|
||||||
{
|
{
|
||||||
|
|
41
save-git.c
41
save-git.c
|
@ -104,8 +104,6 @@ static void show_utf8(struct membuffer *b, const char *prefix, const char *value
|
||||||
|
|
||||||
static void save_overview(struct membuffer *b, struct dive *dive)
|
static void save_overview(struct membuffer *b, struct dive *dive)
|
||||||
{
|
{
|
||||||
show_gps(b, dive->latitude, dive->longitude);
|
|
||||||
show_utf8(b, "location ", dive->location, "\n");
|
|
||||||
show_utf8(b, "divemaster ", dive->divemaster, "\n");
|
show_utf8(b, "divemaster ", dive->divemaster, "\n");
|
||||||
show_utf8(b, "buddy ", dive->buddy, "\n");
|
show_utf8(b, "buddy ", dive->buddy, "\n");
|
||||||
show_utf8(b, "suit ", dive->suit, "\n");
|
show_utf8(b, "suit ", dive->suit, "\n");
|
||||||
|
@ -390,6 +388,7 @@ static void create_dive_buffer(struct dive *dive, struct membuffer *b)
|
||||||
SAVE("visibility", visibility);
|
SAVE("visibility", visibility);
|
||||||
cond_put_format(dive->tripflag == NO_TRIP, b, "notrip\n");
|
cond_put_format(dive->tripflag == NO_TRIP, b, "notrip\n");
|
||||||
save_tags(b, dive->tag_list);
|
save_tags(b, dive->tag_list);
|
||||||
|
cond_put_format(dive->dive_site_uuid, b, "divesiteid %08x\n", dive->dive_site_uuid);
|
||||||
|
|
||||||
save_overview(b, dive);
|
save_overview(b, dive);
|
||||||
save_cylinder_info(b, dive);
|
save_cylinder_info(b, dive);
|
||||||
|
@ -804,7 +803,7 @@ static void save_one_device(void *_b, const char *model, uint32_t deviceid,
|
||||||
put_string(b, "\n");
|
put_string(b, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VERSION 2
|
#define VERSION 3
|
||||||
|
|
||||||
static void save_settings(git_repository *repo, struct dir *tree)
|
static void save_settings(git_repository *repo, struct dir *tree)
|
||||||
{
|
{
|
||||||
|
@ -818,6 +817,38 @@ static void save_settings(git_repository *repo, struct dir *tree)
|
||||||
blob_insert(repo, tree, &b, "00-Subsurface");
|
blob_insert(repo, tree, &b, "00-Subsurface");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void save_divesites(git_repository *repo, struct dir *tree)
|
||||||
|
{
|
||||||
|
struct dir *subdir;
|
||||||
|
struct membuffer dirname = { 0 };
|
||||||
|
put_format(&dirname, "01-Divesites");
|
||||||
|
subdir = new_directory(repo, tree, &dirname);
|
||||||
|
|
||||||
|
for (int i = 0; i < dive_site_table.nr; i++) {
|
||||||
|
struct membuffer b = { 0 };
|
||||||
|
struct dive_site *ds = get_dive_site(i);
|
||||||
|
if (dive_site_is_empty(ds)) {
|
||||||
|
int j;
|
||||||
|
struct dive *d;
|
||||||
|
for_each_dive(j, d) {
|
||||||
|
if (d->dive_site_uuid == ds->uuid)
|
||||||
|
d->dive_site_uuid = 0;
|
||||||
|
}
|
||||||
|
delete_dive_site(get_dive_site(i)->uuid);
|
||||||
|
i--; // since we just deleted that one
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int size = sizeof("Site-012345678");
|
||||||
|
char name[size];
|
||||||
|
snprintf(name, size, "Site-%08x", ds->uuid);
|
||||||
|
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);
|
||||||
|
blob_insert(repo, subdir, &b, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int create_git_tree(git_repository *repo, struct dir *root, bool select_only)
|
static int create_git_tree(git_repository *repo, struct dir *root, bool select_only)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -826,6 +857,8 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
|
||||||
|
|
||||||
save_settings(repo, root);
|
save_settings(repo, root);
|
||||||
|
|
||||||
|
save_divesites(repo, root);
|
||||||
|
|
||||||
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
|
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
|
||||||
trip->index = 0;
|
trip->index = 0;
|
||||||
|
|
||||||
|
@ -938,7 +971,7 @@ static void create_commit_message(struct membuffer *msg)
|
||||||
|
|
||||||
if (dive) {
|
if (dive) {
|
||||||
dive_trip_t *trip = dive->divetrip;
|
dive_trip_t *trip = dive->divetrip;
|
||||||
const char *location = dive->location ? : "no location";
|
const char *location = get_dive_location(dive) ? : "no location";
|
||||||
struct divecomputer *dc = &dive->dc;
|
struct divecomputer *dc = &dive->dc;
|
||||||
const char *sep = "\n";
|
const char *sep = "\n";
|
||||||
|
|
||||||
|
|
|
@ -172,8 +172,11 @@ void put_HTML_samples(struct membuffer *b, struct dive *dive)
|
||||||
|
|
||||||
void put_HTML_coordinates(struct membuffer *b, struct dive *dive)
|
void put_HTML_coordinates(struct membuffer *b, struct dive *dive)
|
||||||
{
|
{
|
||||||
degrees_t latitude = dive->latitude;
|
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||||
degrees_t longitude = dive->longitude;
|
if (!ds)
|
||||||
|
return;
|
||||||
|
degrees_t latitude = ds->latitude;
|
||||||
|
degrees_t longitude = ds->longitude;
|
||||||
|
|
||||||
//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)
|
||||||
|
@ -304,7 +307,7 @@ void write_one_dive(struct membuffer *b, struct dive *dive, const char *photos_d
|
||||||
put_format(b, "\"subsurface_number\":%d,", dive->number);
|
put_format(b, "\"subsurface_number\":%d,", dive->number);
|
||||||
put_HTML_date(b, dive, "\"date\":\"", "\",");
|
put_HTML_date(b, dive, "\"date\":\"", "\",");
|
||||||
put_HTML_time(b, dive, "\"time\":\"", "\",");
|
put_HTML_time(b, dive, "\"time\":\"", "\",");
|
||||||
write_attribute(b, "location", dive->location, ", ");
|
write_attribute(b, "location", get_dive_location(dive), ", ");
|
||||||
put_HTML_coordinates(b, dive);
|
put_HTML_coordinates(b, dive);
|
||||||
put_format(b, "\"rating\":%d,", dive->rating);
|
put_format(b, "\"rating\":%d,", dive->rating);
|
||||||
put_format(b, "\"visibility\":%d,", dive->visibility);
|
put_format(b, "\"visibility\":%d,", dive->visibility);
|
||||||
|
|
71
save-xml.c
71
save-xml.c
|
@ -110,38 +110,8 @@ static void save_salinity(struct membuffer *b, struct divecomputer *dc)
|
||||||
put_string(b, " />\n");
|
put_string(b, " />\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_location(struct membuffer *b, struct dive *dive)
|
|
||||||
{
|
|
||||||
degrees_t latitude = dive->latitude;
|
|
||||||
degrees_t longitude = dive->longitude;
|
|
||||||
|
|
||||||
/* Should we write a location tag at all? */
|
|
||||||
if (!(latitude.udeg || longitude.udeg) && !dive->location)
|
|
||||||
return;
|
|
||||||
|
|
||||||
put_string(b, " <location");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ok, theoretically I guess you could dive at
|
|
||||||
* exactly 0,0. But we don't support that. So
|
|
||||||
* if you do, just fudge it a bit, and say that
|
|
||||||
* you dove a few meters away.
|
|
||||||
*/
|
|
||||||
if (latitude.udeg || longitude.udeg) {
|
|
||||||
put_degrees(b, latitude, " gps='", " ");
|
|
||||||
put_degrees(b, longitude, "", "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do we have a location name or should we write a empty tag? */
|
|
||||||
if (dive->location && dive->location[0] != '\0')
|
|
||||||
show_utf8(b, dive->location, ">", "</location>\n", 0);
|
|
||||||
else
|
|
||||||
put_string(b, "/>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void save_overview(struct membuffer *b, struct dive *dive)
|
static void save_overview(struct membuffer *b, struct dive *dive)
|
||||||
{
|
{
|
||||||
show_location(b, dive);
|
|
||||||
show_utf8(b, dive->divemaster, " <divemaster>", "</divemaster>\n", 0);
|
show_utf8(b, dive->divemaster, " <divemaster>", "</divemaster>\n", 0);
|
||||||
show_utf8(b, dive->buddy, " <buddy>", "</buddy>\n", 0);
|
show_utf8(b, dive->buddy, " <buddy>", "</buddy>\n", 0);
|
||||||
show_utf8(b, dive->notes, " <notes>", "</notes>\n", 0);
|
show_utf8(b, dive->notes, " <notes>", "</notes>\n", 0);
|
||||||
|
@ -424,7 +394,8 @@ void save_one_dive(struct membuffer *b, struct dive *dive)
|
||||||
if (dive->visibility)
|
if (dive->visibility)
|
||||||
put_format(b, " visibility='%d'", dive->visibility);
|
put_format(b, " visibility='%d'", dive->visibility);
|
||||||
save_tags(b, dive->tag_list);
|
save_tags(b, dive->tag_list);
|
||||||
|
if (dive->dive_site_uuid)
|
||||||
|
put_format(b, " divesiteid='%8x'", dive->dive_site_uuid);
|
||||||
show_date(b, dive->when);
|
show_date(b, dive->when);
|
||||||
put_format(b, " duration='%u:%02u min'>\n",
|
put_format(b, " duration='%u:%02u min'>\n",
|
||||||
FRACTION(dive->dc.duration.seconds, 60));
|
FRACTION(dive->dc.duration.seconds, 60));
|
||||||
|
@ -507,7 +478,7 @@ static void save_one_device(void *_f, const char *model, uint32_t deviceid,
|
||||||
put_format(b, "/>\n");
|
put_format(b, "/>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VERSION 2
|
#define VERSION 3
|
||||||
|
|
||||||
int save_dives(const char *filename)
|
int save_dives(const char *filename)
|
||||||
{
|
{
|
||||||
|
@ -529,8 +500,34 @@ void save_dives_buffer(struct membuffer *b, const bool select_only)
|
||||||
call_for_each_dc(b, save_one_device);
|
call_for_each_dc(b, save_one_device);
|
||||||
if (autogroup)
|
if (autogroup)
|
||||||
put_format(b, " <autogroup state='1' />\n");
|
put_format(b, " <autogroup state='1' />\n");
|
||||||
put_format(b, "</settings>\n<dives>\n");
|
put_format(b, "</settings>\n");
|
||||||
|
|
||||||
|
/* save the dive sites */
|
||||||
|
put_format(b, "<divesites>\n");
|
||||||
|
for (i = 0; i < dive_site_table.nr; i++) {
|
||||||
|
struct dive_site *ds = get_dive_site(i);
|
||||||
|
if (dive_site_is_empty(ds)) {
|
||||||
|
int j;
|
||||||
|
struct dive *d;
|
||||||
|
for_each_dive(j, d) {
|
||||||
|
if (d->dive_site_uuid == ds->uuid)
|
||||||
|
d->dive_site_uuid = 0;
|
||||||
|
}
|
||||||
|
delete_dive_site(get_dive_site(i)->uuid);
|
||||||
|
i--; // since we just deleted that one
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
put_format(b, "<site uuid='%8x' ", ds->uuid);
|
||||||
|
show_utf8(b, ds->name, " name='", "'", 1);
|
||||||
|
if (ds->latitude.udeg || ds->longitude.udeg) {
|
||||||
|
put_degrees(b, ds->latitude, " gps='", " ");
|
||||||
|
put_degrees(b, ds->longitude, "", "'");
|
||||||
|
}
|
||||||
|
show_utf8(b, ds->description, " description='", "'", 1);
|
||||||
|
show_utf8(b, ds->notes, " notes='", "'", 1);
|
||||||
|
put_format(b, "/>\n");
|
||||||
|
}
|
||||||
|
put_format(b, "</divesites>\n<dives>\n");
|
||||||
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
|
for (trip = dive_trip_list; trip != NULL; trip = trip->next)
|
||||||
trip->index = 0;
|
trip->index = 0;
|
||||||
|
|
||||||
|
@ -605,7 +602,15 @@ static void try_to_backup(const char *filename)
|
||||||
while (extension[i][0] != '\0') {
|
while (extension[i][0] != '\0') {
|
||||||
int elen = strlen(extension[i]);
|
int elen = strlen(extension[i]);
|
||||||
if (strcasecmp(filename + flen - elen, extension[i]) == 0) {
|
if (strcasecmp(filename + flen - elen, extension[i]) == 0) {
|
||||||
|
if (last_xml_version < VERSION) {
|
||||||
|
int se_len = strlen(extension[i]) + 5;
|
||||||
|
char *special_ext = malloc(se_len);
|
||||||
|
snprintf(special_ext, se_len, "%s.v%d", extension[i], last_xml_version);
|
||||||
|
save_backup(filename, extension[i], special_ext);
|
||||||
|
free(special_ext);
|
||||||
|
} else {
|
||||||
save_backup(filename, extension[i], "bak");
|
save_backup(filename, extension[i], "bak");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -29,6 +29,7 @@ HEADERS = \
|
||||||
display.h \
|
display.h \
|
||||||
dive.h \
|
dive.h \
|
||||||
divelist.h \
|
divelist.h \
|
||||||
|
divesite.h \
|
||||||
file.h \
|
file.h \
|
||||||
gettextfromc.h \
|
gettextfromc.h \
|
||||||
gettext.h \
|
gettext.h \
|
||||||
|
@ -119,6 +120,7 @@ SOURCES = \
|
||||||
device.c \
|
device.c \
|
||||||
dive.c \
|
dive.c \
|
||||||
divelist.c \
|
divelist.c \
|
||||||
|
divesite.c \
|
||||||
equipment.c \
|
equipment.c \
|
||||||
file.c \
|
file.c \
|
||||||
gettextfromc.cpp \
|
gettextfromc.cpp \
|
||||||
|
@ -238,7 +240,8 @@ FORMS = \
|
||||||
qt-ui/listfilter.ui \
|
qt-ui/listfilter.ui \
|
||||||
qt-ui/diveshareexportdialog.ui \
|
qt-ui/diveshareexportdialog.ui \
|
||||||
qt-ui/filterwidget.ui \
|
qt-ui/filterwidget.ui \
|
||||||
qt-ui/plannerDetails.ui
|
qt-ui/plannerDetails.ui \
|
||||||
|
qt-ui/locationInformation.ui
|
||||||
|
|
||||||
# Nether usermanual or printing is supported on android right now
|
# Nether usermanual or printing is supported on android right now
|
||||||
android: FORMS -= qt-ui/printoptions.ui
|
android: FORMS -= qt-ui/printoptions.ui
|
||||||
|
|
|
@ -638,12 +638,12 @@ static void parse_divespot(char *buf)
|
||||||
uemis_set_divelocation(divespot, locationstring, latitude, longitude);
|
uemis_set_divelocation(divespot, locationstring, latitude, longitude);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void track_divespot(char *val, int diveid, char **location, degrees_t *latitude, degrees_t *longitude)
|
static void track_divespot(char *val, int diveid, uint32_t dive_site_uuid)
|
||||||
{
|
{
|
||||||
int id = atoi(val);
|
int id = atoi(val);
|
||||||
if (id >= 0 && id > nr_divespots)
|
if (id >= 0 && id > nr_divespots)
|
||||||
nr_divespots = id;
|
nr_divespots = id;
|
||||||
uemis_mark_divelocation(diveid, id, location, latitude, longitude);
|
uemis_mark_divelocation(diveid, id, dive_site_uuid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,7 +783,8 @@ static bool process_raw_buffer(device_data_t *devdata, uint32_t deviceid, char *
|
||||||
if (for_dive)
|
if (for_dive)
|
||||||
*for_dive = atoi(val);
|
*for_dive = atoi(val);
|
||||||
} else if (!log && dive && !strcmp(tag, "divespot_id")) {
|
} else if (!log && dive && !strcmp(tag, "divespot_id")) {
|
||||||
track_divespot(val, dive->dc.diveid, &dive->location, &dive->latitude, &dive->longitude);
|
dive->dive_site_uuid = create_dive_site("from Uemis");
|
||||||
|
track_divespot(val, dive->dc.diveid, dive->dive_site_uuid);
|
||||||
} else if (dive) {
|
} else if (dive) {
|
||||||
parse_tag(dive, tag, val);
|
parse_tag(dive, tag, val);
|
||||||
}
|
}
|
||||||
|
|
23
uemis.c
23
uemis.c
|
@ -103,9 +103,7 @@ struct uemis_helper {
|
||||||
int diveid;
|
int diveid;
|
||||||
int lbs;
|
int lbs;
|
||||||
int divespot;
|
int divespot;
|
||||||
char **location;
|
int dive_site_uuid;
|
||||||
degrees_t *latitude;
|
|
||||||
degrees_t *longitude;
|
|
||||||
struct uemis_helper *next;
|
struct uemis_helper *next;
|
||||||
};
|
};
|
||||||
static struct uemis_helper *uemis_helper = NULL;
|
static struct uemis_helper *uemis_helper = NULL;
|
||||||
|
@ -150,27 +148,22 @@ int uemis_get_weight_unit(int diveid)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uemis_mark_divelocation(int diveid, int divespot, char **location, degrees_t *latitude, degrees_t *longitude)
|
void uemis_mark_divelocation(int diveid, int divespot, uint32_t dive_site_uuid)
|
||||||
{
|
{
|
||||||
struct uemis_helper *hp = uemis_get_helper(diveid);
|
struct uemis_helper *hp = uemis_get_helper(diveid);
|
||||||
hp->divespot = divespot;
|
hp->divespot = divespot;
|
||||||
hp->location = location;
|
hp->dive_site_uuid = dive_site_uuid;
|
||||||
hp->longitude = longitude;
|
|
||||||
hp->latitude = latitude;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude)
|
void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude)
|
||||||
{
|
{
|
||||||
struct uemis_helper *hp = uemis_helper;
|
struct uemis_helper *hp = uemis_helper;
|
||||||
#if 0 /* seems overkill */
|
|
||||||
if (!g_utf8_validate(text, -1, NULL))
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
while (hp) {
|
while (hp) {
|
||||||
if (hp->divespot == divespot && hp->location) {
|
if (hp->divespot == divespot) {
|
||||||
*hp->location = strdup(text);
|
struct dive_site *ds = get_dive_site_by_uuid(hp->dive_site_uuid);
|
||||||
hp->longitude->udeg = round(longitude * 1000000);
|
ds->name = strdup(text);
|
||||||
hp->latitude->udeg = round(latitude * 1000000);
|
ds->longitude.udeg = round(longitude * 1000000);
|
||||||
|
ds->latitude.udeg = round(latitude * 1000000);
|
||||||
}
|
}
|
||||||
hp = hp->next;
|
hp = hp->next;
|
||||||
}
|
}
|
||||||
|
|
2
uemis.h
2
uemis.h
|
@ -14,7 +14,7 @@ extern "C" {
|
||||||
|
|
||||||
void uemis_parse_divelog_binary(char *base64, void *divep);
|
void uemis_parse_divelog_binary(char *base64, void *divep);
|
||||||
int uemis_get_weight_unit(int diveid);
|
int uemis_get_weight_unit(int diveid);
|
||||||
void uemis_mark_divelocation(int diveid, int divespot, char **location, degrees_t *latitude, degrees_t *longitude);
|
void uemis_mark_divelocation(int diveid, int divespot, uint32_t dive_site_uuid);
|
||||||
void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude);
|
void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -27,11 +27,11 @@ void writeMarkers(struct membuffer *b, const bool selected_only)
|
||||||
if (!dive->selected)
|
if (!dive->selected)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (dive->latitude.udeg == 0 && dive->longitude.udeg == 0)
|
struct dive_site *ds = get_dive_site_for_dive(dive);
|
||||||
|
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, dive->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", "");
|
put_degrees(b, ds->longitude, ",", ")});\n");
|
||||||
put_degrees(b, dive->longitude, ",", ")});\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>");
|
||||||
|
@ -49,7 +49,7 @@ void writeMarkers(struct membuffer *b, const bool selected_only)
|
||||||
put_HTML_watertemp(b, dive, pre, "</p>");
|
put_HTML_watertemp(b, dive, pre, "</p>");
|
||||||
snprintf(pre, sizeof(pre), "<p>%s <b>", translate("gettextFromC", "Location:"));
|
snprintf(pre, sizeof(pre), "<p>%s <b>", translate("gettextFromC", "Location:"));
|
||||||
put_string(b, pre);
|
put_string(b, pre);
|
||||||
put_HTML_quoted(b, dive->location);
|
put_HTML_quoted(b, get_dive_location(dive));
|
||||||
put_string(b, "</b></p>");
|
put_string(b, "</b></p>");
|
||||||
snprintf(pre, sizeof(pre), "<p> %s ", translate("gettextFromC", "Notes:"));
|
snprintf(pre, sizeof(pre), "<p> %s ", translate("gettextFromC", "Notes:"));
|
||||||
put_HTML_notes(b, dive, pre, " </p>");
|
put_HTML_notes(b, dive, pre, " </p>");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue