Changeset 56de6b7 in subsurface


Ignore:
Timestamp:
Feb 13, 2015, 11:52:41 PM (3 years ago)
Author:
Dirk Hohndel <dirk@…>
Branches:
Mtest, android_test, dcDownload, foratdotde, gitMerge, gitdebug, gitpictures, ios, master, mergeKirigamiPort, pictimeshift, resolutionIndependence, spinner, testTomaz, testing, v4.5-branch
Children:
0f2d021
Parents:
2843dc3 (diff), f81e2c1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'divesites'

This brings in the dive site infrastructure and initial UI work

Files:
3 added
30 edited

Legend:

Unmodified
Added
Removed
  • dive.c

    r6374d9c r32ad046  
    1414 * here */
    1515struct dive displayed_dive;
     16struct dive_site displayed_dive_site;
    1617
    1718struct tag_entry *g_tag_list = NULL;
     
    438439        free(d->buddy);
    439440        free(d->divemaster);
    440         free(d->location);
    441441        free(d->notes);
    442442        free(d->suit);
     
    464464        d->buddy = copy_string(s->buddy);
    465465        d->divemaster = copy_string(s->divemaster);
    466         d->location = copy_string(s->location);
    467466        d->notes = copy_string(s->notes);
    468467        d->suit = copy_string(s->suit);
     
    501500        if (clear)
    502501                clear_dive(d);
    503         CONDITIONAL_COPY_STRING(location);
    504502        CONDITIONAL_COPY_STRING(notes);
    505503        CONDITIONAL_COPY_STRING(divemaster);
     
    510508        if (what.visibility)
    511509                d->visibility = s->visibility;
    512         if (what.gps) {
    513                 d->longitude = s->longitude;
    514                 d->latitude = s->latitude;
    515         }
     510        if (what.divesite)
     511                d->dive_site_uuid = s->dive_site_uuid;
    516512        if (what.tags)
    517513                STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl);
     
    27002696
    27012697        for_each_dive (i, d) {
    2702                 if (same_string(d->location, location))
     2698                if (same_string(get_dive_location(d), location))
    27032699                        counter++;
    27042700        }
     
    27452741        res->selected = a->selected || b->selected;
    27462742        merge_trip(res, a, b);
    2747         MERGE_NONZERO(res, a, b, latitude.udeg);
    2748         MERGE_NONZERO(res, a, b, longitude.udeg);
    2749         MERGE_TXT(res, a, b, location);
    27502743        MERGE_TXT(res, a, b, notes);
    27512744        MERGE_TXT(res, a, b, buddy);
     
    27672760        else
    27682761                join_dive_computers(&res->dc, &a->dc, &b->dc, 0);
    2769 
     2762        res->dive_site_uuid = a->dive_site_uuid ?: b->dive_site_uuid;
    27702763        fixup_dive(res);
    27712764        return res;
     
    29322925void dive_set_geodata_from_picture(struct dive *d, struct picture *pic)
    29332926{
    2934         if (!d->latitude.udeg && pic->latitude.udeg) {
    2935                 d->latitude = pic->latitude;
    2936                 d->longitude = pic->longitude;
     2927        struct dive_site *ds = get_dive_site_by_uuid(d->dive_site_uuid);
     2928        if (!dive_site_has_gps_location(ds) && (pic->latitude.udeg || pic->longitude.udeg)) {
     2929                ds->latitude = pic->latitude;
     2930                ds->longitude = pic->longitude;
    29372931        }
    29382932}
  • dive.h

    r585d6a0 r32ad046  
    99#include <sqlite3.h>
    1010#include <string.h>
     11#include "divesite.h"
    1112
    1213/* Windows has no MIN/MAX macros - so let's just roll our own */
     
    4748#include <stdbool.h>
    4849#endif
     50
     51extern int last_xml_version;
    4952
    5053enum dive_comp_type {OC, CCR, PSCR, FREEDIVE, NUM_DC_TYPE};     // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type
     
    319322        bool downloaded;
    320323        timestamp_t when;
    321         char *location;
     324        uint32_t dive_site_uuid;
    322325        char *notes;
    323326        char *divemaster, *buddy;
    324327        int rating;
    325         degrees_t latitude, longitude;
    326328        int visibility; /* 0 - 5 star rating */
    327329        cylinder_t cylinder[MAX_CYLINDERS];
     
    348350/* when selectively copying dive information, which parts should be copied? */
    349351struct dive_components {
    350         unsigned int location : 1;
     352        unsigned int divesite : 1;
    351353        unsigned int notes : 1;
    352354        unsigned int divemaster : 1;
     
    355357        unsigned int rating : 1;
    356358        unsigned int visibility : 1;
    357         unsigned int gps : 1;
    358359        unsigned int tags : 1;
    359360        unsigned int cylinders : 1;
     
    387388extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc);
    388389
    389 static inline int dive_has_gps_location(struct dive *dive)
    390 {
    391         return dive->latitude.udeg || dive->longitude.udeg;
    392 }
    393 
    394 static inline void copy_gps_location(struct dive *from, struct dive *to)
    395 {
    396         if (from && to) {
    397                 to->latitude.udeg = from->latitude.udeg;
    398                 to->longitude.udeg = from->longitude.udeg;
    399                 if (!to->location) {
    400                         to->location = strdup(from->location);
    401                 }
    402         }
    403 }
    404 
    405390static inline int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null)
    406391{
     
    490475extern struct dive_table dive_table;
    491476extern struct dive displayed_dive;
     477extern struct dive_site displayed_dive_site;
    492478extern int selected_dive;
    493479extern unsigned int dc_number;
     
    495481#define current_dc (get_dive_dc(current_dive, dc_number))
    496482
    497 static inline struct dive *get_gps_location(int nr, struct dive_table *table)
    498 {
    499         if (nr >= table->nr || nr < 0)
    500                 return NULL;
    501         return table->dives[nr];
    502 }
    503 
    504483static inline struct dive *get_dive(int nr)
    505484{
     
    514493                return NULL;
    515494        return dt->dives[nr];
     495}
     496
     497static inline struct dive_site *get_dive_site_for_dive(struct dive *dive)
     498{
     499        if (dive)
     500                return get_dive_site_by_uuid(dive->dive_site_uuid);
     501        return NULL;
     502}
     503
     504static inline char *get_dive_location(struct dive *dive)
     505{
     506        struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid);
     507        if (ds && ds->name)
     508                return ds->name;
     509        return NULL;
    516510}
    517511
     
    612606#endif
    613607        return i;
     608}
     609
     610static inline bool dive_site_has_gps_location(struct dive_site *ds)
     611{
     612        return ds && (ds->latitude.udeg || ds->longitude.udeg);
     613}
     614
     615static inline int dive_has_gps_location(struct dive *dive)
     616{
     617        return dive_site_has_gps_location(get_dive_site_by_uuid(dive->dive_site_uuid));
    614618}
    615619
  • divelist.c

    r58173d7 rc109b98  
    679679{
    680680        dive_trip_t *dive_trip = calloc(1, sizeof(dive_trip_t));
     681
    681682        dive_trip->when = dive->when;
    682         if (dive->location)
    683                 dive_trip->location = strdup(dive->location);
     683        dive_trip->location = copy_string(get_dive_location(dive));
    684684        insert_trip(&dive_trip);
    685685
     
    714714                        dive_trip_t *trip = lastdive->divetrip;
    715715                        add_dive_to_trip(dive, trip);
    716                         if (dive->location && !trip->location)
    717                                 trip->location = strdup(dive->location);
     716                        if (get_dive_location(dive) && !trip->location)
     717                                trip->location = copy_string(get_dive_location(dive));
    718718                        lastdive = dive;
    719719                        continue;
     
    746746        /* free all allocations */
    747747        free(dive->dc.sample);
    748         free((void *)dive->location);
    749748        free((void *)dive->notes);
    750749        free((void *)dive->divemaster);
  • liquivision.c

    rab7f61e r4c87ccf  
    122122                // Dive location, assemble Location and Place
    123123                unsigned int len, place_len;
     124                char *location;
    124125                len = array_uint32_le(buf + ptr);
    125126                ptr += 4;
     
    127128
    128129                if (len && place_len) {
    129                         dive->location = malloc(len + place_len + 4);
    130                         memset(dive->location, 0, len + place_len + 4);
    131                         memcpy(dive->location, buf + ptr, len);
    132                         memcpy(dive->location + len, ", ", 2);
    133                         memcpy(dive->location + len + 2, buf + ptr + len + 4, place_len);
     130                        location = malloc(len + place_len + 4);
     131                        memset(location, 0, len + place_len + 4);
     132                        memcpy(location, buf + ptr, len);
     133                        memcpy(location + len, ", ", 2);
     134                        memcpy(location + len + 2, buf + ptr + len + 4, place_len);
    134135                } else if (len) {
    135                         dive->location = strndup(buf + ptr, len);
     136                        location = strndup(buf + ptr, len);
    136137                } else if (place_len) {
    137                         dive->location = strndup(buf + ptr + len + 4, place_len);
    138                 }
     138                        location = strndup(buf + ptr + len + 4, place_len);
     139                }
     140                dive->dive_site_uuid = create_dive_site(location);
     141                free(location);
    139142
    140143                ptr += len + 4 + place_len;
  • load-git.c

    re219bc7 rd2baa36  
    2424
    2525extern degrees_t parse_degrees(char *buf, char **end);
    26 static void parse_dive_gps(char *line, struct membuffer *str, void *_dive)
    27 {
    28         struct dive *dive = _dive;
    29 
    30         dive->latitude = parse_degrees(line, &line);
    31         dive->longitude = parse_degrees(line, &line);
    32 }
    3326
    3427static char *get_utf8(struct membuffer *b)
     
    146139{ return strtoul(line, NULL, 16); }
    147140
     141static void parse_dive_gps(char *line, struct membuffer *str, void *_dive)
     142{
     143        uint32_t uuid;
     144        degrees_t latitude = parse_degrees(line, &line);
     145        degrees_t longitude = parse_degrees(line, &line);
     146        struct dive *dive = _dive;
     147        struct dive_site *ds = get_dive_site_for_dive(dive);
     148        if (!ds) {
     149                uuid = get_dive_site_uuid_by_gps(latitude, longitude, NULL);
     150                if (!uuid)
     151                        uuid = create_dive_site_with_gps("", latitude, longitude);
     152                dive->dive_site_uuid = uuid;
     153        } else {
     154                ds->latitude = latitude;
     155                ds->longitude = longitude;
     156        }
     157
     158}
     159
    148160static void parse_dive_location(char *line, struct membuffer *str, void *_dive)
    149 { struct dive *dive = _dive; dive->location = get_utf8(str); }
     161{
     162        uint32_t uuid;
     163        char *name = get_utf8(str);
     164        struct dive *dive = _dive;
     165        struct dive_site *ds = get_dive_site_for_dive(dive);
     166        fprintf(stderr, "looking for a site named {%s} ", name);
     167        if (!ds) {
     168                uuid = get_dive_site_uuid_by_name(name, NULL);
     169                if (!uuid) { fprintf(stderr, "found none, creating\n");
     170                        uuid = create_dive_site(name);
     171                } else { fprintf(stderr, "found one with uuid %8x\n", uuid); }
     172                dive->dive_site_uuid = uuid;
     173        } else {
     174                fprintf(stderr, "dive had site with uuid %8x and name {%s}\n", ds->uuid, ds->name);
     175                ds->name = name;
     176        }
     177}
    150178
    151179static void parse_dive_divemaster(char *line, struct membuffer *str, void *_dive)
     
    160188static void parse_dive_notes(char *line, struct membuffer *str, void *_dive)
    161189{ struct dive *dive = _dive; dive->notes = get_utf8(str); }
     190
     191static void parse_dive_divesiteid(char *line, struct membuffer *str, void *_dive)
     192{ struct dive *dive = _dive; dive->dive_site_uuid = get_hex(line); }
    162193
    163194/*
     
    205236static void parse_dive_notrip(char *line, struct membuffer *str, void *_dive)
    206237{ struct dive *dive = _dive; dive->tripflag = NO_TRIP; }
     238
     239static void parse_site_description(char *line, struct membuffer *str, void *_ds)
     240{ struct dive_site *ds = _ds; ds->description = strdup(mb_cstring(str)); }
     241
     242static void parse_site_name(char *line, struct membuffer *str, void *_ds)
     243{ struct dive_site *ds = _ds; ds->name = strdup(mb_cstring(str)); }
     244
     245static void parse_site_notes(char *line, struct membuffer *str, void *_ds)
     246{ struct dive_site *ds = _ds; ds->notes = strdup(mb_cstring(str)); }
     247
     248extern degrees_t parse_degrees(char *buf, char **end);
     249static void parse_site_gps(char *line, struct membuffer *str, void *_ds)
     250{
     251        struct dive_site *ds = _ds;
     252
     253        ds->latitude = parse_degrees(line, &line);
     254        ds->longitude = parse_degrees(line, &line);
     255}
    207256
    208257/* Parse key=val parts of samples and cylinders etc */
     
    673722 * you read with a version of subsurface that doesn't know about it.
    674723 */
    675 #define VERSION 2
     724#define VERSION 3
    676725static void parse_settings_version(char *line, struct membuffer *str, void *_unused)
    677726{
     
    784833#undef D
    785834#define D(x) { #x, parse_dive_ ## x }
    786         D(airtemp), D(buddy), D(cylinder), D(divemaster), D(duration),
     835        D(airtemp), D(buddy), D(cylinder), D(divemaster), D(divesiteid), D(duration),
    787836        D(gps), D(location), D(notes), D(notrip), D(rating), D(suit),
    788837        D(tags), D(visibility), D(watertemp), D(weightsystem)
     
    792841{
    793842        match_action(line, str, _dive, dive_action, ARRAY_SIZE(dive_action));
     843}
     844
     845/* These need to be sorted! */
     846struct keyword_action site_action[] = {
     847#undef D
     848#define D(x) { #x, parse_site_ ## x }
     849        D(description), D(gps), D(name), D(notes)
     850};
     851
     852static void site_parser(char *line, struct membuffer *str, void *_ds)
     853{
     854        match_action(line, str, _ds, site_action, ARRAY_SIZE(site_action));
    794855}
    795856
     
    11911252                return picture_directory(root, name);
    11921253
     1254        if (!strcmp(name, "01-Divesites"))
     1255                return GIT_WALK_OK;
     1256
    11931257        while (isdigit(c = name[digits]))
    11941258                digits++;
     
    12811345        cylinder_index = weightsystem_index = 0;
    12821346        for_each_line(blob, dive_parser, active_dive);
     1347        git_blob_free(blob);
     1348        return 0;
     1349}
     1350
     1351static int parse_site_entry(git_repository *repo, const git_tree_entry *entry, const char *suffix)
     1352{
     1353        if (*suffix == '\0')
     1354                return report_error("Dive site without uuid");
     1355        struct dive_site *ds = alloc_dive_site();
     1356        ds->uuid = strtol(suffix, NULL, 16);
     1357        git_blob *blob = git_tree_entry_blob(repo, entry);
     1358        if (!blob)
     1359                return report_error("Unable to read dive site file");
     1360        for_each_line(blob, site_parser, ds);
    12831361        git_blob_free(blob);
    12841362        return 0;
     
    13441422        dive_trip_t *trip = active_trip;
    13451423        const char *name = git_tree_entry_name(entry);
    1346 
    13471424        switch (*name) {
    13481425        /* Picture file? They are saved as time offsets in the dive */
     
    13571434                        return parse_dive_entry(repo, entry, name+4);
    13581435                break;
     1436        case 'S':
     1437                if (!strncmp(name, "Site", 4))
     1438                        return parse_site_entry(repo, entry, name + 5);
    13591439        case '0':
    13601440                if (trip && !strcmp(name, "00-Trip"))
  • parse-xml.c

    r4a8e148 r6dd6e906  
    2222int verbose, quit;
    2323int metric = 1;
     24int last_xml_version = -1;
    2425
    2526static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params);
     
    129130static struct divecomputer *cur_dc;
    130131static struct dive *cur_dive;
     132static struct dive_site *cur_dive_site;
    131133static dive_trip_t *cur_trip = NULL;
    132134static struct sample *cur_sample;
     
    934936        if (MATCH("sensor3.sample", double_to_o2pressure, &sample->o2sensor[2])) // up to 3 CCR sensors
    935937                return;
    936         if (MATCH("po2.sample", double_to_o2pressure, &sample->setpoint)) {
    937                 cur_dive->dc.divemode = CCR;
    938                 return;
    939         }
     938        if (MATCH("po2.sample", double_to_o2pressure, &sample->setpoint))
     939                return;
    940940        if (MATCH("heartbeat", get_uint8, &sample->heartbeat))
    941941                return;
     
    969969static const char *country, *city;
    970970
    971 static void divinglog_place(char *place, char **location)
     971static void divinglog_place(char *place, uint32_t *uuid)
    972972{
    973973        char buffer[1024], *p;
    974974        int len;
    975975
    976         len = snprintf(buffer, sizeof(buffer),
    977                        "%s%s%s%s%s",
    978                        place,
    979                        city ? ", " : "",
    980                        city ? city : "",
    981                        country ? ", " : "",
    982                        country ? country : "");
    983 
    984         p = malloc(len + 1);
    985         memcpy(p, buffer, len + 1);
    986         *location = p;
     976        snprintf(buffer, sizeof(buffer),
     977                 "%s%s%s%s%s",
     978                 place,
     979                 city ? ", " : "",
     980                 city ? city : "",
     981                 country ? ", " : "",
     982                 country ? country : "");
     983        *uuid = get_dive_site_uuid_by_name(buffer, NULL);
     984        if (*uuid == 0)
     985                *uuid = create_dive_site(buffer);
    987986
    988987        city = NULL;
     
    10061005               MATCH("name.country", utf8_string, &country) ||
    10071006               MATCH("name.city", utf8_string, &city) ||
    1008                MATCH("name.place", divinglog_place, &dive->location) ||
     1007               MATCH("name.place", divinglog_place, &dive->dive_site_uuid) ||
    10091008               0;
    10101009}
     
    11281127{
    11291128        char *end;
    1130 
    1131         dive->latitude = parse_degrees(buffer, &end);
     1129        degrees_t latitude = parse_degrees(buffer, &end);
     1130        struct dive_site *ds = get_dive_site_for_dive(dive);
     1131        if (!ds) {
     1132                dive->dive_site_uuid = create_dive_site_with_gps(NULL, latitude, (degrees_t){0});
     1133        } else {
     1134                if (ds->latitude.udeg && ds->latitude.udeg != latitude.udeg)
     1135                        fprintf(stderr, "Oops, changing the latitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)");
     1136                ds->latitude = latitude;
     1137        }
    11321138}
    11331139
     
    11351141{
    11361142        char *end;
    1137 
    1138         dive->longitude = parse_degrees(buffer, &end);
    1139 }
    1140 
    1141 static void gps_location(char *buffer, struct dive *dive)
     1143        degrees_t longitude = parse_degrees(buffer, &end);
     1144        struct dive_site *ds = get_dive_site_for_dive(dive);
     1145        if (!ds) {
     1146                dive->dive_site_uuid = create_dive_site_with_gps(NULL, (degrees_t){0}, longitude);
     1147        } else {
     1148                if (ds->longitude.udeg && ds->longitude.udeg != longitude.udeg)
     1149                        fprintf(stderr, "Oops, changing the longitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)");
     1150                ds->longitude = longitude;
     1151        }
     1152
     1153}
     1154
     1155static void gps_location(char *buffer, struct dive_site *ds)
    11421156{
    11431157        char *end;
    11441158
    1145         dive->latitude = parse_degrees(buffer, &end);
    1146         dive->longitude = parse_degrees(end, &end);
     1159        ds->latitude = parse_degrees(buffer, &end);
     1160        ds->longitude = parse_degrees(end, &end);
     1161}
     1162
     1163static void gps_in_dive(char *buffer, struct dive *dive)
     1164{
     1165        char *end;
     1166        struct dive_site *ds = NULL;
     1167        degrees_t latitude = parse_degrees(buffer, &end);
     1168        degrees_t longitude = parse_degrees(end, &end);
     1169        fprintf(stderr, "got lat %f lon %f\n", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0);
     1170        uint32_t uuid = dive->dive_site_uuid;
     1171        if (uuid == 0) {
     1172                uuid = get_dive_site_uuid_by_gps(latitude, longitude, &ds);
     1173                if (ds) {
     1174                        fprintf(stderr, "found dive site {%s} with these coordinates\n", ds->name);
     1175                        dive->dive_site_uuid = uuid;
     1176                } else {
     1177                        fprintf(stderr, "found no uuid in dive, no existing dive site with these coordinates, creating a new divesite without name and above GPS\n");
     1178                        dive->dive_site_uuid = create_dive_site_with_gps("", latitude, longitude);
     1179                }
     1180        } else {
     1181                fprintf(stderr, "found uuid in dive, checking to see if we should add GPS\n");
     1182                struct dive_site *ds = get_dive_site_by_uuid(uuid);
     1183                if (dive_site_has_gps_location(ds) &&
     1184                    (latitude.udeg != 0 || longitude.udeg != 0) &&
     1185                    (ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) {
     1186                        // Houston, we have a problem
     1187                        fprintf(stderr, "dive site uuid in dive, but gps location (%10.6f/%10.6f) different from dive location (%10.6f/%10.6f)\n",
     1188                                ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0,
     1189                                latitude.udeg / 1000000.0, longitude.udeg / 1000000.0);
     1190                        int len = ds->notes ? strlen(ds->notes) : 0;
     1191                        len += sizeof("\nalternative coordinates") + 24;
     1192                        char *notes = malloc(len);
     1193                        snprintf(notes, len, "%s\nalternative coordinates %11.6f/%11.6f",
     1194                                 ds->notes ?: "", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0);
     1195                        free(ds->notes);
     1196                        ds->notes = notes;
     1197                } else {
     1198                        fprintf(stderr, "let's add the gps coordinates to divesite with uuid %8x and name %s\n", ds->uuid, ds->name ?: "(none)");
     1199                        ds->latitude = latitude;
     1200                        ds->longitude = longitude;
     1201                }
     1202        }
     1203}
     1204
     1205static void add_dive_site(char *buffer, struct dive *dive)
     1206{
     1207        fprintf(stderr, "add_dive_site with name %s\n", buffer);
     1208        int size = trimspace(buffer);
     1209        if(size) {
     1210                uint32_t uuid = dive->dive_site_uuid;
     1211                struct dive_site *ds = get_dive_site_by_uuid(uuid);
     1212                if (uuid && !ds) {
     1213                        // that's strange - we have a uuid but it doesn't exist - let's just ignore it
     1214                        fprintf(stderr, "dive contains a non-existing dive site uuid %x\n", dive->dive_site_uuid);
     1215                        uuid = 0;
     1216                }
     1217                if (!uuid)
     1218                        // if the dive doesn't have a uuid, check if there's already a dive site by this name
     1219                        uuid = get_dive_site_uuid_by_name(buffer, &ds);
     1220                if (ds) {
     1221                        // we have a uuid, let's hope there isn't a different name
     1222                        fprintf(stderr, "have existing site with name {%s} gps %f/%f ", ds->name, ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0);
     1223                        if (same_string(ds->name, "")) {
     1224                                fprintf(stderr, "so now add name {%s}\n", buffer);
     1225                                ds->name = copy_string(buffer);
     1226                        } else if (!same_string(ds->name, buffer)) {
     1227                                // coin toss, let's just keep the first name we found
     1228                                fprintf(stderr, "which means the dive already links to dive site of different name {%s} / {%s}\n", ds->name, buffer);
     1229                        }
     1230                } else {
     1231                        fprintf(stderr, "no uuid, create new dive site with name {%s}\n", buffer);
     1232                        dive->dive_site_uuid = create_dive_site(buffer);
     1233                }
     1234        }
    11471235}
    11481236
     
    11741262                break;
    11751263        }
    1176 
     1264        if (MATCH("divesiteid", hex_value, &dive->dive_site_uuid))
     1265                return;
    11771266        if (MATCH("number", get_index, &dive->number))
    11781267                return;
     
    12041293        if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end))
    12051294                return;
    1206         if (MATCH("gps", gps_location, dive))
    1207                 return;
    1208         if (MATCH("Place", gps_location, dive))
     1295        if (MATCH("gps", gps_in_dive, dive))
     1296                return;
     1297        if (MATCH("Place", gps_in_dive, dive))
    12091298                return;
    12101299        if (MATCH("latitude", gps_lat, dive))
     
    12201309        if (MATCH("lon", gps_long, dive))
    12211310                return;
    1222         if (MATCH("location", utf8_string, &dive->location))
    1223                 return;
    1224         if (MATCH("name.dive", utf8_string, &dive->location))
     1311        if (MATCH("location", add_dive_site, dive))
     1312                return;
     1313        if (MATCH("name.dive", add_dive_site, dive))
    12251314                return;
    12261315        if (MATCH("suit", utf8_string, &dive->suit))
     
    12891378
    12901379        nonmatch("trip", name, buf);
     1380}
     1381
     1382/* We're processing a divesite entry - try to fill the components */
     1383static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, char *buf)
     1384{
     1385        start_match("divesite", name, buf);
     1386
     1387        struct dive_site *ds = *ds_p;
     1388
     1389        if (MATCH("uuid", hex_value, &ds->uuid))
     1390                return;
     1391        if (MATCH("name", utf8_string, &ds->name))
     1392                return;
     1393        if (MATCH("description", utf8_string, &ds->description))
     1394                return;
     1395        if (MATCH("notes", utf8_string, &ds->notes))
     1396                return;
     1397        if (MATCH("gps", gps_location, ds))
     1398                return;
     1399
     1400        nonmatch("divesite", name, buf);
    12911401}
    12921402
     
    13061416{
    13071417        return (cur_dive &&
    1308                 (cur_dive->location || cur_dive->when || cur_dive->dc.samples));
     1418                (cur_dive->dive_site_uuid || cur_dive->when || cur_dive->dc.samples));
    13091419}
    13101420
     
    13491459        reset_dc_settings();
    13501460}
     1461
     1462static void dive_site_start(void)
     1463{
     1464        if (cur_dive_site)
     1465                return;
     1466        cur_dive_site = calloc(1, sizeof(struct dive_site));
     1467}
     1468
     1469static void dive_site_end(void)
     1470{
     1471        if (!cur_dive_site)
     1472                return;
     1473        if (cur_dive_site->uuid) {
     1474                uint32_t tmp = create_dive_site_with_gps(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude);
     1475                struct dive_site *ds = get_dive_site_by_uuid(tmp);
     1476                ds->uuid = cur_dive_site->uuid;
     1477                ds->notes = cur_dive_site->notes;
     1478                ds->description = cur_dive_site->description;
     1479                if (verbose > 3)
     1480                        printf("completed dive site uuid %x8 name {%s}\n", ds->uuid, ds->name);
     1481        }
     1482        free(cur_dive_site);
     1483        cur_dive_site = NULL;
     1484}
     1485
     1486// now we need to add the code to parse the parts of the divesite enry
    13511487
    13521488static void dive_start(void)
     
    15301666static void entry(const char *name, char *buf)
    15311667{
     1668        if (!strncmp(name, "version.program", sizeof("version.program") - 1) ||
     1669            !strncmp(name, "version.divelog", sizeof("version.divelog") - 1))
     1670                last_xml_version = atoi(buf);
    15321671        if (in_userid) {
    15331672                try_to_fill_userid(name, buf);
     
    15371676                try_to_fill_dc_settings(name, buf);
    15381677                try_to_match_autogroup(name, buf);
     1678                return;
     1679        }
     1680        if (cur_dive_site) {
     1681                try_to_fill_dive_site(&cur_dive_site, name, buf);
    15391682                return;
    15401683        }
     
    16671810          { "divecomputerid", dc_settings_start, dc_settings_end },
    16681811          { "settings", settings_start, settings_end },
     1812          { "site", dive_site_start, dive_site_end },
    16691813          { "dive", dive_start, dive_end },
    16701814          { "Dive", dive_start, dive_end },
     
    22922436
    22932437        if (data[2])
    2294                 utf8_string(data[2], &cur_dive->location);
     2438                add_dive_site(data[2], cur_dive);
    22952439        if (data[3])
    22962440                utf8_string(data[3], &cur_dive->buddy);
     
    23892533extern int cobalt_location(void *handle, int columns, char **data, char **column)
    23902534{
     2535        static char *location = NULL;
    23912536        if (data[0]) {
    2392                 if (cur_dive->location) {
    2393                         char *tmp = malloc(strlen(cur_dive->location) + strlen(data[0]) + 4);
     2537                if (location) {
     2538                        char *tmp = malloc(strlen(location) + strlen(data[0]) + 4);
    23942539                        if (!tmp)
    23952540                                return -1;
    2396                         sprintf(tmp, "%s / %s", cur_dive->location, data[0]);
    2397                         free(cur_dive->location);
    2398                         cur_dive->location = tmp;
     2541                        sprintf(tmp, "%s / %s", location, data[0]);
     2542                        free(location);
     2543                        location = NULL;
     2544                        cur_dive->dive_site_uuid = create_dive_site(tmp);
    23992545                } else {
    2400                         utf8_string(data[0], &cur_dive->location);
     2546                        location = strdup(data[0]);
    24012547                }
    24022548        }
    2403 
    24042549        return 0;
    24052550}
  • qt-ui/completionmodels.cpp

    r4487efca rf8b63e1b  
    4141CREATE_CSV_UPDATE_METHOD(BuddyCompletionModel, buddy);
    4242CREATE_CSV_UPDATE_METHOD(DiveMasterCompletionModel, divemaster);
    43 CREATE_UPDATE_METHOD(LocationCompletionModel, location);
    4443CREATE_UPDATE_METHOD(SuitCompletionModel, suit);
     44
     45void LocationCompletionModel::updateModel()
     46{
     47        QStringList list;
     48        struct dive_site *ds;
     49        int i = 0;
     50        for_each_dive_site(i, ds) {
     51                if (!list.contains(ds->name))
     52                        list.append(ds->name);
     53        }
     54        std::sort(list.begin(), list.end());
     55        setStringList(list);
     56}
    4557
    4658void TagCompletionModel::updateModel()
  • qt-ui/divecomponentselection.ui

    r822eb755 r32da126  
    1010    <x>0</x>
    1111    <y>0</y>
    12     <width>308</width>
    13     <height>263</height>
     12    <width>401</width>
     13    <height>317</height>
    1414   </rect>
    1515  </property>
     
    4242     <layout class="QGridLayout" name="gridLayout">
    4343      <item row="0" column="0">
    44        <widget class="QCheckBox" name="location">
     44       <widget class="QCheckBox" name="divesite">
    4545        <property name="text">
    46          <string>Location</string>
     46         <string>Dive site</string>
    4747        </property>
    4848       </widget>
     
    5252        <property name="text">
    5353         <string>Suit</string>
    54         </property>
    55        </widget>
    56       </item>
    57       <item row="1" column="0">
    58        <widget class="QCheckBox" name="gps">
    59         <property name="text">
    60          <string>GPS coordinates</string>
    61         </property>
    62        </widget>
    63       </item>
    64       <item row="2" column="0">
    65        <widget class="QCheckBox" name="divemaster">
    66         <property name="text">
    67          <string>Divemaster</string>
    68         </property>
    69        </widget>
    70       </item>
    71       <item row="3" column="0">
    72        <widget class="QCheckBox" name="buddy">
    73         <property name="text">
    74          <string>Buddy</string>
    75         </property>
    76        </widget>
    77       </item>
    78       <item row="4" column="0">
    79        <widget class="QCheckBox" name="rating">
    80         <property name="text">
    81          <string>Rating</string>
    8254        </property>
    8355       </widget>
     
    11587        <property name="text">
    11688         <string>Cylinders</string>
     89        </property>
     90       </widget>
     91      </item>
     92      <item row="1" column="0">
     93       <widget class="QCheckBox" name="divemaster">
     94        <property name="text">
     95         <string>Divemaster</string>
     96        </property>
     97       </widget>
     98      </item>
     99      <item row="2" column="0">
     100       <widget class="QCheckBox" name="buddy">
     101        <property name="text">
     102         <string>Buddy</string>
     103        </property>
     104       </widget>
     105      </item>
     106      <item row="3" column="0">
     107       <widget class="QCheckBox" name="rating">
     108        <property name="text">
     109         <string>Rating</string>
    117110        </property>
    118111       </widget>
  • qt-ui/filtermodels.cpp

    r6b038c2 r616cb18  
    250250        }
    251251        // Checked means 'Show', Unchecked means 'Hide'.
    252         QString location(d->location);
     252        QString location(get_dive_location(d));
    253253        // only show empty location dives if the user checked that.
    254254        if (location.isEmpty()) {
     
    278278        int i = 0;
    279279        for_each_dive (i, dive) {
    280                 QString location(dive->location);
     280                QString location(get_dive_location(dive));
    281281                if (!location.isEmpty() && !list.contains(location)) {
    282282                        list.append(location);
  • qt-ui/globe.cpp

    r6b038c2 r32ad046  
    165165        for_each_dive (idx, dive) {
    166166                long lat_diff, lon_diff;
    167                 if (!dive_has_gps_location(dive))
     167                struct dive_site *ds = get_dive_site_for_dive(dive);
     168                if (!dive_site_has_gps_location(ds))
    168169                        continue;
    169                 lat_diff = labs(dive->latitude.udeg - lat_udeg);
    170                 lon_diff = labs(dive->longitude.udeg - lon_udeg);
     170                lat_diff = labs(ds->latitude.udeg - lat_udeg);
     171                lon_diff = labs(ds->longitude.udeg - lon_udeg);
    171172                if (lat_diff > 180000000)
    172173                        lat_diff = 360000000 - lat_diff;
     
    187188void GlobeGPS::repopulateLabels()
    188189{
     190        struct dive_site *ds;
    189191        if (loadedDives) {
    190192                model()->treeModel()->removeDocument(loadedDives);
     
    205207                        // or it's the one that we are moving right now...
    206208                        continue;
    207                 if (dive_has_gps_location(dive)) {
    208                         GeoDataPlacemark *place = new GeoDataPlacemark(dive->location);
    209                         place->setCoordinate(dive->longitude.udeg / 1000000.0, dive->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree);
     209                if (idx == -1)
     210                        ds = &displayed_dive_site;
     211                else
     212                        ds = get_dive_site_for_dive(dive);
     213                if (dive_site_has_gps_location(ds)) {
     214                        GeoDataPlacemark *place = new GeoDataPlacemark(ds->name);
     215                        place->setCoordinate(ds->longitude.udeg / 1000000.0, ds->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree);
    210216                        // don't add dive locations twice, unless they are at least 50m apart
    211                         if (locationMap[QString(dive->location)]) {
    212                                 GeoDataCoordinates existingLocation = locationMap[QString(dive->location)]->coordinate();
     217                        if (locationMap[QString(ds->name)]) {
     218                                GeoDataCoordinates existingLocation = locationMap[QString(ds->name)]->coordinate();
    213219                                GeoDataLineString segment = GeoDataLineString();
    214220                                segment.append(existingLocation);
     
    221227                                        continue;
    222228                        }
    223                         locationMap[QString(dive->location)] = place;
     229                        locationMap[QString(ds->name)] = place;
    224230                        loadedDives->append(place);
    225231                }
     
    237243void GlobeGPS::centerOnCurrentDive()
    238244{
    239         struct dive *dive = current_dive;
     245        struct dive_site *ds = get_dive_site_for_dive(current_dive);
    240246        // dive has changed, if we had the 'editingDive', hide it.
    241         if (messageWidget->isVisible() && (!dive || dive_has_gps_location(dive) || amount_selected != 1))
     247        if (messageWidget->isVisible() && (!ds || dive_site_has_gps_location(ds) || amount_selected != 1))
    242248                messageWidget->hide();
    243249
    244250        editingDiveLocation = false;
    245         if (!dive)
    246                 return;
    247 
    248         qreal longitude = dive->longitude.udeg / 1000000.0;
    249         qreal latitude = dive->latitude.udeg / 1000000.0;
    250 
    251         if ((!dive_has_gps_location(dive) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) {
     251        if (!ds)
     252                return;
     253
     254        qreal longitude = ds->longitude.udeg / 1000000.0;
     255        qreal latitude = ds->latitude.udeg / 1000000.0;
     256
     257        if ((!dive_site_has_gps_location(ds) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) {
    252258                prepareForGetDiveCoordinates();
    253259                return;
    254260        }
    255         if (!dive_has_gps_location(dive)) {
     261        if (!dive_site_has_gps_location(ds)) {
    256262                zoomOutForNoGPS();
    257263                return;
     
    310316}
    311317
     318// This needs to update the dive site, not just this dive
    312319void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::Unit unit)
    313320{
     321        struct dive_site *ds;
    314322        messageWidget->hide();
    315323
     
    325333
    326334        // change the location of the displayed_dive and put the UI in edit mode
    327         displayed_dive.latitude.udeg = lrint(lat * 1000000.0);
    328         displayed_dive.longitude.udeg = lrint(lon * 1000000.0);
     335        displayed_dive_site.latitude.udeg = lrint(lat * 1000000.0);
     336        displayed_dive_site.longitude.udeg = lrint(lon * 1000000.0);
    329337        emit(coordinatesChanged());
    330338        repopulateLabels();
     
    342350        // there could be two scenarios that got us here; let's check if we are editing a dive
    343351        if (MainWindow::instance()->information()->isEditing() && clickOnGlobe) {
    344                 MainWindow::instance()->information()->updateCoordinatesText(lat, lon);
     352                //
     353                // FIXME
     354                // TODO
     355                //
     356                // this needs to do this on the dive site screen
     357                // MainWindow::instance()->information()->updateCoordinatesText(lat, lon);
    345358                repopulateLabels();
    346359        } else if (clickOnGlobe) {
  • qt-ui/maintab.cpp

    r194dd8bd rf81e2c1  
    5050        closeMessage();
    5151
     52        connect(ui.manageDiveSite, SIGNAL(clicked()), this, SLOT(prepareDiveSiteEdit()));
     53
    5254        QAction *action = new QAction(tr("Apply changes"), this);
    5355        connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges()));
     
    5658        action = new QAction(tr("Discard changes"), this);
    5759        connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges()));
     60        addMessageAction(action);
    5861
    5962        QShortcut *closeKey = new QShortcut(QKeySequence(Qt::Key_Escape), this);
    6063        connect(closeKey, SIGNAL(activated()), this, SLOT(escDetected()));
    61 
    62         addMessageAction(action);
    6364
    6465        if (qApp->style()->objectName() == "oxygen")
     
    7273
    7374        ui.location->installEventFilter(this);
    74         ui.coordinates->installEventFilter(this);
    7575        ui.divemaster->installEventFilter(this);
    7676        ui.buddy->installEventFilter(this);
     
    213213}
    214214
     215void MainTab::prepareDiveSiteEdit() {
     216        emit requestDiveSiteEdit(displayed_dive.dive_site_uuid);
     217}
     218
    215219void MainTab::toggleTriggeredColumn()
    216220{
     
    392396}
    393397
     398void MainTab::showLocation()
     399{
     400        ui.location->setText(get_dive_location(&displayed_dive));
     401}
     402
    394403void MainTab::updateDiveInfo(bool clear)
    395404{
     
    425434                        ui.notes->setPlainText(tmp);
    426435        }
    427 
    428436        UPDATE_TEXT(displayed_dive, notes);
    429         UPDATE_TEXT(displayed_dive, location);
    430437        UPDATE_TEXT(displayed_dive, suit);
    431438        UPDATE_TEXT(displayed_dive, divemaster);
     
    436443
    437444        if (!clear) {
    438                 updateGpsCoordinates();
     445                struct dive_site *ds = get_dive_site_by_uuid(displayed_dive.dive_site_uuid);
     446                if (ds)
     447                        ui.location->setText(ds->name);
     448                else
     449                        ui.location->clear();
    439450                // Subsurface always uses "local time" as in "whatever was the local time at the location"
    440451                // so all time stamps have no time zone information and are in UTC
     
    447458                        currentTrip = *MainWindow::instance()->dive_list()->selectedTrips().begin();
    448459                        // only use trip relevant fields
    449                         ui.coordinates->setVisible(false);
    450                         ui.CoordinatedLabel->setVisible(false);
    451460                        ui.divemaster->setVisible(false);
    452461                        ui.DivemasterLabel->setVisible(false);
     
    478487                        currentTrip = NULL;
    479488                        // make all the fields visible writeable
    480                         ui.coordinates->setVisible(true);
    481                         ui.CoordinatedLabel->setVisible(true);
    482489                        ui.divemaster->setVisible(true);
    483490                        ui.buddy->setVisible(true);
     
    648655                clearEquipment();
    649656                ui.rating->setCurrentStars(0);
    650                 ui.coordinates->clear();
    651657                ui.visibility->setCurrentStars(0);
     658                ui.location->clear();
    652659        }
    653660        editMode = NONE;
     
    757764                }
    758765                struct dive *cd = current_dive;
    759                 //Reset coordinates field, in case it contains garbage.
    760                 updateGpsCoordinates();
    761766                // now check if something has changed and if yes, edit the selected dives that
    762767                // were identical with the master dive shown (and mark the divelist as changed)
     
    786791                        MODIFY_SELECTED_DIVES(mydive->when -= offset;);
    787792                }
    788                 if (displayed_dive.latitude.udeg != cd->latitude.udeg ||
    789                     displayed_dive.longitude.udeg != cd->longitude.udeg)
    790                         MODIFY_SELECTED_DIVES(
    791                                 if (copyPaste ||
    792                                     (same_string(mydive->location, cd->location) &&
    793                                      mydive->latitude.udeg == cd->latitude.udeg &&
    794                                      mydive->longitude.udeg == cd->longitude.udeg))
    795                                         gpsHasChanged(mydive, cd, ui.coordinates->text(), 0);
    796                         );
    797                 if (!same_string(displayed_dive.location, cd->location))
    798                         MODIFY_SELECTED_DIVES(EDIT_TEXT(location));
    799793
    800794                saveTags();
     
    902896        ui.notes->setPalette(p);
    903897        ui.location->setPalette(p);
    904         ui.coordinates->setPalette(p);
    905898        ui.divemaster->setPalette(p);
    906899        ui.suit->setPalette(p);
     
    11401133                displayedTrip.location = strdup(ui.location->text().toUtf8().data());
    11411134        } else {
    1142                 free(displayed_dive.location);
    1143                 displayed_dive.location = strdup(ui.location->text().toUtf8().data());
     1135                // this means we switched dive sites... this requires a lot more thinking
     1136                //
     1137                //
     1138                //  FIXME
     1139                //
     1140                // TODO
     1141                //
     1142                //
     1143                //
     1144                // free(displayed_dive.location);
     1145                // displayed_dive.location = strdup(ui.location->text().toUtf8().data());
    11441146        }
    11451147        markChangedWidget(ui.location);
     
    11491151void MainTab::on_location_editingFinished()
    11501152{
    1151         // if we have a location and no GPS data, look up the GPS data;
    1152         // but if the GPS data was intentionally cleared then don't
    1153         if (!currentTrip &&
    1154             !same_string(displayed_dive.location, "") &&
    1155             ui.coordinates->text().trimmed().isEmpty() &&
    1156             !(editMode == DIVE && dive_has_gps_location(current_dive))) {
    1157                 struct dive *dive;
    1158                 int i = 0;
    1159                 for_each_dive (i, dive) {
    1160                         if (same_string(displayed_dive.location, dive->location) &&
    1161                             (dive->latitude.udeg || dive->longitude.udeg)) {
    1162                                 displayed_dive.latitude = dive->latitude;
    1163                                 displayed_dive.longitude = dive->longitude;
    1164                                 MainWindow::instance()->globe()->reload();
    1165                                 updateGpsCoordinates();
    1166                                 break;
    1167                         }
    1168                 }
    1169         }
     1153        // find the dive site or create it
     1154        const char *name = ui.location->text().toUtf8().data();
     1155        uint32_t uuid = get_dive_site_uuid_by_name(name, NULL);
     1156        if (!uuid)
     1157                uuid = create_dive_site(name);
     1158        displayed_dive.dive_site_uuid = uuid;
    11701159}
    11711160
     
    12001189}
    12011190
     1191#if 0 // we'll need something like this for the dive site management
    12021192void MainTab::on_coordinates_textChanged(const QString &text)
    12031193{
     
    12161206        }
    12171207}
     1208#endif
    12181209
    12191210void MainTab::on_rating_valueChanged(int value)
     
    12671258}
    12681259
     1260#if 0 // we'll need this for dive sites
    12691261void MainTab::updateCoordinatesText(qreal lat, qreal lon)
    12701262{
     
    12791271                enableEdition();
    12801272
    1281         ui.coordinates->setText(printGPSCoords(displayed_dive.latitude.udeg, displayed_dive.longitude.udeg));
    1282         ui.coordinates->setModified(displayed_dive.latitude.udeg || displayed_dive.longitude.udeg);
    1283 }
     1273        struct dive_site *ds = get_dive_site_by_uuid(displayed_dive.dive_site_uuid);
     1274        if (ds && dive_site_has_gps_location(ds)) {
     1275                ui.coordinates->setText(printGPSCoords(ds->latitude.udeg, ds->longitude.udeg));
     1276                ui.coordinates->setModified(true);
     1277        } else if (!ui.coordinates->text().isEmpty()) {
     1278                ui.coordinates->setModified(true);
     1279                ui.coordinates->clear();
     1280        }
     1281}
     1282#endif
    12841283
    12851284void MainTab::escDetected()
     
    13131312        enableEdition();
    13141313        copyPaste = true;
    1315         SHOW_SELECTIVE(location);
    13161314        SHOW_SELECTIVE(buddy);
    13171315        SHOW_SELECTIVE(divemaster);
     
    13281326        if (what.visibility)
    13291327                ui.visibility->setCurrentStars(displayed_dive.visibility);
    1330         if (what.gps)
    1331                 updateGpsCoordinates();
     1328        if (what.divesite)
     1329                ui.location->setText(get_dive_location(&displayed_dive));
    13321330        if (what.tags) {
    13331331                char buf[1024];
  • qt-ui/maintab.h

    r7d48c1f rf81e2c1  
    1111#include <QDialog>
    1212#include <QMap>
     13#include <QUuid>
    1314
    1415#include "ui_maintab.h"
     
    5657        void addDiveFinished();
    5758        void dateTimeChanged();
    58 
     59        void requestDiveSiteEdit(uint32_t uuid);
    5960public
    6061slots:
     
    6667        void on_location_textChanged(const QString &text);
    6768        void on_location_editingFinished();
    68         void on_coordinates_textChanged(const QString &text);
    6969        void on_divemaster_textChanged();
    7070        void on_buddy_textChanged();
     
    9393        void photoDoubleClicked(const QString filePath);
    9494        void removeSelectedPhotos();
    95         void updateGpsCoordinates();
     95        void prepareDiveSiteEdit();
     96        void showLocation();
    9697
    9798private:
  • qt-ui/maintab.ui

    r81ba72b r2607fea2  
    2323    </property>
    2424    <item row="2" column="1">
    25      <widget class="KMessageWidget" name="diveNotesMessage" native="true"/>
     25     <widget class="KMessageWidget" name="diveNotesMessage" native="true">
     26     </widget>
    2627    </item>
    2728    <item row="3" column="1">
     
    4142         <x>0</x>
    4243         <y>0</y>
    43          <width>443</width>
    44          <height>758</height>
     44         <width>441</width>
     45         <height>753</height>
    4546        </rect>
    4647       </property>
     
    132133          </item>
    133134          <item>
    134            <widget class="QPushButton" name="pushButton">
     135           <widget class="QPushButton" name="manageDiveSite">
    135136            <property name="text">
    136137             <string>manage</string>
    137138            </property>
    138139           </widget>
    139           </item>
    140          </layout>
    141         </item>
    142         <item>
    143          <layout class="QGridLayout" name="gridLayout_2">
    144           <item row="0" column="0">
    145            <widget class="QLabel" name="CoordinatedLabel">
    146             <property name="sizePolicy">
    147              <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
    148               <horstretch>0</horstretch>
    149               <verstretch>0</verstretch>
    150              </sizepolicy>
    151             </property>
    152             <property name="text">
    153              <string>Coordinates</string>
    154             </property>
    155            </widget>
    156           </item>
    157           <item row="0" column="1">
    158            <widget class="QLabel" name="TypeLabel">
    159             <property name="text">
    160              <string>Dive mode</string>
    161             </property>
    162            </widget>
    163           </item>
    164           <item row="1" column="0">
    165            <widget class="QLineEdit" name="coordinates">
    166             <property name="readOnly">
    167              <bool>false</bool>
    168             </property>
    169            </widget>
    170           </item>
    171           <item row="1" column="1">
    172            <widget class="QComboBox" name="DiveType"/>
    173140          </item>
    174141         </layout>
     
    277244        </item>
    278245        <item>
    279          <widget class="QLabel" name="TagLabel">
    280           <property name="text">
    281            <string>Tags</string>
    282           </property>
    283          </widget>
    284         </item>
    285         <item>
    286          <widget class="TagWidget" name="tagWidget">
    287           <property name="sizePolicy">
    288            <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
    289             <horstretch>0</horstretch>
    290             <verstretch>0</verstretch>
    291            </sizepolicy>
    292           </property>
    293           <property name="minimumSize">
    294            <size>
    295             <width>0</width>
    296             <height>0</height>
    297            </size>
    298           </property>
    299           <property name="verticalScrollBarPolicy">
    300            <enum>Qt::ScrollBarAlwaysOff</enum>
    301           </property>
    302           <property name="horizontalScrollBarPolicy">
    303            <enum>Qt::ScrollBarAlwaysOff</enum>
    304           </property>
    305           <property name="lineWrapMode">
    306            <enum>QPlainTextEdit::NoWrap</enum>
    307           </property>
    308          </widget>
     246         <layout class="QGridLayout" name="gridLayout_2">
     247          <item row="1" column="1">
     248           <widget class="QComboBox" name="DiveType"/>
     249          </item>
     250          <item row="0" column="0">
     251           <widget class="QLabel" name="TagLabel">
     252            <property name="text">
     253             <string>Tags</string>
     254            </property>
     255           </widget>
     256          </item>
     257          <item row="0" column="1">
     258           <widget class="QLabel" name="TypeLabel">
     259            <property name="text">
     260             <string>Dive mode</string>
     261            </property>
     262           </widget>
     263          </item>
     264          <item row="1" column="0">
     265           <widget class="TagWidget" name="tagWidget">
     266            <property name="sizePolicy">
     267             <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
     268              <horstretch>0</horstretch>
     269              <verstretch>0</verstretch>
     270             </sizepolicy>
     271            </property>
     272            <property name="minimumSize">
     273             <size>
     274              <width>0</width>
     275              <height>0</height>
     276             </size>
     277            </property>
     278            <property name="verticalScrollBarPolicy">
     279             <enum>Qt::ScrollBarAlwaysOff</enum>
     280            </property>
     281            <property name="horizontalScrollBarPolicy">
     282             <enum>Qt::ScrollBarAlwaysOff</enum>
     283            </property>
     284            <property name="lineWrapMode">
     285             <enum>QPlainTextEdit::NoWrap</enum>
     286            </property>
     287           </widget>
     288          </item>
     289         </layout>
    309290        </item>
    310291        <item>
     
    401382         <x>0</x>
    402383         <y>0</y>
    403          <width>454</width>
    404          <height>752</height>
     384         <width>68</width>
     385         <height>40</height>
    405386        </rect>
    406387       </property>
     
    457438         <x>0</x>
    458439         <y>0</y>
    459          <width>454</width>
    460          <height>752</height>
     440         <width>441</width>
     441         <height>363</height>
    461442        </rect>
    462443       </property>
     
    774755         <x>0</x>
    775756         <y>0</y>
    776          <width>454</width>
    777          <height>752</height>
     757         <width>446</width>
     758         <height>215</height>
    778759        </rect>
    779760       </property>
     
    10371018  <tabstop>visibility</tabstop>
    10381019  <tabstop>suit</tabstop>
    1039   <tabstop>tagWidget</tabstop>
    10401020  <tabstop>notes</tabstop>
    10411021 </tabstops>
  • qt-ui/mainwindow.cpp

    rfd1a33d9 rf81e2c1  
    6868        DivePlannerWidget *plannerWidget = new DivePlannerWidget();
    6969        PlannerDetails *plannerDetails = new PlannerDetails();
     70        LocationInformationWidget *locationInformation = new LocationInformationWidget();
    7071
    7172        registerApplicationState("Default", mainTab, profileWidget, diveListView, globeGps );
     
    7475        registerApplicationState("PlanDive", plannerWidget, profileWidget, plannerSettings, plannerDetails );
    7576        registerApplicationState("EditPlannedDive", plannerWidget, profileWidget, diveListView, globeGps );
     77        registerApplicationState("EditDiveSite",locationInformation, profileWidget, diveListView, globeGps );
     78
    7679        setApplicationState("Default");
    7780
     
    109112        connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled()));
    110113        connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan()));
     114        connect(mainTab, SIGNAL(requestDiveSiteEdit(uint32_t)), this, SLOT(enableDiveSiteEdit(uint32_t)));
     115        connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(setDefaultState()));
     116        connect(locationInformation, SIGNAL(informationManagementEnded()), this, SLOT(refreshDisplay()));
     117        connect(locationInformation, SIGNAL(informationManagementEnded()), information(), SLOT(showLocation()));
     118
    111119#ifdef NO_PRINTING
    112120        ui.printPlan->hide();
     
    129137        ui.menuView->removeAction(ui.actionViewGlobe);
    130138#else
    131         connect(globe(), SIGNAL(coordinatesChanged()), information(), SLOT(updateGpsCoordinates()));
     139        connect(globe(), SIGNAL(coordinatesChanged()), locationInformation, SLOT(updateGpsCoordinates()));
    132140#endif
    133141#ifdef NO_USERMANUAL
     
    206214}
    207215
     216LocationInformationWidget *MainWindow::locationInformationWidget() {
     217        return qobject_cast<LocationInformationWidget*>(applicationState["EditDiveSite"].topLeft);
     218}
     219
     220void MainWindow::enableDiveSiteEdit(uint32_t id) {
     221        setApplicationState("EditDiveSite");
     222}
     223
     224void MainWindow::setDefaultState() {
     225        setApplicationState("Default");
     226}
     227
    208228void MainWindow::setLoadedWithFiles(bool f)
    209229{
     
    256276        graphics()->plotDive();
    257277        information()->updateDiveInfo();
     278        locationInformationWidget()->setLocationId(displayed_dive.dive_site_uuid);
    258279}
    259280
     
    335356        while (dive_table.nr)
    336357                delete_single_dive(0);
     358        while (dive_site_table.nr)
     359                delete_dive_site(get_dive_site(0)->uuid);
    337360
    338361        free((void *)existing_filename);
     
    533556        DivePlannerPointsModel::instance()->clear();
    534557        DivePlannerPointsModel::instance()->setupCylinders();
     558        locationInformationWidget()->setLocationId(0);
    535559}
    536560
  • qt-ui/mainwindow.h

    ref14798 r0e6345f  
    1111#include <QAction>
    1212#include <QUrl>
     13#include <QUuid>
    1314
    1415#include "ui_mainwindow.h"
     
    6970        DivePlannerWidget *divePlannerWidget();
    7071        PlannerSettingsWidget *divePlannerSettingsWidget();
    71 
     72        LocationInformationWidget *locationInformationWidget();
    7273        void showError(QString message);
    7374        void setTitle(enum MainWindowTitleFormat format);
     
    160161        void on_actionFilterTags_triggered();
    161162        void on_actionConfigure_Dive_Computer_triggered();
     163        void enableDiveSiteEdit(uint32_t id);
     164        void setDefaultState();
    162165
    163166protected:
  • qt-ui/models.cpp

    r6b038c2 r8bea7cb  
    11921192                        break;
    11931193                case LOCATION:
    1194                         retVal = QString(dive->location);
     1194                        retVal = QString(get_dive_location(dive));
    11951195                        break;
    11961196                }
     
    12331233                        break;
    12341234                case LOCATION:
    1235                         retVal = QString(dive->location);
     1235                        retVal = QString(get_dive_location(dive));
    12361236                        break;
    12371237                case GAS:
     
    21112111                if (row == 1) {
    21122112                        if (col == 0)
    2113                                 return QString(dive->location);
     2113                                return QString(get_dive_location(dive));
    21142114                        if (col == 3)
    21152115                                return QString(tr("Duration: %1 min")).arg(di.displayDuration());
  • qt-ui/printlayout.cpp

    r194dd8bd r253a137  
    463463        model->setData(model->index(row, 4), dive->divemaster, Qt::DisplayRole);
    464464        model->setData(model->index(row, 5), dive->buddy, Qt::DisplayRole);
    465         model->setData(model->index(row, 6), dive->location, Qt::DisplayRole);
     465        model->setData(model->index(row, 6), get_dive_location(dive), Qt::DisplayRole);
    466466}
    467467
  • qt-ui/simplewidgets.cpp

    r6b038c2 r3ea2e15  
    77#include <QCalendarWidget>
    88#include <QKeyEvent>
     9#include <QAction>
    910
    1011#include "file.h"
     
    457458        ui.setupUi(this);
    458459        what = _what;
    459         UI_FROM_COMPONENT(location);
    460         UI_FROM_COMPONENT(gps);
     460        UI_FROM_COMPONENT(divesite);
    461461        UI_FROM_COMPONENT(divemaster);
    462462        UI_FROM_COMPONENT(buddy);
     
    478478{
    479479        if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
    480                 COMPONENT_FROM_UI(location);
    481                 COMPONENT_FROM_UI(gps);
     480                COMPONENT_FROM_UI(divesite);
    482481                COMPONENT_FROM_UI(divemaster);
    483482                COMPONENT_FROM_UI(buddy);
     
    647646        hide();
    648647}
     648#include <QDebug>
     649#include <QShowEvent>
     650
     651LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent)
     652{
     653        ui.setupUi(this);
     654        ui.diveSiteMessage->setText("You are editing the Dive Site");
     655        ui.diveSiteMessage->setCloseButtonVisible(false);
     656
     657        QAction *action = new QAction(tr("Apply changes"), this);
     658        connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges()));
     659        ui.diveSiteMessage->addAction(action);
     660
     661        action = new QAction(tr("Discard changes"), this);
     662        connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges()));
     663        ui.diveSiteMessage->addAction(action);
     664}
     665
     666void LocationInformationWidget::setLocationId(uint32_t uuid)
     667{
     668        currentDs = get_dive_site_by_uuid(uuid);
     669
     670        if (!currentDs) {
     671                currentDs = get_dive_site_by_uuid(create_dive_site(""));
     672                displayed_dive.dive_site_uuid = currentDs->uuid;
     673                ui.diveSiteName->clear();
     674                ui.diveSiteDescription->clear();
     675                ui.diveSiteNotes->clear();
     676                ui.diveSiteCoordinates->clear();
     677        }
     678        displayed_dive_site = *currentDs;
     679        ui.diveSiteName->setText(displayed_dive_site.name);
     680        ui.diveSiteDescription->setText(displayed_dive_site.description);
     681        ui.diveSiteNotes->setPlainText(displayed_dive_site.notes);
     682        ui.diveSiteCoordinates->setText(printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg));
     683}
     684
     685void LocationInformationWidget::updateGpsCoordinates()
     686{
     687        ui.diveSiteCoordinates->setText(printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg));
     688        MainWindow::instance()->setApplicationState("EditDiveSite");
     689}
     690
     691void LocationInformationWidget::acceptChanges()
     692{
     693        char *uiString;
     694        currentDs->latitude = displayed_dive_site.latitude;
     695        currentDs->longitude = displayed_dive_site.longitude;
     696        uiString = ui.diveSiteName->text().toUtf8().data();
     697        if (!same_string(uiString, currentDs->name)) {
     698                free(currentDs->name);
     699                currentDs->name = copy_string(uiString);
     700        }
     701        uiString = ui.diveSiteDescription->text().toUtf8().data();
     702        if (!same_string(uiString, currentDs->description)) {
     703                free(currentDs->description);
     704                currentDs->description = copy_string(uiString);
     705        }
     706        uiString = ui.diveSiteNotes->document()->toPlainText().toUtf8().data();
     707        if (!same_string(uiString, currentDs->notes)) {
     708                free(currentDs->notes);
     709                currentDs->notes = copy_string(uiString);
     710        }
     711        if (dive_site_is_empty(currentDs)) {
     712                delete_dive_site(currentDs->uuid);
     713                displayed_dive.dive_site_uuid = 0;
     714                setLocationId(0);
     715        } else {
     716                setLocationId(currentDs->uuid);
     717        }
     718        mark_divelist_changed(true);
     719        emit informationManagementEnded();
     720}
     721
     722void LocationInformationWidget::rejectChanges()
     723{
     724        Q_ASSERT(currentDs != NULL);
     725        if (dive_site_is_empty(currentDs)) {
     726                delete_dive_site(currentDs->uuid);
     727                displayed_dive.dive_site_uuid = 0;
     728                setLocationId(0);
     729        } else {
     730                setLocationId(currentDs->uuid);
     731        }
     732        emit informationManagementEnded();
     733}
     734
     735void LocationInformationWidget::showEvent(QShowEvent *ev) {
     736        ui.diveSiteMessage->setCloseButtonVisible(false);
     737}
  • qt-ui/simplewidgets.h

    ree5d93e1 r32ad046  
    77
    88#include <QWidget>
     9#include <QGroupBox>
    910#include <QDialog>
    1011#include <stdint.h>
     
    215216};
    216217
     218#include "ui_locationInformation.h"
     219
     220class LocationInformationWidget : public QGroupBox {
     221Q_OBJECT
     222public:
     223        LocationInformationWidget(QWidget *parent = 0);
     224
     225public slots:
     226        void acceptChanges();
     227        void rejectChanges();
     228
     229        void showEvent(QShowEvent *);
     230
     231        void setLocationId(uint32_t uuid);
     232        void updateGpsCoordinates(void);
     233
     234signals:
     235        void informationManagementEnded();
     236
     237private:
     238        struct dive_site *currentDs;
     239        Ui::LocationInformation ui;
     240};
     241
    217242bool isGnome3Session();
    218243QImage grayImage(const QImage &coloredImg);
  • qt-ui/socialnetworks.cpp

    r62bc751 rb2f0d21d  
    303303        }
    304304        if (ui->Location->isChecked()) {
    305                 fullText += tr("Dive location: %1 \n").arg(d->location);
     305                fullText += tr("Dive location: %1 \n").arg(get_dive_location(d));
    306306        }
    307307        if (ui->Buddy->isChecked()) {
  • qt-ui/subsurfacewebservices.cpp

    r6b038c2 r6708e06  
    3030
    3131struct dive_table gps_location_table;
    32 static bool merge_locations_into_dives(void);
     32
     33// we don't overwrite any existing GPS info in the dive
     34// so get the dive site and if there is none or there is one without GPS fix, add it
     35static void copy_gps_location(struct dive *from, struct dive *to)
     36{
     37        struct dive_site *ds = get_dive_site_for_dive(to);
     38        if (!ds || !dive_site_has_gps_location(ds)) {
     39                struct dive_site *gds = get_dive_site_for_dive(from);
     40                if (!ds) {
     41                        // simply link to the one created for the fake dive
     42                        to->dive_site_uuid = gds->uuid;
     43                } else {
     44                        ds->latitude = gds->latitude;
     45                        ds->longitude = gds->longitude;
     46                        if (same_string(ds->name, ""))
     47                                ds->name = copy_string(gds->name);
     48                }
     49        }
     50}
    3351
    3452#define SAME_GROUP 6 * 3600 // six hours
     
    4361        for_each_dive (i, dive) {
    4462                if (!dive_has_gps_location(dive)) {
    45                         for (j = tracer; (gpsfix = get_gps_location(j, &gps_location_table)) !=NULL; j++) {
     63                        for (j = tracer; (gpsfix = get_dive_from_table(j, &gps_location_table)) !=NULL; j++) {
    4664                                if (dive_within_time_range (dive, gpsfix->when, SAME_GROUP)) {
    4765                                        /*
     
    5068                                         */
    5169                                        if ((dive->when <= gpsfix->when && gpsfix->when <= dive->when + dive->duration.seconds)) {
    52                                                 copy_gps_location(gpsfix,dive);
     70                                                copy_gps_location(gpsfix, dive);
    5371                                                changed++;
    5472                                                tracer = j;
     
    5876                                                 * If it is not, check if there are more position fixes in SAME_GROUP range
    5977                                                 */
    60                                                 if ((nextgpsfix = get_gps_location(j+1,&gps_location_table)) &&
     78                                                if ((nextgpsfix = get_dive_from_table(j+1,&gps_location_table)) &&
    6179                                                    dive_within_time_range (dive, nextgpsfix->when, SAME_GROUP)) {
    6280                                                        /*
     
    6684                                                         */
    6785                                                        if ((dive->when + dive->duration.seconds - gpsfix->when) < (nextgpsfix->when - gpsfix->when)) {
    68                                                                 copy_gps_location(gpsfix,dive);
     86                                                                copy_gps_location(gpsfix, dive);
    6987                                                                tracer = j;
    7088                                                                break;
     
    7492                                                 */
    7593                                                } else {
    76                                                         copy_gps_location(gpsfix,dive);
     94                                                        copy_gps_location(gpsfix, dive);
    7795                                                        changed++;
    7896                                                        tracer = j;
     
    330348        switch (ui.buttonBox->buttonRole(button)) {
    331349        case QDialogButtonBox::ApplyRole: {
     350                int i;
     351                struct dive *d;
     352                struct dive_site *ds;
    332353                clear_table(&gps_location_table);
    333354                QByteArray url = tr("Webservice").toLocal8Bit();
    334355                parse_xml_buffer(url.data(), downloadedData.data(), downloadedData.length(), &gps_location_table, NULL);
    335 
     356                // make sure we mark all the dive sites that were created
     357                for (i = 0; i < gps_location_table.nr; i++) {
     358                        d = get_dive_from_table(i, &gps_location_table);
     359                        ds = get_dive_site_by_uuid(d->dive_site_uuid);
     360                        if (ds)
     361                                ds->notes = strdup("SubsurfaceWebservice");
     362                }
    336363                /* now merge the data in the gps_location table into the dive_table */
    337364                if (merge_locations_into_dives()) {
     
    362389                close();
    363390                resetState();
     391                /* and now clean up and remove all the extra dive sites that were created */
     392                QSet<uint32_t> usedUuids;
     393                for_each_dive(i, d) {
     394                        if (d->dive_site_uuid)
     395                                usedUuids.insert(d->dive_site_uuid);
     396                }
     397                for_each_dive_site(i, ds) {
     398                        if (!usedUuids.contains(ds->uuid) && same_string(ds->notes, "SubsurfaceWebservice"))
     399                                delete_dive_site(ds->uuid);
     400                }
    364401        } break;
    365402        case QDialogButtonBox::RejectRole:
  • qthelper.cpp

    rbd9a443 r4e95bea  
    166166}
    167167
     168#if 0 // we'll need something like this for the dive site management, eventually
    168169bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out)
    169170{
     
    194195        return true;
    195196}
     197#endif
    196198
    197199QList<int> getDivesInTrip(dive_trip_t *trip)
  • save-git.c

    r6607425 r6820b13  
    105105static void save_overview(struct membuffer *b, struct dive *dive)
    106106{
    107         show_gps(b, dive->latitude, dive->longitude);
    108         show_utf8(b, "location ", dive->location, "\n");
    109107        show_utf8(b, "divemaster ", dive->divemaster, "\n");
    110108        show_utf8(b, "buddy ", dive->buddy, "\n");
     
    391389        cond_put_format(dive->tripflag == NO_TRIP, b, "notrip\n");
    392390        save_tags(b, dive->tag_list);
     391        cond_put_format(dive->dive_site_uuid, b, "divesiteid %08x\n", dive->dive_site_uuid);
    393392
    394393        save_overview(b, dive);
     
    805804}
    806805
    807 #define VERSION 2
     806#define VERSION 3
    808807
    809808static void save_settings(git_repository *repo, struct dir *tree)
     
    819818}
    820819
     820static void save_divesites(git_repository *repo, struct dir *tree)
     821{
     822        struct dir *subdir;
     823        struct membuffer dirname = { 0 };
     824        put_format(&dirname, "01-Divesites");
     825        subdir = new_directory(repo, tree, &dirname);
     826
     827        for (int i = 0; i < dive_site_table.nr; i++) {
     828                struct membuffer b = { 0 };
     829                struct dive_site *ds = get_dive_site(i);
     830                if (dive_site_is_empty(ds)) {
     831                        int j;
     832                        struct dive *d;
     833                        for_each_dive(j, d) {
     834                                if (d->dive_site_uuid == ds->uuid)
     835                                        d->dive_site_uuid = 0;
     836                        }
     837                        delete_dive_site(get_dive_site(i)->uuid);
     838                        i--; // since we just deleted that one
     839                        continue;
     840                }
     841                int size = sizeof("Site-012345678");
     842                char name[size];
     843                snprintf(name, size, "Site-%08x", ds->uuid);
     844                show_utf8(&b, "name ", ds->name, "\n");
     845                show_utf8(&b, "description ", ds->description, "\n");
     846                show_utf8(&b, "notes ", ds->notes, "\n");
     847                show_gps(&b, ds->latitude, ds->longitude);
     848                blob_insert(repo, subdir, &b, name);
     849        }
     850}
     851
    821852static int create_git_tree(git_repository *repo, struct dir *root, bool select_only)
    822853{
     
    826857
    827858        save_settings(repo, root);
     859
     860        save_divesites(repo, root);
    828861
    829862        for (trip = dive_trip_list; trip != NULL; trip = trip->next)
     
    939972        if (dive) {
    940973                dive_trip_t *trip = dive->divetrip;
    941                 const char *location = dive->location ? : "no location";
     974                const char *location = get_dive_location(dive) ? : "no location";
    942975                struct divecomputer *dc = &dive->dc;
    943976                const char *sep = "\n";
  • save-html.c

    r7034907 rb7e53aa  
    173173void put_HTML_coordinates(struct membuffer *b, struct dive *dive)
    174174{
    175         degrees_t latitude = dive->latitude;
    176         degrees_t longitude = dive->longitude;
     175        struct dive_site *ds = get_dive_site_for_dive(dive);
     176        if (!ds)
     177                return;
     178        degrees_t latitude = ds->latitude;
     179        degrees_t longitude = ds->longitude;
    177180
    178181        //don't put coordinates if in (0,0)
     
    305308        put_HTML_date(b, dive, "\"date\":\"", "\",");
    306309        put_HTML_time(b, dive, "\"time\":\"", "\",");
    307         write_attribute(b, "location", dive->location, ", ");
     310        write_attribute(b, "location", get_dive_location(dive), ", ");
    308311        put_HTML_coordinates(b, dive);
    309312        put_format(b, "\"rating\":%d,", dive->rating);
  • save-xml.c

    re219bc7 r6820b13  
    111111}
    112112
    113 static void show_location(struct membuffer *b, struct dive *dive)
    114 {
    115         degrees_t latitude = dive->latitude;
    116         degrees_t longitude = dive->longitude;
    117 
    118         /* Should we write a location tag at all? */
    119         if (!(latitude.udeg || longitude.udeg) && !dive->location)
    120                 return;
    121 
    122         put_string(b, "  <location");
    123 
    124         /*
    125          * Ok, theoretically I guess you could dive at
    126          * exactly 0,0. But we don't support that. So
    127          * if you do, just fudge it a bit, and say that
    128          * you dove a few meters away.
    129          */
    130         if (latitude.udeg || longitude.udeg) {
    131                 put_degrees(b, latitude, " gps='", " ");
    132                 put_degrees(b, longitude, "", "'");
    133         }
    134 
    135         /* Do we have a location name or should we write a empty tag? */
    136         if (dive->location && dive->location[0] != '\0')
    137                 show_utf8(b, dive->location, ">", "</location>\n", 0);
    138         else
    139                 put_string(b, "/>\n");
    140 }
    141 
    142113static void save_overview(struct membuffer *b, struct dive *dive)
    143114{
    144         show_location(b, dive);
    145115        show_utf8(b, dive->divemaster, "  <divemaster>", "</divemaster>\n", 0);
    146116        show_utf8(b, dive->buddy, "  <buddy>", "</buddy>\n", 0);
     
    425395                put_format(b, " visibility='%d'", dive->visibility);
    426396        save_tags(b, dive->tag_list);
    427 
     397        if (dive->dive_site_uuid)
     398                put_format(b, " divesiteid='%8x'", dive->dive_site_uuid);
    428399        show_date(b, dive->when);
    429400        put_format(b, " duration='%u:%02u min'>\n",
     
    508479}
    509480
    510 #define VERSION 2
     481#define VERSION 3
    511482
    512483int save_dives(const char *filename)
     
    530501        if (autogroup)
    531502                put_format(b, "  <autogroup state='1' />\n");
    532         put_format(b, "</settings>\n<dives>\n");
    533 
     503        put_format(b, "</settings>\n");
     504
     505        /* save the dive sites */
     506        put_format(b, "<divesites>\n");
     507        for (i = 0; i < dive_site_table.nr; i++) {
     508                struct dive_site *ds = get_dive_site(i);
     509                if (dive_site_is_empty(ds)) {
     510                        int j;
     511                        struct dive *d;
     512                        for_each_dive(j, d) {
     513                                if (d->dive_site_uuid == ds->uuid)
     514                                        d->dive_site_uuid = 0;
     515                        }
     516                        delete_dive_site(get_dive_site(i)->uuid);
     517                        i--; // since we just deleted that one
     518                        continue;
     519                }
     520                put_format(b, "<site uuid='%8x' ", ds->uuid);
     521                show_utf8(b, ds->name, " name='", "'", 1);
     522                if (ds->latitude.udeg || ds->longitude.udeg) {
     523                        put_degrees(b, ds->latitude, " gps='", " ");
     524                        put_degrees(b, ds->longitude, "", "'");
     525                }
     526                show_utf8(b, ds->description, " description='", "'", 1);
     527                show_utf8(b, ds->notes, " notes='", "'", 1);
     528                put_format(b, "/>\n");
     529        }
     530        put_format(b, "</divesites>\n<dives>\n");
    534531        for (trip = dive_trip_list; trip != NULL; trip = trip->next)
    535532                trip->index = 0;
     
    606603                int elen = strlen(extension[i]);
    607604                if (strcasecmp(filename + flen - elen, extension[i]) == 0) {
    608                         save_backup(filename, extension[i], "bak");
     605                        if (last_xml_version < VERSION) {
     606                                int se_len = strlen(extension[i]) + 5;
     607                                char *special_ext = malloc(se_len);
     608                                snprintf(special_ext, se_len, "%s.v%d", extension[i], last_xml_version);
     609                                save_backup(filename, extension[i], special_ext);
     610                                free(special_ext);
     611                        } else {
     612                                save_backup(filename, extension[i], "bak");
     613                        }
    609614                        break;
    610615                }
  • subsurface.pro

    r6d996a7 rdcfda29  
    3030        dive.h \
    3131        divelist.h \
     32        divesite.h \
    3233        file.h \
    3334        gettextfromc.h \
     
    120121        dive.c \
    121122        divelist.c \
     123        divesite.c \
    122124        equipment.c \
    123125        file.c \
     
    239241        qt-ui/diveshareexportdialog.ui \
    240242        qt-ui/filterwidget.ui \
    241         qt-ui/plannerDetails.ui
     243        qt-ui/plannerDetails.ui \
     244        qt-ui/locationInformation.ui
    242245
    243246# Nether usermanual or printing is supported on android right now
  • uemis-downloader.c

    r5e7be30 rd032c2a5  
    639639}
    640640
    641 static void track_divespot(char *val, int diveid, char **location, degrees_t *latitude, degrees_t *longitude)
     641static void track_divespot(char *val, int diveid, uint32_t dive_site_uuid)
    642642{
    643643        int id = atoi(val);
    644644        if (id >= 0 && id > nr_divespots)
    645645                nr_divespots = id;
    646         uemis_mark_divelocation(diveid, id, location, latitude, longitude);
     646        uemis_mark_divelocation(diveid, id, dive_site_uuid);
    647647        return;
    648648}
     
    784784                                *for_dive = atoi(val);
    785785                } else if (!log && dive && !strcmp(tag, "divespot_id")) {
    786                         track_divespot(val, dive->dc.diveid, &dive->location, &dive->latitude, &dive->longitude);
     786                        dive->dive_site_uuid = create_dive_site("from Uemis");
     787                        track_divespot(val, dive->dc.diveid, dive->dive_site_uuid);
    787788                } else if (dive) {
    788789                        parse_tag(dive, tag, val);
  • uemis.c

    r93d59c2 rd032c2a5  
    104104        int lbs;
    105105        int divespot;
    106         char **location;
    107         degrees_t *latitude;
    108         degrees_t *longitude;
     106        int dive_site_uuid;
    109107        struct uemis_helper *next;
    110108};
     
    151149}
    152150
    153 void uemis_mark_divelocation(int diveid, int divespot, char **location, degrees_t *latitude, degrees_t *longitude)
     151void uemis_mark_divelocation(int diveid, int divespot, uint32_t dive_site_uuid)
    154152{
    155153        struct uemis_helper *hp = uemis_get_helper(diveid);
    156154        hp->divespot = divespot;
    157         hp->location = location;
    158         hp->longitude = longitude;
    159         hp->latitude = latitude;
     155        hp->dive_site_uuid = dive_site_uuid;
    160156}
    161157
     
    163159{
    164160        struct uemis_helper *hp = uemis_helper;
    165 #if 0 /* seems overkill */
    166         if (!g_utf8_validate(text, -1, NULL))
    167                 return;
    168 #endif
    169161        while (hp) {
    170                 if (hp->divespot == divespot && hp->location) {
    171                         *hp->location = strdup(text);
    172                         hp->longitude->udeg = round(longitude * 1000000);
    173                         hp->latitude->udeg = round(latitude * 1000000);
     162                if (hp->divespot == divespot) {
     163                        struct dive_site *ds = get_dive_site_by_uuid(hp->dive_site_uuid);
     164                        ds->name = strdup(text);
     165                        ds->longitude.udeg = round(longitude * 1000000);
     166                        ds->latitude.udeg = round(latitude * 1000000);
    174167                }
    175168                hp = hp->next;
  • uemis.h

    reef3d63 rd032c2a5  
    1515void uemis_parse_divelog_binary(char *base64, void *divep);
    1616int uemis_get_weight_unit(int diveid);
    17 void uemis_mark_divelocation(int diveid, int divespot, char **location, degrees_t *latitude, degrees_t *longitude);
     17void uemis_mark_divelocation(int diveid, int divespot, uint32_t dive_site_uuid);
    1818void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude);
    1919
  • worldmap-save.c

    r7034907 rb7e53aa  
    2828                                continue;
    2929                }
    30                 if (dive->latitude.udeg == 0 && dive->longitude.udeg == 0)
     30                struct dive_site *ds = get_dive_site_for_dive(dive);
     31                if (!ds || !dive_site_has_gps_location(ds))
    3132                        continue;
    32 
    33                 put_degrees(b, dive->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", "");
    34                 put_degrees(b, dive->longitude, ",", ")});\n");
     33                put_degrees(b, ds->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", "");
     34                put_degrees(b, ds->longitude, ",", ")});\n");
    3535                put_string(b, "markers.push(temp);\ntempinfowindow = new google.maps.InfoWindow({content: '<div id=\"content\">'+'<div id=\"siteNotice\">'+'</div>'+'<div id=\"bodyContent\">");
    3636                snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Date:"));
     
    5050                snprintf(pre, sizeof(pre), "<p>%s <b>", translate("gettextFromC", "Location:"));
    5151                put_string(b, pre);
    52                 put_HTML_quoted(b, dive->location);
     52                put_HTML_quoted(b, get_dive_location(dive));
    5353                put_string(b, "</b></p>");
    5454                snprintf(pre, sizeof(pre), "<p> %s ", translate("gettextFromC", "Notes:"));
Note: See TracChangeset for help on using the changeset viewer.