diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/dive.h | 8 | ||||
-rw-r--r-- | core/divelist.c | 65 | ||||
-rw-r--r-- | core/divelist.h | 8 | ||||
-rw-r--r-- | core/divesite.c | 67 | ||||
-rw-r--r-- | core/divesite.h | 9 | ||||
-rw-r--r-- | core/downloadfromdcthread.cpp | 5 | ||||
-rw-r--r-- | core/downloadfromdcthread.h | 2 |
7 files changed, 134 insertions, 30 deletions
diff --git a/core/dive.h b/core/dive.h index d40e53043..03d6fc2df 100644 --- a/core/dive.h +++ b/core/dive.h @@ -758,15 +758,17 @@ extern void average_max_depth(struct diveplan *dive, int *avg_depth, int *max_de #ifdef __cplusplus } -/* Make pointers to dive, dive_trip and dive_table "Qt metatypes" so that they can - * be passed through QVariants and through QML. +/* Make pointers to dive, dive_trip, dive_table, trip_table and dive_site_table + * "Qt metatypes" so that they can be passed through QVariants and through QML. * Note: we have to use the typedef "dive_table_t" instead of "struct dive_table", * because MOC removes the "struct", but dive_table is already the name of a global - * variable, leading to compilation errors. Likewise for "struct trip_table". */ + * variable, leading to compilation errors. Likewise for "struct trip_table" and + * "struct dive_site_table". */ Q_DECLARE_METATYPE(struct dive *); Q_DECLARE_METATYPE(struct dive_trip *); Q_DECLARE_METATYPE(dive_table_t *); Q_DECLARE_METATYPE(trip_table_t *); +Q_DECLARE_METATYPE(dive_site_table_t *); #endif diff --git a/core/divelist.c b/core/divelist.c index 8e1ba1628..09f08acd0 100644 --- a/core/divelist.c +++ b/core/divelist.c @@ -1518,17 +1518,18 @@ static bool merge_dive_tables(struct dive_table *dives_from, struct dive_table * /* Merge the dives of the trip "from" and the dive_table "dives_from" into the trip "to" * and dive_table "dives_to". If "prefer_imported" is true, dive data of "from" takes * precedence */ -void add_imported_dives(struct dive_table *import_table, struct trip_table *import_trip_table, int flags) +void add_imported_dives(struct dive_table *import_table, struct trip_table *import_trip_table, struct dive_site_table *import_sites_table, int flags) { int i, idx; struct dive_table dives_to_add = { 0 }; struct dive_table dives_to_remove = { 0 }; struct trip_table trips_to_add = { 0 }; + struct dive_site_table dive_sites_to_add = { 0 }; /* Process imported dives and generate lists of dives * to-be-added and to-be-removed */ - process_imported_dives(import_table, import_trip_table, flags, - &dives_to_add, &dives_to_remove, &trips_to_add); + process_imported_dives(import_table, import_trip_table, import_sites_table, flags, + &dives_to_add, &dives_to_remove, &trips_to_add, &dive_sites_to_add); /* Add new dives to trip, so that trips don't get deleted * on deletion of old dives */ @@ -1560,6 +1561,11 @@ void add_imported_dives(struct dive_table *import_table, struct trip_table *impo insert_trip(trips_to_add.trips[i], &trip_table); trips_to_add.nr = 0; + /* Add new dive sites */ + for (i = 0; i < dive_sites_to_add.nr; i++) + register_dive_site(dive_sites_to_add.dive_sites[i]); + dive_sites_to_add.nr = 0; + /* We might have deleted the old selected dive. * Choose the newest dive as selected (if any) */ current_dive = dive_table.nr > 0 ? dive_table.dives[dive_table.nr - 1] : NULL; @@ -1600,21 +1606,23 @@ bool try_to_merge_trip(struct dive_trip *trip_import, struct dive_table *import_ } /* Process imported dives: take a table of dives to be imported and - * generate three lists: + * generate four lists: * 1) Dives to be added * 2) Dives to be removed * 3) Trips to be added + * 4) Dive sites to be added * The dives to be added are owning (i.e. the caller is responsible * for freeing them). - * The dives and trips in "import_table" and "import_trip_table" are - * consumed. On return, both tables have size 0. - * "import_trip_table" may be NULL if all dives are not associated + * The dives, trips and sites in "import_table", "import_trip_table" + * and "import_sites_table" are consumed. On return, the tables have + * size 0. "import_trip_table" may be NULL if all dives are not associated * with a trip. - * The output parameters should be empty - if not, their content + * The output tables should be empty - if not, their content * will be cleared! * - * Note: The new dives will have their divetrip-field set, but will - * *not* be part of the trip. The caller has to add them to the trip. + * Note: The new dives will have their divetrip- and divesites-fields + * set, but will *not* be part of the trip and site. The caller has to + * add them to the trip and site. * * The lists are generated by merging dives if possible. This is * performed trip-wise. Finer control on merging is provided by @@ -1629,10 +1637,11 @@ bool try_to_merge_trip(struct dive_trip *trip_import, struct dive_table *import_ * - If IMPORT_ADD_TO_NEW_TRIP is true, dives that are not assigned * to a trip will be added to a newly generated trip. */ -void process_imported_dives(struct dive_table *import_table, struct trip_table *import_trip_table, int flags, +void process_imported_dives(struct dive_table *import_table, struct trip_table *import_trip_table, + struct dive_site_table *import_sites_table, int flags, /* output parameters: */ struct dive_table *dives_to_add, struct dive_table *dives_to_remove, - struct trip_table *trips_to_add) + struct trip_table *trips_to_add, struct dive_site_table *sites_to_add) { int i, j, nr, start_renumbering_at = 0; struct dive_trip *trip_import, *new_trip; @@ -1651,6 +1660,7 @@ void process_imported_dives(struct dive_table *import_table, struct trip_table * clear_table(dives_to_add); clear_table(dives_to_remove); clear_trip_table(trips_to_add); + clear_dive_site_table(sites_to_add); /* Check if any of the new dives has a number. This will be * important later to decide if we want to renumber the added @@ -1687,6 +1697,37 @@ void process_imported_dives(struct dive_table *import_table, struct trip_table * preexisting = dive_table.nr; /* Remember old size for renumbering */ + /* If dive sites already exist, use the existing versions. */ + for (i = 0; i < import_sites_table->nr; i++) { + struct dive_site *new_ds = import_sites_table->dive_sites[i]; + struct dive_site *old_ds = get_same_dive_site(new_ds); + + /* Check if it dive site is actually used by new dives. */ + for (j = 0; j < import_table->nr; j++) { + if (import_table->dives[j]->dive_site == new_ds) + break; + } + + if (j == import_table->nr) { + /* Dive site not even used - free it and go to next. */ + free_dive_site(new_ds); + continue; + } + + if (!old_ds) { + /* Dive site doesn't exist. Add it to list of dive sites to be added. */ + add_dive_site_to_table(new_ds, sites_to_add); + continue; + } + /* Dive site already exists - use the old and free the new. */ + for (j = 0; j < import_table->nr; j++) { + if (import_table->dives[j]->dive_site == new_ds) + import_table->dives[j]->dive_site = old_ds; + } + free_dive_site(new_ds); + } + import_sites_table->nr = 0; /* All dive sites were consumed */ + /* Merge overlapping trips. Since both trip tables are sorted, we * could be smarter here, but realistically not a whole lot of trips * will be imported so do a simple n*m loop until someone complains. diff --git a/core/divelist.h b/core/divelist.h index e1ff706f7..1880856df 100644 --- a/core/divelist.h +++ b/core/divelist.h @@ -23,10 +23,12 @@ extern void process_loaded_dives(); #define IMPORT_IS_DOWNLOADED (1 << 1) #define IMPORT_MERGE_ALL_TRIPS (1 << 2) #define IMPORT_ADD_TO_NEW_TRIP (1 << 3) -extern void add_imported_dives(struct dive_table *import_table, struct trip_table *import_trip_table, int flags); -extern void process_imported_dives(struct dive_table *import_table, struct trip_table *import_trip_table, int flags, +extern void add_imported_dives(struct dive_table *import_table, struct trip_table *import_trip_table, struct dive_site_table *import_sites_table, + int flags); +extern void process_imported_dives(struct dive_table *import_table, struct trip_table *import_trip_table, struct dive_site_table *import_sites_table, + int flags, struct dive_table *dives_to_add, struct dive_table *dives_to_remove, - struct trip_table *trips_to_add); + struct trip_table *trips_to_add, struct dive_site_table *sites_to_add); extern char *get_dive_gas_string(const struct dive *dive); extern struct dive **grow_dive_table(struct dive_table *table); diff --git a/core/divesite.c b/core/divesite.c index 9baabd872..bf99ed395 100644 --- a/core/divesite.c +++ b/core/divesite.c @@ -117,14 +117,13 @@ static uint32_t dive_site_getUniqId(struct dive_site_table *ds_table) return id; } -/* we never allow a second dive site with the same uuid */ -struct dive_site *alloc_or_get_dive_site(uint32_t uuid, struct dive_site_table *ds_table) +void register_dive_site(struct dive_site *ds) { - struct dive_site *ds; - - if (uuid && (ds = get_dive_site_by_uuid(uuid, ds_table)) != NULL) - return ds; + add_dive_site_to_table(ds, &dive_site_table); +} +void add_dive_site_to_table(struct dive_site *ds, struct dive_site_table *ds_table) +{ int nr = ds_table->nr; int allocated = ds_table->allocated; struct dive_site **sites = ds_table->dive_sites; @@ -137,11 +136,23 @@ struct dive_site *alloc_or_get_dive_site(uint32_t uuid, struct dive_site_table * ds_table->dive_sites = sites; ds_table->allocated = allocated; } + sites[nr] = ds; + ds_table->nr = nr + 1; +} + +/* we never allow a second dive site with the same uuid */ +struct dive_site *alloc_or_get_dive_site(uint32_t uuid, struct dive_site_table *ds_table) +{ + struct dive_site *ds; + + if (uuid && (ds = get_dive_site_by_uuid(uuid, ds_table)) != NULL) + return ds; + ds = calloc(1, sizeof(*ds)); if (!ds) exit(1); - sites[nr] = ds; - ds_table->nr = nr + 1; + add_dive_site_to_table(ds, ds_table); + // we should always be called with a valid uuid except in the special // case where we want to copy a dive site into the memory we allocated // here - then we need to pass in 0 and create a temporary uuid here @@ -195,12 +206,16 @@ void free_dive_site(struct dive_site *ds) } } -void delete_dive_site(struct dive_site *ds, struct dive_site_table *ds_table) +void unregister_dive_site(struct dive_site *ds) +{ + remove_dive_site_from_table(ds, &dive_site_table); +} + +void remove_dive_site_from_table(struct dive_site *ds, struct dive_site_table *ds_table) { int nr = ds_table->nr; for (int i = 0; i < nr; i++) { if (ds == get_dive_site(i, ds_table)) { - free_dive_site(ds); if (nr - 1 > i) memmove(&ds_table->dive_sites[i], &ds_table->dive_sites[i+1], @@ -211,6 +226,14 @@ void delete_dive_site(struct dive_site *ds, struct dive_site_table *ds_table) } } +void delete_dive_site(struct dive_site *ds, struct dive_site_table *ds_table) +{ + if (!ds) + return; + remove_dive_site_from_table(ds, ds_table); + free_dive_site(ds); +} + static uint32_t create_divesite_uuid(const char *name, timestamp_t divetime) { if (name == NULL) @@ -291,6 +314,30 @@ static void merge_string(char **a, char **b) free(s1); } +/* Used to check on import if two dive sites are equivalent. + * Since currently no merging is performed, be very conservative + * and only consider equal dive sites that are exactly the same. + * Taxonomy is not compared, as no taxonomy is generated on + * import. + */ +static bool same_dive_site(const struct dive_site *a, const struct dive_site *b) +{ + return same_string(a->name, b->name) + && same_location(&a->location, &b->location) + && same_string(a->description, b->description) + && same_string(a->notes, b->notes); +} + +struct dive_site *get_same_dive_site(const struct dive_site *site) +{ + int i; + struct dive_site *ds; + for_each_dive_site (i, ds, &dive_site_table) + if (same_dive_site(ds, site)) + return ds; + return NULL; +} + void merge_dive_site(struct dive_site *a, struct dive_site *b) { if (!has_location(&a->location)) a->location = b->location; diff --git a/core/divesite.h b/core/divesite.h index ba4cd32a5..1f841a7d2 100644 --- a/core/divesite.h +++ b/core/divesite.h @@ -24,10 +24,10 @@ struct dive_site struct taxonomy_data taxonomy; }; -struct dive_site_table { +typedef struct dive_site_table { int nr, allocated; struct dive_site **dive_sites; -}; +} dive_site_table_t; extern struct dive_site_table dive_site_table; @@ -45,6 +45,10 @@ static inline struct dive_site *get_dive_site(int nr, struct dive_site_table *ds int get_divesite_idx(const struct dive_site *ds, struct dive_site_table *ds_table); struct dive_site *get_dive_site_by_uuid(uint32_t uuid, struct dive_site_table *ds_table); void dive_site_table_sort(struct dive_site_table *ds_table); +void add_dive_site_to_table(struct dive_site *ds, struct dive_site_table *ds_table); +void remove_dive_site_from_table(struct dive_site *ds, struct dive_site_table *ds_table); +void register_dive_site(struct dive_site *ds); +void unregister_dive_site(struct dive_site *ds); struct dive_site *alloc_or_get_dive_site(uint32_t uuid, struct dive_site_table *ds_table); int nr_of_dives_at_dive_site(struct dive_site *ds, bool select_only); bool is_dive_site_used(struct dive_site *ds, bool select_only); @@ -56,6 +60,7 @@ struct dive_site *get_dive_site_by_name(const char *name, struct dive_site_table struct dive_site *get_dive_site_by_gps(const location_t *, struct dive_site_table *ds_table); struct dive_site *get_dive_site_by_gps_and_name(char *name, const location_t *, struct dive_site_table *ds_table); struct dive_site *get_dive_site_by_gps_proximity(const location_t *, int distance, struct dive_site_table *ds_table); +struct dive_site *get_same_dive_site(const struct dive_site *); bool dive_site_is_empty(struct dive_site *ds); void copy_dive_site_taxonomy(struct dive_site *orig, struct dive_site *copy); void copy_dive_site(struct dive_site *orig, struct dive_site *copy); diff --git a/core/downloadfromdcthread.cpp b/core/downloadfromdcthread.cpp index 5b336dee5..f2a65ac5f 100644 --- a/core/downloadfromdcthread.cpp +++ b/core/downloadfromdcthread.cpp @@ -306,6 +306,11 @@ struct dive_table *DownloadThread::table() return &downloadTable; } +struct dive_site_table *DownloadThread::sites() +{ + return &diveSiteTable; +} + QString DCDeviceData::vendor() const { return data.vendor; diff --git a/core/downloadfromdcthread.h b/core/downloadfromdcthread.h index e4cfb2351..d14a5402b 100644 --- a/core/downloadfromdcthread.h +++ b/core/downloadfromdcthread.h @@ -59,6 +59,7 @@ private: class DownloadThread : public QThread { Q_OBJECT Q_PROPERTY(dive_table_t *table READ table CONSTANT) + Q_PROPERTY(dive_site_table_t *sites READ sites CONSTANT) public: DownloadThread(); @@ -66,6 +67,7 @@ public: DCDeviceData *data(); struct dive_table *table(); + struct dive_site_table *sites(); QString error; private: |