From 6200909ba4ffba2d79770b7eacdb615eeb2c88c1 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Thu, 30 May 2019 18:29:36 +0200 Subject: [PATCH] Cleanup: move tag functions into own translation unit Make dive.h a bit slimmer. It's only a drop in the bucket - but at least when modifying tag functions not the *whole* application is rebuilt anymore. Signed-off-by: Berthold Stoeger --- core/CMakeLists.txt | 2 + core/datatrak.c | 1 + core/dive.c | 223 +----------------------- core/dive.h | 46 ----- core/import-suunto.c | 1 + core/load-git.c | 1 + core/parse-xml.c | 1 + core/qthelper.cpp | 1 + core/save-git.c | 1 + core/save-html.c | 1 + core/save-xml.c | 1 + core/structured_list.h | 30 ++++ core/tag.c | 206 ++++++++++++++++++++++ core/tag.h | 62 +++++++ core/uemis-downloader.c | 1 + desktop-widgets/command_edit.cpp | 1 + desktop-widgets/divelogexportdialog.cpp | 1 + desktop-widgets/simplewidgets.cpp | 1 + packaging/ios/Subsurface-mobile.pro | 1 + qt-models/completionmodels.cpp | 1 + qt-models/divetripmodel.cpp | 1 + smtk-import/smartrak.c | 1 + subsurface-desktop-main.cpp | 1 + subsurface-mobile-main.cpp | 1 + tests/testtaglist.cpp | 1 + 25 files changed, 321 insertions(+), 267 deletions(-) create mode 100644 core/structured_list.h create mode 100644 core/tag.c create mode 100644 core/tag.h diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 17a2bd0c7..9d3f3e493 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -144,6 +144,8 @@ set(SUBSURFACE_CORE_LIB_SRCS subsurfacestartup.h subsurfacesysinfo.cpp subsurfacesysinfo.h + tag.c + tag.h taxonomy.c taxonomy.h time.c diff --git a/core/datatrak.c b/core/datatrak.c index 5e806f08f..43c7346cd 100644 --- a/core/datatrak.c +++ b/core/datatrak.c @@ -17,6 +17,7 @@ #include "file.h" #include "divesite.h" #include "ssrf.h" +#include "tag.h" static unsigned int two_bytes_to_int(unsigned char x, unsigned char y) { diff --git a/core/dive.c b/core/dive.c index 907ad40e7..5191402a5 100644 --- a/core/dive.c +++ b/core/dive.c @@ -14,24 +14,14 @@ #include "qthelper.h" #include "metadata.h" #include "membuffer.h" +#include "tag.h" +#include "structured_list.h" /* one could argue about the best place to have this variable - * it's used in the UI, but it seems to make the most sense to have it * here */ struct dive displayed_dive; -struct tag_entry *g_tag_list = NULL; - -static const char *default_tags[] = { - QT_TRANSLATE_NOOP("gettextFromC", "boat"), QT_TRANSLATE_NOOP("gettextFromC", "shore"), QT_TRANSLATE_NOOP("gettextFromC", "drift"), - QT_TRANSLATE_NOOP("gettextFromC", "deep"), QT_TRANSLATE_NOOP("gettextFromC", "cavern"), QT_TRANSLATE_NOOP("gettextFromC", "ice"), - QT_TRANSLATE_NOOP("gettextFromC", "wreck"), QT_TRANSLATE_NOOP("gettextFromC", "cave"), QT_TRANSLATE_NOOP("gettextFromC", "altitude"), - QT_TRANSLATE_NOOP("gettextFromC", "pool"), QT_TRANSLATE_NOOP("gettextFromC", "lake"), QT_TRANSLATE_NOOP("gettextFromC", "river"), - QT_TRANSLATE_NOOP("gettextFromC", "night"), QT_TRANSLATE_NOOP("gettextFromC", "fresh"), QT_TRANSLATE_NOOP("gettextFromC", "student"), - QT_TRANSLATE_NOOP("gettextFromC", "instructor"), QT_TRANSLATE_NOOP("gettextFromC", "photo"), QT_TRANSLATE_NOOP("gettextFromC", "video"), - QT_TRANSLATE_NOOP("gettextFromC", "deco") -}; - const char *cylinderuse_text[] = { QT_TRANSLATE_NOOP("gettextFromC", "OC-gas"), QT_TRANSLATE_NOOP("gettextFromC", "diluent"), QT_TRANSLATE_NOOP("gettextFromC", "oxygen"), QT_TRANSLATE_NOOP("gettextFromC", "not used") }; @@ -474,31 +464,6 @@ struct dive *alloc_dive(void) return dive; } -/* Clear everything but the first element; - * this works for taglist, picturelist, even dive computers */ -#define STRUCTURED_LIST_FREE(_type, _start, _free) \ - { \ - _type *_ptr = _start; \ - while (_ptr) { \ - _type *_next = _ptr->next; \ - _free(_ptr); \ - _ptr = _next; \ - } \ - } - -#define STRUCTURED_LIST_COPY(_type, _first, _dest, _cpy) \ - { \ - _type *_sptr = _first; \ - _type **_dptr = &_dest; \ - while (_sptr) { \ - *_dptr = malloc(sizeof(_type)); \ - _cpy(_sptr, *_dptr); \ - _sptr = _sptr->next; \ - _dptr = &(*_dptr)->next; \ - } \ - *_dptr = 0; \ - } - static void free_dc(struct divecomputer *dc); static void free_dc_contents(struct divecomputer *dc); @@ -548,14 +513,6 @@ static void copy_pl(struct picture *sp, struct picture *dp) dp->filename = copy_string(sp->filename); } -/* copy an element in a list of tags */ -static void copy_tl(struct tag_entry *st, struct tag_entry *dt) -{ - dt->tag = malloc(sizeof(struct divetag)); - dt->tag->name = copy_string(st->tag->name); - dt->tag->source = copy_string(st->tag->source); -} - static void free_dive_structures(struct dive *d) { if (!d) @@ -3253,182 +3210,6 @@ static void join_dive_computers(struct dive *d, struct divecomputer *res, remove_redundant_dc(res, prefer_downloaded); } -static bool tag_seen_before(struct tag_entry *start, struct tag_entry *before) -{ - while (start && start != before) { - if (same_string(start->tag->name, before->tag->name)) - return true; - start = start->next; - } - return false; -} - -/* remove duplicates and empty nodes */ -void taglist_cleanup(struct tag_entry **tag_list) -{ - struct tag_entry **tl = tag_list; - while (*tl) { - /* skip tags that are empty or that we have seen before */ - if (empty_string((*tl)->tag->name) || tag_seen_before(*tag_list, *tl)) { - *tl = (*tl)->next; - continue; - } - tl = &(*tl)->next; - } -} - -char *taglist_get_tagstring(struct tag_entry *tag_list) -{ - bool first_tag = true; - struct membuffer b = { 0 }; - struct tag_entry *tmp = tag_list; - while (tmp != NULL) { - if (!empty_string(tmp->tag->name)) { - if (first_tag) { - put_format(&b, "%s", tmp->tag->name); - first_tag = false; - } else { - put_format(&b, ", %s", tmp->tag->name); - } - } - tmp = tmp->next; - } - /* Ensures we do return null terminated empty string for: - * - empty tag list - * - tag list with empty tag only - */ - mb_cstring(&b); - return detach_buffer(&b); -} - -static inline void taglist_free_divetag(struct divetag *tag) -{ - if (tag->name != NULL) - free(tag->name); - if (tag->source != NULL) - free(tag->source); - free(tag); -} - -/* Add a tag to the tag_list, keep the list sorted */ -static struct divetag *taglist_add_divetag(struct tag_entry **tag_list, struct divetag *tag) -{ - struct tag_entry *next, *entry; - - while ((next = *tag_list) != NULL) { - int cmp = strcmp(next->tag->name, tag->name); - - /* Already have it? */ - if (!cmp) - return next->tag; - /* Is the entry larger? If so, insert here */ - if (cmp > 0) - break; - /* Continue traversing the list */ - tag_list = &next->next; - } - - /* Insert in front of it */ - entry = malloc(sizeof(struct tag_entry)); - entry->next = next; - entry->tag = tag; - *tag_list = entry; - return tag; -} - -struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag) -{ - size_t i = 0; - int is_default_tag = 0; - struct divetag *ret_tag, *new_tag; - const char *translation; - new_tag = malloc(sizeof(struct divetag)); - - for (i = 0; i < sizeof(default_tags) / sizeof(char *); i++) { - if (strcmp(default_tags[i], tag) == 0) { - is_default_tag = 1; - break; - } - } - /* Only translate default tags */ - if (is_default_tag) { - translation = translate("gettextFromC", tag); - new_tag->name = malloc(strlen(translation) + 1); - memcpy(new_tag->name, translation, strlen(translation) + 1); - new_tag->source = malloc(strlen(tag) + 1); - memcpy(new_tag->source, tag, strlen(tag) + 1); - } else { - new_tag->source = NULL; - new_tag->name = malloc(strlen(tag) + 1); - memcpy(new_tag->name, tag, strlen(tag) + 1); - } - /* Try to insert new_tag into g_tag_list if we are not operating on it */ - if (tag_list != &g_tag_list) { - ret_tag = taglist_add_divetag(&g_tag_list, new_tag); - /* g_tag_list already contains new_tag, free the duplicate */ - if (ret_tag != new_tag) - taglist_free_divetag(new_tag); - ret_tag = taglist_add_divetag(tag_list, ret_tag); - } else { - ret_tag = taglist_add_divetag(tag_list, new_tag); - if (ret_tag != new_tag) - taglist_free_divetag(new_tag); - } - return ret_tag; -} - -void taglist_free(struct tag_entry *entry) -{ - STRUCTURED_LIST_FREE(struct tag_entry, entry, free) -} - -struct tag_entry *taglist_copy(struct tag_entry *s) -{ - struct tag_entry *res; - STRUCTURED_LIST_COPY(struct tag_entry, s, res, copy_tl); - return res; -} - -/* Merge src1 and src2, write to *dst */ -static void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_entry *src2) -{ - struct tag_entry *entry; - - for (entry = src1; entry; entry = entry->next) - taglist_add_divetag(dst, entry->tag); - for (entry = src2; entry; entry = entry->next) - taglist_add_divetag(dst, entry->tag); -} - -void taglist_init_global() -{ - size_t i; - - for (i = 0; i < sizeof(default_tags) / sizeof(char *); i++) - taglist_add_tag(&g_tag_list, default_tags[i]); -} - -bool taglist_contains(struct tag_entry *tag_list, const char *tag) -{ - while (tag_list) { - if (same_string(tag_list->tag->name, tag)) - return true; - tag_list = tag_list->next; - } - return false; -} - -struct tag_entry *taglist_added(struct tag_entry *original_list, struct tag_entry *new_list) -{ - struct tag_entry *added_list = NULL; - while (new_list) { - if (!taglist_contains(original_list, new_list->tag->name)) - taglist_add_tag(&added_list, new_list->tag->name); - new_list = new_list->next; - } - return added_list; -} - bool is_dc_planner(const struct divecomputer *dc) { return same_string(dc->model, "planned dive"); diff --git a/core/dive.h b/core/dive.h index c115f5c0f..a68336494 100644 --- a/core/dive.h +++ b/core/dive.h @@ -177,52 +177,6 @@ struct sample // BASE TYPE BYTES UNITS RANGE // not calculated when planning a dive }; // Total size of structure: 57 bytes, excluding padding at end -struct divetag { - /* - * The name of the divetag. If a translation is available, name contains - * the translated tag - */ - char *name; - /* - * If a translation is available, we write the original tag to source. - * This enables us to write a non-localized tag to the xml file. - */ - char *source; -}; - -struct tag_entry { - struct divetag *tag; - struct tag_entry *next; -}; - -/* - * divetags are only stored once, each dive only contains - * a list of tag_entries which then point to the divetags - * in the global g_tag_list - */ - -extern struct tag_entry *g_tag_list; - -struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag); -struct tag_entry *taglist_added(struct tag_entry *original_list, struct tag_entry *new_list); - -/* - * Writes all divetags form tag_list into internally allocated buffer - * Function returns pointer to allocated buffer - * Buffer contains comma separated list of tags names or null terminated string - * - * NOTE! The returned buffer must be freed once used. - */ -char *taglist_get_tagstring(struct tag_entry *tag_list); - -/* cleans up a list: removes empty tags and duplicates */ -void taglist_cleanup(struct tag_entry **tag_list); - -void taglist_init_global(); -void taglist_free(struct tag_entry *tag_list); -struct tag_entry *taglist_copy(struct tag_entry *s); -bool taglist_contains(struct tag_entry *tag_list, const char *tag); - struct extra_data { const char *key; const char *value; diff --git a/core/import-suunto.c b/core/import-suunto.c index 078593700..060ed113b 100644 --- a/core/import-suunto.c +++ b/core/import-suunto.c @@ -12,6 +12,7 @@ #include "device.h" #include "membuffer.h" #include "gettext.h" +#include "tag.h" static int dm4_events(void *param, int columns, char **data, char **column) { diff --git a/core/load-git.c b/core/load-git.c index a0baedecd..91d8f8cd1 100644 --- a/core/load-git.c +++ b/core/load-git.c @@ -22,6 +22,7 @@ #include "membuffer.h" #include "git-access.h" #include "qthelper.h" +#include "tag.h" const char *saved_git_id = NULL; diff --git a/core/parse-xml.c b/core/parse-xml.c index 43d0049a7..f4a7d60a9 100644 --- a/core/parse-xml.c +++ b/core/parse-xml.c @@ -29,6 +29,7 @@ #include "device.h" #include "membuffer.h" #include "qthelper.h" +#include "tag.h" int verbose, quit, force_root; int last_xml_version = -1; diff --git a/core/qthelper.cpp b/core/qthelper.cpp index 65c55414d..e9bab9ebd 100644 --- a/core/qthelper.cpp +++ b/core/qthelper.cpp @@ -17,6 +17,7 @@ #include #include "exif.h" #include "file.h" +#include "tag.h" #include "imagedownloader.h" #include #include diff --git a/core/save-git.c b/core/save-git.c index a5f6f0dde..bbf70c373 100644 --- a/core/save-git.c +++ b/core/save-git.c @@ -26,6 +26,7 @@ #include "version.h" #include "qthelper.h" #include "gettext.h" +#include "tag.h" #define VA_BUF(b, fmt) do { va_list args; va_start(args, fmt); put_vformat(b, fmt, args); va_end(args); } while (0) diff --git a/core/save-html.c b/core/save-html.c index f9d7049a9..3c54efd6f 100644 --- a/core/save-html.c +++ b/core/save-html.c @@ -8,6 +8,7 @@ #include "qthelper.h" #include "gettext.h" #include "divesite.h" +#include "tag.h" #include void write_attribute(struct membuffer *b, const char *att_name, const char *value, const char *separator) diff --git a/core/save-xml.c b/core/save-xml.c index f043ab6d8..658f05e1b 100644 --- a/core/save-xml.c +++ b/core/save-xml.c @@ -22,6 +22,7 @@ #include "git-access.h" #include "qthelper.h" #include "gettext.h" +#include "tag.h" /* * We're outputting utf8 in xml. diff --git a/core/structured_list.h b/core/structured_list.h new file mode 100644 index 000000000..232e4ee34 --- /dev/null +++ b/core/structured_list.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef STRUCTURED_LIST_H +#define STRUCTURED_LIST_H + +/* Clear everything but the first element; + * this works for taglist, picturelist, even dive computers */ +#define STRUCTURED_LIST_FREE(_type, _start, _free) \ + { \ + _type *_ptr = _start; \ + while (_ptr) { \ + _type *_next = _ptr->next; \ + _free(_ptr); \ + _ptr = _next; \ + } \ + } + +#define STRUCTURED_LIST_COPY(_type, _first, _dest, _cpy) \ + { \ + _type *_sptr = _first; \ + _type **_dptr = &_dest; \ + while (_sptr) { \ + *_dptr = malloc(sizeof(_type)); \ + _cpy(_sptr, *_dptr); \ + _sptr = _sptr->next; \ + _dptr = &(*_dptr)->next; \ + } \ + *_dptr = 0; \ + } + +#endif diff --git a/core/tag.c b/core/tag.c new file mode 100644 index 000000000..ba88ab879 --- /dev/null +++ b/core/tag.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "tag.h" +#include "structured_list.h" +#include "subsurface-string.h" +#include "membuffer.h" +#include "gettext.h" + +#include + +struct tag_entry *g_tag_list = NULL; + +static const char *default_tags[] = { + QT_TRANSLATE_NOOP("gettextFromC", "boat"), QT_TRANSLATE_NOOP("gettextFromC", "shore"), QT_TRANSLATE_NOOP("gettextFromC", "drift"), + QT_TRANSLATE_NOOP("gettextFromC", "deep"), QT_TRANSLATE_NOOP("gettextFromC", "cavern"), QT_TRANSLATE_NOOP("gettextFromC", "ice"), + QT_TRANSLATE_NOOP("gettextFromC", "wreck"), QT_TRANSLATE_NOOP("gettextFromC", "cave"), QT_TRANSLATE_NOOP("gettextFromC", "altitude"), + QT_TRANSLATE_NOOP("gettextFromC", "pool"), QT_TRANSLATE_NOOP("gettextFromC", "lake"), QT_TRANSLATE_NOOP("gettextFromC", "river"), + QT_TRANSLATE_NOOP("gettextFromC", "night"), QT_TRANSLATE_NOOP("gettextFromC", "fresh"), QT_TRANSLATE_NOOP("gettextFromC", "student"), + QT_TRANSLATE_NOOP("gettextFromC", "instructor"), QT_TRANSLATE_NOOP("gettextFromC", "photo"), QT_TRANSLATE_NOOP("gettextFromC", "video"), + QT_TRANSLATE_NOOP("gettextFromC", "deco") +}; + +/* copy an element in a list of tags */ +static void copy_tl(struct tag_entry *st, struct tag_entry *dt) +{ + dt->tag = malloc(sizeof(struct divetag)); + dt->tag->name = copy_string(st->tag->name); + dt->tag->source = copy_string(st->tag->source); +} + +static bool tag_seen_before(struct tag_entry *start, struct tag_entry *before) +{ + while (start && start != before) { + if (same_string(start->tag->name, before->tag->name)) + return true; + start = start->next; + } + return false; +} + +/* remove duplicates and empty nodes */ +void taglist_cleanup(struct tag_entry **tag_list) +{ + struct tag_entry **tl = tag_list; + while (*tl) { + /* skip tags that are empty or that we have seen before */ + if (empty_string((*tl)->tag->name) || tag_seen_before(*tag_list, *tl)) { + *tl = (*tl)->next; + continue; + } + tl = &(*tl)->next; + } +} + +char *taglist_get_tagstring(struct tag_entry *tag_list) +{ + bool first_tag = true; + struct membuffer b = { 0 }; + struct tag_entry *tmp = tag_list; + while (tmp != NULL) { + if (!empty_string(tmp->tag->name)) { + if (first_tag) { + put_format(&b, "%s", tmp->tag->name); + first_tag = false; + } else { + put_format(&b, ", %s", tmp->tag->name); + } + } + tmp = tmp->next; + } + /* Ensures we do return null terminated empty string for: + * - empty tag list + * - tag list with empty tag only + */ + mb_cstring(&b); + return detach_buffer(&b); +} + +static inline void taglist_free_divetag(struct divetag *tag) +{ + if (tag->name != NULL) + free(tag->name); + if (tag->source != NULL) + free(tag->source); + free(tag); +} + +/* Add a tag to the tag_list, keep the list sorted */ +static struct divetag *taglist_add_divetag(struct tag_entry **tag_list, struct divetag *tag) +{ + struct tag_entry *next, *entry; + + while ((next = *tag_list) != NULL) { + int cmp = strcmp(next->tag->name, tag->name); + + /* Already have it? */ + if (!cmp) + return next->tag; + /* Is the entry larger? If so, insert here */ + if (cmp > 0) + break; + /* Continue traversing the list */ + tag_list = &next->next; + } + + /* Insert in front of it */ + entry = malloc(sizeof(struct tag_entry)); + entry->next = next; + entry->tag = tag; + *tag_list = entry; + return tag; +} + +struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag) +{ + size_t i = 0; + int is_default_tag = 0; + struct divetag *ret_tag, *new_tag; + const char *translation; + new_tag = malloc(sizeof(struct divetag)); + + for (i = 0; i < sizeof(default_tags) / sizeof(char *); i++) { + if (strcmp(default_tags[i], tag) == 0) { + is_default_tag = 1; + break; + } + } + /* Only translate default tags */ + if (is_default_tag) { + translation = translate("gettextFromC", tag); + new_tag->name = malloc(strlen(translation) + 1); + memcpy(new_tag->name, translation, strlen(translation) + 1); + new_tag->source = malloc(strlen(tag) + 1); + memcpy(new_tag->source, tag, strlen(tag) + 1); + } else { + new_tag->source = NULL; + new_tag->name = malloc(strlen(tag) + 1); + memcpy(new_tag->name, tag, strlen(tag) + 1); + } + /* Try to insert new_tag into g_tag_list if we are not operating on it */ + if (tag_list != &g_tag_list) { + ret_tag = taglist_add_divetag(&g_tag_list, new_tag); + /* g_tag_list already contains new_tag, free the duplicate */ + if (ret_tag != new_tag) + taglist_free_divetag(new_tag); + ret_tag = taglist_add_divetag(tag_list, ret_tag); + } else { + ret_tag = taglist_add_divetag(tag_list, new_tag); + if (ret_tag != new_tag) + taglist_free_divetag(new_tag); + } + return ret_tag; +} + +void taglist_free(struct tag_entry *entry) +{ + STRUCTURED_LIST_FREE(struct tag_entry, entry, free) +} + +struct tag_entry *taglist_copy(struct tag_entry *s) +{ + struct tag_entry *res; + STRUCTURED_LIST_COPY(struct tag_entry, s, res, copy_tl); + return res; +} + +/* Merge src1 and src2, write to *dst */ +void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_entry *src2) +{ + struct tag_entry *entry; + + for (entry = src1; entry; entry = entry->next) + taglist_add_divetag(dst, entry->tag); + for (entry = src2; entry; entry = entry->next) + taglist_add_divetag(dst, entry->tag); +} + +void taglist_init_global() +{ + size_t i; + + for (i = 0; i < sizeof(default_tags) / sizeof(char *); i++) + taglist_add_tag(&g_tag_list, default_tags[i]); +} + +bool taglist_contains(struct tag_entry *tag_list, const char *tag) +{ + while (tag_list) { + if (same_string(tag_list->tag->name, tag)) + return true; + tag_list = tag_list->next; + } + return false; +} + +struct tag_entry *taglist_added(struct tag_entry *original_list, struct tag_entry *new_list) +{ + struct tag_entry *added_list = NULL; + while (new_list) { + if (!taglist_contains(original_list, new_list->tag->name)) + taglist_add_tag(&added_list, new_list->tag->name); + new_list = new_list->next; + } + return added_list; +} + diff --git a/core/tag.h b/core/tag.h new file mode 100644 index 000000000..1f50dc920 --- /dev/null +++ b/core/tag.h @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +// Dive tag related structures and helpers +#ifndef TAG_H +#define TAG_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct divetag { + /* + * The name of the divetag. If a translation is available, name contains + * the translated tag + */ + char *name; + /* + * If a translation is available, we write the original tag to source. + * This enables us to write a non-localized tag to the xml file. + */ + char *source; +}; + +struct tag_entry { + struct divetag *tag; + struct tag_entry *next; +}; + +/* + * divetags are only stored once, each dive only contains + * a list of tag_entries which then point to the divetags + * in the global g_tag_list + */ +extern struct tag_entry *g_tag_list; + +struct divetag *taglist_add_tag(struct tag_entry **tag_list, const char *tag); +struct tag_entry *taglist_added(struct tag_entry *original_list, struct tag_entry *new_list); + +/* + * Writes all divetags form tag_list into internally allocated buffer + * Function returns pointer to allocated buffer + * Buffer contains comma separated list of tags names or null terminated string + * + * NOTE! The returned buffer must be freed once used. + */ +char *taglist_get_tagstring(struct tag_entry *tag_list); + +/* cleans up a list: removes empty tags and duplicates */ +void taglist_cleanup(struct tag_entry **tag_list); + +void taglist_init_global(); +void taglist_free(struct tag_entry *tag_list); +struct tag_entry *taglist_copy(struct tag_entry *s); +bool taglist_contains(struct tag_entry *tag_list, const char *tag); +void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_entry *src2); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/core/uemis-downloader.c b/core/uemis-downloader.c index 593b94617..83f37545b 100644 --- a/core/uemis-downloader.c +++ b/core/uemis-downloader.c @@ -26,6 +26,7 @@ #include "uemis.h" #include "divelist.h" #include "divesite.h" +#include "tag.h" #include "core/subsurface-string.h" #define ERR_FS_ALMOST_FULL QT_TRANSLATE_NOOP("gettextFromC", "Uemis Zurich: the file system is almost full.\nDisconnect/reconnect the dive computer\nand click \'Retry\'") diff --git a/desktop-widgets/command_edit.cpp b/desktop-widgets/command_edit.cpp index 2c9d56ba5..89b864f60 100644 --- a/desktop-widgets/command_edit.cpp +++ b/desktop-widgets/command_edit.cpp @@ -5,6 +5,7 @@ #include "core/divelist.h" #include "core/qthelper.h" // for copy_qstring #include "core/subsurface-string.h" +#include "core/tag.h" #include "desktop-widgets/mapwidget.h" // TODO: Replace desktop-dependency by signal namespace Command { diff --git a/desktop-widgets/divelogexportdialog.cpp b/desktop-widgets/divelogexportdialog.cpp index 4fef543a0..1059d9bd0 100644 --- a/desktop-widgets/divelogexportdialog.cpp +++ b/desktop-widgets/divelogexportdialog.cpp @@ -17,6 +17,7 @@ #include "profile-widget/profilewidget2.h" #include "core/save-profiledata.h" #include "core/divesite.h" +#include "core/tag.h" // Retrieves the current unit settings defined in the Subsurface preferences. #define GET_UNIT(name, field, f, t) \ diff --git a/desktop-widgets/simplewidgets.cpp b/desktop-widgets/simplewidgets.cpp index 660a8a433..acb66c0c5 100644 --- a/desktop-widgets/simplewidgets.cpp +++ b/desktop-widgets/simplewidgets.cpp @@ -22,6 +22,7 @@ #include "profile-widget/profilewidget2.h" #include "desktop-widgets/command.h" #include "core/metadata.h" +#include "core/tag.h" double MinMaxAvgWidget::average() const { diff --git a/packaging/ios/Subsurface-mobile.pro b/packaging/ios/Subsurface-mobile.pro index ea6a378ea..a0caf4886 100644 --- a/packaging/ios/Subsurface-mobile.pro +++ b/packaging/ios/Subsurface-mobile.pro @@ -70,6 +70,7 @@ SOURCES += ../../subsurface-mobile-main.cpp \ ../../core/membuffer.c \ ../../core/sha1.c \ ../../core/strtod.c \ + ../../core/tag.c \ ../../core/taxonomy.c \ ../../core/time.c \ ../../core/uemis.c \ diff --git a/qt-models/completionmodels.cpp b/qt-models/completionmodels.cpp index b4e166de3..957b8c7fd 100644 --- a/qt-models/completionmodels.cpp +++ b/qt-models/completionmodels.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "qt-models/completionmodels.h" #include "core/dive.h" +#include "core/tag.h" #include #include diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp index 59069164f..7795b3563 100644 --- a/qt-models/divetripmodel.cpp +++ b/qt-models/divetripmodel.cpp @@ -6,6 +6,7 @@ #include "core/divelist.h" #include "core/qthelper.h" #include "core/subsurface-string.h" +#include "core/tag.h" #include #include #include diff --git a/smtk-import/smartrak.c b/smtk-import/smartrak.c index 31c7e4dc3..64c6d8e5f 100644 --- a/smtk-import/smartrak.c +++ b/smtk-import/smartrak.c @@ -33,6 +33,7 @@ #include "core/libdivecomputer.h" #include "core/divesite.h" #include "core/membuffer.h" +#include "core/tag.h" /* SmartTrak version, constant for every single file */ int smtk_version; diff --git a/subsurface-desktop-main.cpp b/subsurface-desktop-main.cpp index cec1a159b..7922b01e1 100644 --- a/subsurface-desktop-main.cpp +++ b/subsurface-desktop-main.cpp @@ -12,6 +12,7 @@ #include "core/qthelper.h" #include "core/subsurfacestartup.h" #include "core/settings/qPref.h" +#include "core/tag.h" #include "desktop-widgets/diveplanner.h" #include "desktop-widgets/mainwindow.h" #include "desktop-widgets/preferences/preferencesdialog.h" diff --git a/subsurface-mobile-main.cpp b/subsurface-mobile-main.cpp index a9e4b424d..93c81f5a1 100644 --- a/subsurface-mobile-main.cpp +++ b/subsurface-mobile-main.cpp @@ -13,6 +13,7 @@ #include "core/subsurfacestartup.h" #include "core/settings/qPref.h" #include "core/settings/qPrefDisplay.h" +#include "core/tag.h" #include #include diff --git a/tests/testtaglist.cpp b/tests/testtaglist.cpp index afe5049f1..cd7e59c43 100644 --- a/tests/testtaglist.cpp +++ b/tests/testtaglist.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "testtaglist.h" #include "core/dive.h" +#include "core/tag.h" void TestTagList::initTestCase() {