mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
core: port tag-list to C++
Also adds a new test, which tests merging of two tag-lists. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
640ecb345b
commit
f18acf6fb9
25 changed files with 195 additions and 227 deletions
|
@ -187,7 +187,7 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
|
|||
dive->maxdepth.mm ? put_format(&buf, "\\def\\%smaximumdepth{%.1f\\%sdepthunit}\n", ssrf, get_depth_units(dive->maxdepth.mm, NULL, &unit), ssrf) : put_format(&buf, "\\def\\%smaximumdepth{}\n", ssrf);
|
||||
dive->meandepth.mm ? put_format(&buf, "\\def\\%smeandepth{%.1f\\%sdepthunit}\n", ssrf, get_depth_units(dive->meandepth.mm, NULL, &unit), ssrf) : put_format(&buf, "\\def\\%smeandepth{}\n", ssrf);
|
||||
|
||||
std::string tags = taglist_get_tagstring(dive->tag_list);
|
||||
std::string tags = taglist_get_tagstring(dive->tags);
|
||||
put_format(&buf, "\\def\\%stype{%s}\n", ssrf, tags.c_str());
|
||||
put_format(&buf, "\\def\\%sviz{%s}\n", ssrf, qPrintable(viz));
|
||||
put_format(&buf, "\\def\\%srating{%s}\n", ssrf, qPrintable(rating));
|
||||
|
|
|
@ -564,18 +564,17 @@ void EditTagsBase::redo()
|
|||
QStringList EditTags::data(struct dive *d) const
|
||||
{
|
||||
QStringList res;
|
||||
for (const struct tag_entry *tag = d->tag_list; tag; tag = tag->next)
|
||||
res.push_back(QString::fromStdString(tag->tag->name));
|
||||
for (const divetag *tag: d->tags)
|
||||
res.push_back(QString::fromStdString(tag->name));
|
||||
return res;
|
||||
}
|
||||
|
||||
void EditTags::set(struct dive *d, const QStringList &v) const
|
||||
{
|
||||
taglist_free(d->tag_list);
|
||||
d->tag_list = NULL;
|
||||
d->tags.clear();
|
||||
for (const QString &tag: v)
|
||||
taglist_add_tag(&d->tag_list, qPrintable(tag));
|
||||
taglist_cleanup(&d->tag_list);
|
||||
taglist_add_tag(d->tags, tag.toStdString());
|
||||
taglist_cleanup(d->tags);
|
||||
}
|
||||
|
||||
QString EditTags::fieldName() const
|
||||
|
@ -627,8 +626,7 @@ static void swapCandQString(QString &q, char *&c)
|
|||
q = std::move(tmp);
|
||||
}
|
||||
|
||||
PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dIn),
|
||||
tags(nullptr)
|
||||
PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dIn)
|
||||
{
|
||||
if (what.notes)
|
||||
notes = data->notes;
|
||||
|
@ -653,7 +651,7 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI
|
|||
if (what.divesite)
|
||||
divesite = data->dive_site;
|
||||
if (what.tags)
|
||||
tags = taglist_copy(data->tag_list);
|
||||
tags = data->tags;
|
||||
if (what.cylinders) {
|
||||
cylinders = data->cylinders;
|
||||
// Paste cylinders is "special":
|
||||
|
@ -695,7 +693,6 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI
|
|||
|
||||
PasteState::~PasteState()
|
||||
{
|
||||
taglist_free(tags);
|
||||
}
|
||||
|
||||
void PasteState::swap(dive_components what)
|
||||
|
@ -723,7 +720,7 @@ void PasteState::swap(dive_components what)
|
|||
if (what.divesite)
|
||||
std::swap(divesite, d->dive_site);
|
||||
if (what.tags)
|
||||
std::swap(tags, d->tag_list);
|
||||
std::swap(tags, d->tags);
|
||||
if (what.cylinders)
|
||||
std::swap(cylinders, d->cylinders);
|
||||
if (what.weights)
|
||||
|
@ -1397,7 +1394,7 @@ EditDive::EditDive(dive *oldDiveIn, dive *newDiveIn, dive_site *createDs, dive_s
|
|||
changedFields |= DiveField::CHILL;
|
||||
if (!same_string(oldDive->suit, newDive->suit))
|
||||
changedFields |= DiveField::SUIT;
|
||||
if (taglist_get_tagstring(oldDive->tag_list) != taglist_get_tagstring(newDive->tag_list)) // This is cheating. Do we have a taglist comparison function?
|
||||
if (taglist_get_tagstring(oldDive->tags) != taglist_get_tagstring(newDive->tags)) // This is cheating. Do we have a taglist comparison function?
|
||||
changedFields |= DiveField::TAGS;
|
||||
if (oldDive->dcs[0].divemode != newDive->dcs[0].divemode)
|
||||
changedFields |= DiveField::MODE;
|
||||
|
|
|
@ -299,7 +299,7 @@ struct PasteState {
|
|||
int current;
|
||||
int surge;
|
||||
int chill;
|
||||
tag_entry *tags;
|
||||
tag_list tags;
|
||||
cylinder_table cylinders;
|
||||
weightsystem_table weightsystems;
|
||||
int number;
|
||||
|
|
|
@ -265,26 +265,26 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
* Weather, values table, 0 to 6
|
||||
* Subsurface don't have this record but we can use tags
|
||||
*/
|
||||
dt_dive->tag_list = NULL;
|
||||
dt_dive->tags.clear();
|
||||
read_bytes(1);
|
||||
switch (tmp_1byte) {
|
||||
case 1:
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "clear")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "clear"));
|
||||
break;
|
||||
case 2:
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "misty")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "misty"));
|
||||
break;
|
||||
case 3:
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "fog")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "fog"));
|
||||
break;
|
||||
case 4:
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "rain")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "rain"));
|
||||
break;
|
||||
case 5:
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "storm")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "storm"));
|
||||
break;
|
||||
case 6:
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "snow")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "snow"));
|
||||
break;
|
||||
default:
|
||||
// unknown, do nothing
|
||||
|
@ -304,22 +304,22 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
read_bytes(1);
|
||||
switch (tmp_1byte) {
|
||||
case 1:
|
||||
dt_dive->suit = strdup(QT_TRANSLATE_NOOP("gettextFromC", "No suit"));
|
||||
dt_dive->suit = strdup(translate("gettextFromC", "No suit"));
|
||||
break;
|
||||
case 2:
|
||||
dt_dive->suit = strdup(QT_TRANSLATE_NOOP("gettextFromC", "Shorty"));
|
||||
dt_dive->suit = strdup(translate("gettextFromC", "Shorty"));
|
||||
break;
|
||||
case 3:
|
||||
dt_dive->suit = strdup(QT_TRANSLATE_NOOP("gettextFromC", "Combi"));
|
||||
dt_dive->suit = strdup(translate("gettextFromC", "Combi"));
|
||||
break;
|
||||
case 4:
|
||||
dt_dive->suit = strdup(QT_TRANSLATE_NOOP("gettextFromC", "Wet suit"));
|
||||
dt_dive->suit = strdup(translate("gettextFromC", "Wet suit"));
|
||||
break;
|
||||
case 5:
|
||||
dt_dive->suit = strdup(QT_TRANSLATE_NOOP("gettextFromC", "Semidry suit"));
|
||||
dt_dive->suit = strdup(translate("gettextFromC", "Semidry suit"));
|
||||
break;
|
||||
case 6:
|
||||
dt_dive->suit = strdup(QT_TRANSLATE_NOOP("gettextFromC", "Dry suit"));
|
||||
dt_dive->suit = strdup(translate("gettextFromC", "Dry suit"));
|
||||
break;
|
||||
default:
|
||||
// unknown, do nothing
|
||||
|
@ -380,28 +380,28 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
*/
|
||||
read_bytes(1);
|
||||
if (bit_set(tmp_1byte, 2))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "no stop")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "no stop"));
|
||||
if (bit_set(tmp_1byte, 3))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "deco")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "deco"));
|
||||
if (bit_set(tmp_1byte, 4))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "single ascent")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "single ascent"));
|
||||
if (bit_set(tmp_1byte, 5))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "multiple ascent")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "multiple ascent"));
|
||||
if (bit_set(tmp_1byte, 6))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "fresh water")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "fresh water"));
|
||||
if (bit_set(tmp_1byte, 7))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "salt water")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "salt water"));
|
||||
|
||||
/*
|
||||
* Dive Type 2 - Bit table, use tags again
|
||||
*/
|
||||
read_bytes(1);
|
||||
if (bit_set(tmp_1byte, 0)) {
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup("nitrox"));
|
||||
taglist_add_tag(dt_dive->tags, "nitrox");
|
||||
is_nitrox = 1;
|
||||
}
|
||||
if (bit_set(tmp_1byte, 1)) {
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup("rebreather"));
|
||||
taglist_add_tag(dt_dive->tags, "rebreather");
|
||||
is_SCR = 1;
|
||||
dt_dive->dcs[0].divemode = PSCR;
|
||||
}
|
||||
|
@ -411,36 +411,36 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
*/
|
||||
read_bytes(1);
|
||||
if (bit_set(tmp_1byte, 0))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "sight seeing")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "sight seeing"));
|
||||
if (bit_set(tmp_1byte, 1))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "club dive")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "club dive"));
|
||||
if (bit_set(tmp_1byte, 2))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "instructor")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "instructor"));
|
||||
if (bit_set(tmp_1byte, 3))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "instruction")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "instruction"));
|
||||
if (bit_set(tmp_1byte, 4))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "night")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "night"));
|
||||
if (bit_set(tmp_1byte, 5))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "cave")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "cave"));
|
||||
if (bit_set(tmp_1byte, 6))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "ice")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "ice"));
|
||||
if (bit_set(tmp_1byte, 7))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "search")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "search"));
|
||||
|
||||
/*
|
||||
* Dive Activity 2 - Bit table, use tags again
|
||||
*/
|
||||
read_bytes(1);
|
||||
if (bit_set(tmp_1byte, 0))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "wreck")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "wreck"));
|
||||
if (bit_set(tmp_1byte, 1))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "river")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "river"));
|
||||
if (bit_set(tmp_1byte, 2))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "drift")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "drift"));
|
||||
if (bit_set(tmp_1byte, 3))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "photo")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "photo"));
|
||||
if (bit_set(tmp_1byte, 4))
|
||||
taglist_add_tag(&dt_dive->tag_list, strdup(QT_TRANSLATE_NOOP("gettextFromC", "other")));
|
||||
taglist_add_tag(dt_dive->tags, translate("gettextFromC", "other"));
|
||||
|
||||
/*
|
||||
* Other activities - String 1st byte = long
|
||||
|
@ -450,7 +450,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
if (tmp_1byte != 0) {
|
||||
read_string(tmp_string1);
|
||||
snprintf(buffer, sizeof(buffer), "%s: %s\n",
|
||||
QT_TRANSLATE_NOOP("gettextFromC", "Other activities"),
|
||||
translate("gettextFromC", "Other activities"),
|
||||
tmp_string1);
|
||||
tmp_notes_str = strdup(buffer);
|
||||
free(tmp_string1);
|
||||
|
@ -474,7 +474,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct
|
|||
read_string(tmp_string1);
|
||||
int len = snprintf(buffer, sizeof(buffer), "%s%s:\n%s",
|
||||
tmp_notes_str ? tmp_notes_str : "",
|
||||
QT_TRANSLATE_NOOP("gettextFromC", "Datatrak/Wlog notes"),
|
||||
translate("gettextFromC", "Datatrak/Wlog notes"),
|
||||
tmp_string1);
|
||||
dt_dive->notes = (char *)calloc((len +1), 1);
|
||||
memcpy(dt_dive->notes, buffer, len);
|
||||
|
@ -630,7 +630,7 @@ static void wlog_compl_parser(std::string &wl_mem, struct dive *dt_dive, int dco
|
|||
*/
|
||||
tmp = (int) two_bytes_to_int(runner[pos_weight + 1], runner[pos_weight]);
|
||||
if (tmp != 0x7fff) {
|
||||
weightsystem_t ws = { {tmp * 10}, QT_TRANSLATE_NOOP("gettextFromC", "unknown"), false };
|
||||
weightsystem_t ws = { {tmp * 10}, translate("gettextFromC", "unknown"), false };
|
||||
dt_dive->weightsystems.push_back(std::move(ws));
|
||||
}
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ static void free_dive_structures(struct dive *d)
|
|||
free(d->notes);
|
||||
free(d->suit);
|
||||
/* free tags, additional dive computers, and pictures */
|
||||
taglist_free(d->tag_list);
|
||||
d->tags.clear();
|
||||
d->cylinders.clear();
|
||||
d->weightsystems.clear();
|
||||
clear_picture_table(&d->pictures);
|
||||
|
@ -211,7 +211,6 @@ void copy_dive(const struct dive *s, struct dive *d)
|
|||
d->notes = copy_string(s->notes);
|
||||
d->suit = copy_string(s->suit);
|
||||
copy_pictures(&s->pictures, &d->pictures);
|
||||
d->tag_list = taglist_copy(s->tag_list);
|
||||
}
|
||||
|
||||
static void copy_dive_onedc(const struct dive *s, const struct divecomputer &sdc, struct dive *d)
|
||||
|
@ -253,7 +252,7 @@ void selective_copy_dive(const struct dive *s, struct dive *d, struct dive_compo
|
|||
s->dive_site->add_dive(d);
|
||||
}
|
||||
if (what.tags)
|
||||
d->tag_list = taglist_copy(s->tag_list);
|
||||
d->tags = s->tags;
|
||||
if (what.cylinders)
|
||||
copy_cylinder_types(s, d);
|
||||
if (what.weights)
|
||||
|
@ -2349,7 +2348,7 @@ struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset,
|
|||
MERGE_NONZERO(res, a, b, surge);
|
||||
MERGE_NONZERO(res, a, b, chill);
|
||||
copy_pictures(a->pictures.nr ? &a->pictures : &b->pictures, &res->pictures);
|
||||
taglist_merge(&res->tag_list, a->tag_list, b->tag_list);
|
||||
res->tags = taglist_merge(a->tags, b->tags);
|
||||
/* if we get dives without any gas / cylinder information in an import, make sure
|
||||
* that there is at leatst one entry in the cylinder map for that dive */
|
||||
auto cylinders_map_a = std::make_unique<int[]>(std::max(size_t(1), a->cylinders.size()));
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "divecomputer.h"
|
||||
#include "equipment.h"
|
||||
#include "picture.h" // TODO: remove
|
||||
#include "tag.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -46,7 +47,7 @@ struct dive {
|
|||
int salinity = 0; // kg per 10000 l
|
||||
int user_salinity = 0; // water density reflecting a user-specified type
|
||||
|
||||
struct tag_entry *tag_list = nullptr;
|
||||
tag_list tags;
|
||||
std::vector<divecomputer> dcs; // Attn: pointers to divecomputers are not stable!
|
||||
int id = 0; // unique ID for this dive
|
||||
struct picture_table pictures = { };
|
||||
|
|
|
@ -818,8 +818,8 @@ static bool check(const filter_constraint &c, const QStringList &list)
|
|||
static bool has_tags(const filter_constraint &c, const struct dive *d)
|
||||
{
|
||||
QStringList dive_tags;
|
||||
for (const tag_entry *tag = d->tag_list; tag; tag = tag->next)
|
||||
dive_tags.push_back(QString::fromStdString(tag->tag->name).trimmed());
|
||||
for (const divetag *tag: d->tags)
|
||||
dive_tags.push_back(QString::fromStdString(tag->name).trimmed());
|
||||
return check(c, dive_tags);
|
||||
}
|
||||
|
||||
|
|
|
@ -123,8 +123,8 @@ static std::vector<QString> getWords(const dive *d)
|
|||
tokenize(QString(d->diveguide), res);
|
||||
tokenize(QString(d->buddy), res);
|
||||
tokenize(QString(d->suit), res);
|
||||
for (const tag_entry *tag = d->tag_list; tag; tag = tag->next)
|
||||
tokenize(QString::fromStdString(tag->tag->name), res);
|
||||
for (const divetag *tag: d->tags)
|
||||
tokenize(QString::fromStdString(tag->name), res);
|
||||
for (auto &cyl: d->cylinders)
|
||||
tokenize(QString::fromStdString(cyl.type.description), res);
|
||||
for (auto &ws: d->weightsystems)
|
||||
|
|
|
@ -155,7 +155,7 @@ static int dm4_tags(void *param, int, char **data, char **)
|
|||
struct parser_state *state = (struct parser_state *)param;
|
||||
|
||||
if (data[0])
|
||||
taglist_add_tag(&state->cur_dive->tag_list, data[0]);
|
||||
taglist_add_tag(state->cur_dive->tags, data[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -261,7 +261,7 @@ static void parse_dive_tags(char *, struct git_parser_state *state)
|
|||
{
|
||||
for (const std::string &tag: state->converted_strings) {
|
||||
if (!tag.empty())
|
||||
taglist_add_tag(&state->active_dive->tag_list, tag.c_str());
|
||||
taglist_add_tag(state->active_dive->tags, tag.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ enum ParseState {
|
|||
FINDSTART,
|
||||
FINDEND
|
||||
};
|
||||
static void divetags(const char *buffer, struct tag_entry **tags)
|
||||
static void divetags(const char *buffer, tag_list *tags)
|
||||
{
|
||||
int i = 0, start = 0, end = 0;
|
||||
enum ParseState state = FINDEND;
|
||||
|
@ -116,7 +116,7 @@ static void divetags(const char *buffer, struct tag_entry **tags)
|
|||
if (i > 0 && buffer[i - 1] != '\\') {
|
||||
std::string s(buffer + start, i - start);
|
||||
state = FINDSTART;
|
||||
taglist_add_tag(tags, s.c_str());
|
||||
taglist_add_tag(*tags, s.c_str());
|
||||
} else {
|
||||
state = FINDSTART;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ static void divetags(const char *buffer, struct tag_entry **tags)
|
|||
end = len - 1;
|
||||
if (len > 0) {
|
||||
std::string s(buffer + start, i - start);
|
||||
taglist_add_tag(tags, buffer + start);
|
||||
taglist_add_tag(*tags, buffer + start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1254,7 +1254,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
|
|||
return;
|
||||
if (MATCH("number", get_index, &dive->number))
|
||||
return;
|
||||
if (MATCH("tags", divetags, &dive->tag_list))
|
||||
if (MATCH("tags", divetags, &dive->tags))
|
||||
return;
|
||||
if (MATCH("tripflag", get_notrip, &dive->notrip))
|
||||
return;
|
||||
|
|
|
@ -104,17 +104,16 @@ static void save_overview(struct membuffer *b, struct dive *dive)
|
|||
show_utf8(b, "notes ", dive->notes, "\n");
|
||||
}
|
||||
|
||||
static void save_tags(struct membuffer *b, struct tag_entry *tags)
|
||||
static void save_tags(struct membuffer *b, const tag_list &tags)
|
||||
{
|
||||
const char *sep = " ";
|
||||
|
||||
if (!tags)
|
||||
if (tags.empty())
|
||||
return;
|
||||
put_string(b, "tags");
|
||||
while (tags) {
|
||||
show_utf8(b, sep, tags->tag->source.empty() ? tags->tag->name.c_str() : tags->tag->source.c_str(), "");
|
||||
for (const divetag *tag: tags) {
|
||||
show_utf8(b, sep, tag->source.empty() ? tag->name.c_str() : tag->source.c_str(), "");
|
||||
sep = ", ";
|
||||
tags = tags->next;
|
||||
}
|
||||
put_string(b, "\n");
|
||||
}
|
||||
|
@ -449,7 +448,7 @@ static void create_dive_buffer(struct dive *dive, struct membuffer *b)
|
|||
SAVE("airpressure", surface_pressure.mbar);
|
||||
cond_put_format(dive->notrip, b, "notrip\n");
|
||||
cond_put_format(dive->invalid, b, "invalid\n");
|
||||
save_tags(b, dive->tag_list);
|
||||
save_tags(b, dive->tags);
|
||||
if (dive->dive_site)
|
||||
put_format(b, "divesiteid %08x\n", dive->dive_site->uuid);
|
||||
if (verbose && dive->dive_site)
|
||||
|
|
|
@ -311,18 +311,16 @@ void put_HTML_watertemp(struct membuffer *b, const struct dive *dive, const char
|
|||
static void put_HTML_tags(struct membuffer *b, const struct dive *dive, const char *pre, const char *post)
|
||||
{
|
||||
put_string(b, pre);
|
||||
struct tag_entry *tag = dive->tag_list;
|
||||
|
||||
if (!tag)
|
||||
if (dive->tags.empty())
|
||||
put_string(b, "[\"--\"");
|
||||
|
||||
const char *separator = "[";
|
||||
while (tag) {
|
||||
for (const divetag *tag: dive->tags) {
|
||||
put_format(b, "%s\"", separator);
|
||||
separator = ", ";
|
||||
put_HTML_quoted(b, tag->tag->name.c_str());
|
||||
put_HTML_quoted(b, tag->name.c_str());
|
||||
put_string(b, "\"");
|
||||
tag = tag->next;
|
||||
}
|
||||
put_string(b, "]");
|
||||
put_string(b, post);
|
||||
|
|
|
@ -367,17 +367,16 @@ static void save_events(struct membuffer *b, struct dive *dive, const struct div
|
|||
save_one_event(b, dive, ev);
|
||||
}
|
||||
|
||||
static void save_tags(struct membuffer *b, struct tag_entry *entry)
|
||||
static void save_tags(struct membuffer *b, const tag_list &tags)
|
||||
{
|
||||
if (entry) {
|
||||
if (!tags.empty()) {
|
||||
const char *sep = " tags='";
|
||||
do {
|
||||
const struct divetag *tag = entry->tag;
|
||||
for (const divetag *tag: tags) {
|
||||
put_string(b, sep);
|
||||
/* If the tag has been translated, write the source to the xml file */
|
||||
quote(b, tag->source.empty() ? tag->name.c_str() : tag->source.c_str(), 1);
|
||||
sep = ", ";
|
||||
} while ((entry = entry->next) != NULL);
|
||||
}
|
||||
put_string(b, "'");
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +508,7 @@ void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize)
|
|||
if (dive->maxcns)
|
||||
put_format(b, " cns='%d%%'", dive->maxcns);
|
||||
|
||||
save_tags(b, dive->tag_list);
|
||||
save_tags(b, dive->tags);
|
||||
if (dive->dive_site)
|
||||
put_format(b, " divesiteid='%8x'", dive->dive_site->uuid);
|
||||
if (dive->user_salinity)
|
||||
|
|
125
core/tag.cpp
125
core/tag.cpp
|
@ -22,124 +22,87 @@ static const char *default_tags[] = {
|
|||
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)
|
||||
divetag::divetag(std::string name, std::string source) :
|
||||
name(std::move(name)), source(std::move(source))
|
||||
{
|
||||
dt->tag = st->tag;
|
||||
}
|
||||
|
||||
static bool tag_seen_before(struct tag_entry *start, struct tag_entry *before)
|
||||
/* remove duplicates and empty tags */
|
||||
void taglist_cleanup(tag_list &list)
|
||||
{
|
||||
while (start && start != before) {
|
||||
if (start->tag->name == before->tag->name)
|
||||
return true;
|
||||
start = start->next;
|
||||
}
|
||||
return false;
|
||||
// Remove empty tags
|
||||
list.erase(std::remove_if(list.begin(), list.end(), [](const divetag *tag) { return tag->name.empty(); }),
|
||||
list.end());
|
||||
|
||||
// Sort (should be a NOP, because we add in a sorted way, but let's make sure)
|
||||
std::sort(list.begin(), list.end());
|
||||
|
||||
// Remove duplicates
|
||||
list.erase(std::unique(list.begin(), list.end(),
|
||||
[](const divetag *tag1, const divetag *tag2) { return tag1->name == tag2->name; }),
|
||||
list.end());
|
||||
}
|
||||
|
||||
/* remove duplicates and empty nodes */
|
||||
void taglist_cleanup(struct tag_entry **tag_list)
|
||||
std::string taglist_get_tagstring(const tag_list &list)
|
||||
{
|
||||
struct tag_entry **tl = tag_list;
|
||||
while (*tl) {
|
||||
/* skip tags that are empty or that we have seen before */
|
||||
if ((*tl)->tag->name.empty() || tag_seen_before(*tag_list, *tl)) {
|
||||
*tl = (*tl)->next;
|
||||
continue;
|
||||
}
|
||||
tl = &(*tl)->next;
|
||||
}
|
||||
}
|
||||
|
||||
std::string taglist_get_tagstring(struct tag_entry *tag_list)
|
||||
{
|
||||
bool first_tag = true;
|
||||
std::string res;
|
||||
for (struct tag_entry *tmp = tag_list; tmp != NULL; tmp = tmp->next) {
|
||||
if (tmp->tag->name.empty())
|
||||
for (const divetag *tag: list) {
|
||||
if (tag->name.empty())
|
||||
continue;
|
||||
if (!first_tag)
|
||||
if (!res.empty())
|
||||
res += ", ";
|
||||
res += tmp->tag->name;
|
||||
first_tag = false;
|
||||
res += tag->name;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Add a tag to the tag_list, keep the list sorted */
|
||||
static void taglist_add_divetag(struct tag_entry **tag_list, const struct divetag *tag)
|
||||
static void taglist_add_divetag(tag_list &list, const struct divetag *tag)
|
||||
{
|
||||
struct tag_entry *next, *entry;
|
||||
|
||||
while ((next = *tag_list) != NULL) {
|
||||
int cmp = next->tag->name.compare(tag->name);
|
||||
|
||||
/* Already have it? */
|
||||
if (!cmp)
|
||||
return;
|
||||
/* 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 = (tag_entry *)malloc(sizeof(struct tag_entry));
|
||||
entry->next = next;
|
||||
entry->tag = tag;
|
||||
*tag_list = entry;
|
||||
// Use binary search to enter at sorted position
|
||||
auto it = std::lower_bound(list.begin(), list.end(), tag,
|
||||
[](const struct divetag *tag1, const struct divetag *tag2)
|
||||
{ return tag1->name < tag2->name; });
|
||||
// Don't add if it already exists
|
||||
if (it == list.end() || (*it)->name != tag->name)
|
||||
list.insert(it, tag);
|
||||
}
|
||||
|
||||
static const divetag *register_tag(const char *s, const char *source)
|
||||
static const divetag *register_tag(std::string s, std::string source)
|
||||
{
|
||||
// binary search
|
||||
auto it = std::lower_bound(g_tag_list.begin(), g_tag_list.end(), s,
|
||||
[](const std::unique_ptr<divetag> &tag, const char *s)
|
||||
[](const std::unique_ptr<divetag> &tag, const std::string &s)
|
||||
{ return tag->name < s; });
|
||||
if (it == g_tag_list.end() || (*it)->name != s) {
|
||||
std::string source_s = empty_string(source) ? std::string() : std::string(source);
|
||||
it = g_tag_list.insert(it, std::make_unique<divetag>(s, source));
|
||||
}
|
||||
if (it == g_tag_list.end() || (*it)->name != s)
|
||||
it = g_tag_list.insert(it, std::make_unique<divetag>(std::move(s), std::move(source)));
|
||||
return it->get();
|
||||
}
|
||||
|
||||
void taglist_add_tag(struct tag_entry **tag_list, const char *tag)
|
||||
void taglist_add_tag(tag_list &list, const std::string &tag)
|
||||
{
|
||||
bool is_default_tag = std::find_if(std::begin(default_tags), std::end(default_tags),
|
||||
[&tag] (const char *default_tag) { return tag == default_tag; });
|
||||
|
||||
/* Only translate default tags */
|
||||
/* TODO: Do we really want to translate user-supplied tags if they happen to be known!? */
|
||||
const char *translation = is_default_tag ? translate("gettextFromC", tag) : tag;
|
||||
const char *source = is_default_tag ? tag : nullptr;
|
||||
const struct divetag *d_tag = register_tag(translation, source);
|
||||
std::string translation = is_default_tag ? translate("gettextFromC", tag.c_str()) : tag;
|
||||
std::string source = is_default_tag ? tag : std::string();
|
||||
const struct divetag *d_tag = register_tag(std::move(translation), std::move(source));
|
||||
|
||||
taglist_add_divetag(tag_list, d_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;
|
||||
taglist_add_divetag(list, d_tag);
|
||||
}
|
||||
|
||||
/* Merge src1 and src2, write to *dst */
|
||||
void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_entry *src2)
|
||||
tag_list taglist_merge(const tag_list &src1, const tag_list &src2)
|
||||
{
|
||||
struct tag_entry *entry;
|
||||
tag_list dst;
|
||||
|
||||
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);
|
||||
for (const divetag *t: src1)
|
||||
taglist_add_divetag(dst, t);
|
||||
for (const divetag *t: src2)
|
||||
taglist_add_divetag(dst, t);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void taglist_init_global()
|
||||
|
|
28
core/tag.h
28
core/tag.h
|
@ -19,25 +19,18 @@ struct divetag {
|
|||
* This enables us to write a non-localized tag to the xml file.
|
||||
*/
|
||||
std::string source;
|
||||
divetag(const char *n, const char *s) : name(n), source(s)
|
||||
{
|
||||
}
|
||||
divetag(std::string name, std::string source);
|
||||
};
|
||||
|
||||
struct tag_entry {
|
||||
const struct divetag *tag;
|
||||
struct tag_entry *next;
|
||||
};
|
||||
using tag_list = std::vector<const divetag *>;
|
||||
|
||||
void taglist_add_tag(struct tag_entry **tag_list, const char *tag);
|
||||
void taglist_add_tag(tag_list &list, const std::string &tag);
|
||||
|
||||
/* cleans up a list: removes empty tags and duplicates */
|
||||
void taglist_cleanup(struct tag_entry **tag_list);
|
||||
void taglist_cleanup(tag_list &list);
|
||||
|
||||
void taglist_init_global();
|
||||
void taglist_free(struct tag_entry *tag_list);
|
||||
struct tag_entry *taglist_copy(struct tag_entry *s);
|
||||
void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_entry *src2);
|
||||
tag_list taglist_merge(const tag_list &src1, const tag_list &src2);
|
||||
|
||||
/*
|
||||
* divetags are only stored once, each dive only contains
|
||||
|
@ -46,14 +39,7 @@ void taglist_merge(struct tag_entry **dst, struct tag_entry *src1, struct tag_en
|
|||
*/
|
||||
extern std::vector<std::unique_ptr<divetag>> g_tag_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
|
||||
*/
|
||||
extern std::string taglist_get_tagstring(struct tag_entry *tag_list);
|
||||
|
||||
/* Comma separated list of tags names or null terminated string */
|
||||
std::string taglist_get_tagstring(struct tag_entry *tag_list);
|
||||
/* Comma separated list of tags names or empty string */
|
||||
std::string taglist_get_tagstring(const tag_list &tags);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -341,11 +341,8 @@ void DiveComponentSelection::buttonClicked(QAbstractButton *button)
|
|||
text << tr("Suit: ") << current_dive->suit << "\n";
|
||||
if (what-> tags) {
|
||||
text << tr("Tags: ");
|
||||
tag_entry *entry = current_dive->tag_list;
|
||||
while (entry) {
|
||||
text << entry->tag->name.c_str() << " ";
|
||||
entry = entry->next;
|
||||
}
|
||||
for (const divetag *tag: current_dive->tags)
|
||||
text << tag->name.c_str() << " ";
|
||||
text << "\n";
|
||||
}
|
||||
if (what->cylinders) {
|
||||
|
|
|
@ -118,7 +118,7 @@ void TabDiveNotes::divesChanged(const QVector<dive *> &dives, DiveField field)
|
|||
if (field.divesite)
|
||||
updateDiveSite(currentDive);
|
||||
if (field.tags)
|
||||
ui.tagWidget->setText(QString::fromStdString(taglist_get_tagstring(currentDive->tag_list)));
|
||||
ui.tagWidget->setText(QString::fromStdString(taglist_get_tagstring(currentDive->tags)));
|
||||
if (field.buddy)
|
||||
ui.buddy->setText(currentDive->buddy);
|
||||
if (field.diveguide)
|
||||
|
@ -253,7 +253,7 @@ void TabDiveNotes::updateData(const std::vector<dive *> &, dive *currentDive, in
|
|||
// reset labels in case we last displayed trip notes
|
||||
ui.LocationLabel->setText(tr("Location"));
|
||||
ui.NotesLabel->setText(tr("Notes"));
|
||||
ui.tagWidget->setText(QString::fromStdString(taglist_get_tagstring(currentDive->tag_list)));
|
||||
ui.tagWidget->setText(QString::fromStdString(taglist_get_tagstring(currentDive->tags)));
|
||||
bool isManual = is_dc_manually_added_dive(¤tDive->dcs[0]);
|
||||
ui.depth->setVisible(isManual);
|
||||
ui.depthLabel->setVisible(isManual);
|
||||
|
|
|
@ -552,7 +552,7 @@ QVariant TemplateLayout::getValue(QString list, QString property, const State &s
|
|||
} else if (property == "notes") {
|
||||
return formatNotes(d);
|
||||
} else if (property == "tags") {
|
||||
return QString::fromStdString(taglist_get_tagstring(d->tag_list));
|
||||
return QString::fromStdString(taglist_get_tagstring(d->tags));
|
||||
} else if (property == "gas") {
|
||||
return formatGas(d);
|
||||
} else if (property == "sac") {
|
||||
|
|
|
@ -1324,7 +1324,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
|
|||
}
|
||||
// normalize the tag list we have and the one we get from the UI
|
||||
// try hard to deal with accidental white space issues
|
||||
QStringList existingTagList = QString::fromStdString(taglist_get_tagstring(d->tag_list)).split(",", SKIP_EMPTY);
|
||||
QStringList existingTagList = QString::fromStdString(taglist_get_tagstring(d->tags)).split(",", SKIP_EMPTY);
|
||||
QStringList newTagList = tags.split(",", SKIP_EMPTY);
|
||||
QStringList newCleanTagList;
|
||||
for (QString s: newTagList) {
|
||||
|
@ -1335,10 +1335,9 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
|
|||
existingTagList.sort();
|
||||
if (newCleanTagList.join(",") != existingTagList.join(",")) {
|
||||
diveChanged = true;
|
||||
taglist_free(d->tag_list);
|
||||
d->tag_list = nullptr;
|
||||
d->tags.clear();
|
||||
for (QString tag: newCleanTagList)
|
||||
taglist_add_tag(&d->tag_list, qPrintable(tag));
|
||||
taglist_add_tag(d->tags, qPrintable(tag));
|
||||
}
|
||||
if (d->rating != rating) {
|
||||
diveChanged = true;
|
||||
|
|
|
@ -294,7 +294,7 @@ QVariant DiveTripModelBase::diveData(const struct dive *d, int column, int role)
|
|||
case MobileListModel::SumWeightRole: return formatSumWeight(d);
|
||||
case MobileListModel::DiveGuideRole: return QString(d->diveguide);
|
||||
case MobileListModel::BuddyRole: return QString(d->buddy);
|
||||
case MobileListModel::TagsRole: return QString::fromStdString(taglist_get_tagstring(d->tag_list));
|
||||
case MobileListModel::TagsRole: return QString::fromStdString(taglist_get_tagstring(d->tags));
|
||||
case MobileListModel::NotesRole: return formatNotes(d);
|
||||
case MobileListModel::GpsRole: return formatDiveGPS(d);
|
||||
case MobileListModel::GpsDecimalRole: return format_gps_decimal(d);
|
||||
|
@ -347,7 +347,7 @@ QVariant DiveTripModelBase::diveData(const struct dive *d, int column, int role)
|
|||
else
|
||||
return d->maxcns;
|
||||
case TAGS:
|
||||
return QString::fromStdString(taglist_get_tagstring(d->tag_list));
|
||||
return QString::fromStdString(taglist_get_tagstring(d->tags));
|
||||
case PHOTOS:
|
||||
break;
|
||||
case COUNTRY:
|
||||
|
@ -1767,8 +1767,8 @@ bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) c
|
|||
case MAXCNS:
|
||||
return lessThanHelper(d1->maxcns - d2->maxcns, row_diff);
|
||||
case TAGS: {
|
||||
std::string s1 = taglist_get_tagstring(d1->tag_list);
|
||||
std::string s2 = taglist_get_tagstring(d2->tag_list);
|
||||
std::string s1 = taglist_get_tagstring(d1->tags);
|
||||
std::string s2 = taglist_get_tagstring(d2->tags);
|
||||
int diff = strCmp(s1, s2);
|
||||
return lessThanHelper(diff, row_diff);
|
||||
}
|
||||
|
|
|
@ -691,7 +691,7 @@ static void smtk_parse_relations(MdbHandle *mdb, struct dive *dive, char *dive_i
|
|||
if (str.empty())
|
||||
continue;
|
||||
if (tag)
|
||||
taglist_add_tag(&dive->tag_list, str.c_str());
|
||||
taglist_add_tag(dive->tags, str);
|
||||
else
|
||||
concat(tmp, ", ", str);
|
||||
if (str.find("SCR") != std::string::npos)
|
||||
|
@ -717,7 +717,7 @@ static void smtk_parse_other(struct dive *dive, const std::vector<std::string> &
|
|||
const std::string &str = list[i];
|
||||
if (!str.empty()) {
|
||||
if (tag)
|
||||
taglist_add_tag(&dive->tag_list, str.c_str());
|
||||
taglist_add_tag(dive->tags, str);
|
||||
else
|
||||
concat(&dive->notes, "\n", format_string_std("Smartrak %s: %s", data_name, str.c_str()));
|
||||
}
|
||||
|
|
|
@ -1501,8 +1501,8 @@ struct DiveGuideVariable : public StatsVariableTemplate<StatsVariable::Type::Dis
|
|||
struct TagBinner : public StringBinner<TagBinner, StringBin> {
|
||||
std::vector<QString> to_bin_values(const dive *d) const {
|
||||
std::vector<QString> tags;
|
||||
for (const tag_entry *tag = d->tag_list; tag; tag = tag->next)
|
||||
tags.push_back(QString::fromStdString(tag->tag->name).trimmed());
|
||||
for (const divetag *tag: d->tags)
|
||||
tags.push_back(QString::fromStdString(tag->name).trimmed());
|
||||
return tags;
|
||||
}
|
||||
};
|
||||
|
@ -1513,7 +1513,7 @@ struct TagVariable : public StatsVariableTemplate<StatsVariable::Type::Discrete>
|
|||
return StatsTranslations::tr("Tags");
|
||||
}
|
||||
QString diveCategories(const dive *d) const override {
|
||||
return QString::fromStdString(taglist_get_tagstring(d->tag_list));
|
||||
return QString::fromStdString(taglist_get_tagstring(d->tags));
|
||||
}
|
||||
std::vector<const StatsBinner *> binners() const override {
|
||||
return { &tag_binner };
|
||||
|
|
|
@ -15,29 +15,29 @@ void TestTagList::cleanupTestCase()
|
|||
|
||||
void TestTagList::testGetTagstringNoTags()
|
||||
{
|
||||
struct tag_entry *tag_list = NULL;
|
||||
std::string tagstring = taglist_get_tagstring(tag_list);
|
||||
tag_list tags;
|
||||
std::string tagstring = taglist_get_tagstring(tags);
|
||||
QVERIFY(tagstring.empty());
|
||||
}
|
||||
|
||||
void TestTagList::testGetTagstringSingleTag()
|
||||
{
|
||||
struct tag_entry *tag_list = NULL;
|
||||
taglist_add_tag(&tag_list, "A new tag");
|
||||
std::string tagstring = taglist_get_tagstring(tag_list);
|
||||
tag_list tags;
|
||||
taglist_add_tag(tags, "A new tag");
|
||||
std::string tagstring = taglist_get_tagstring(tags);
|
||||
QCOMPARE(QString::fromStdString(tagstring), QString::fromUtf8("A new tag"));
|
||||
}
|
||||
|
||||
void TestTagList::testGetTagstringMultipleTags()
|
||||
{
|
||||
struct tag_entry *tag_list = NULL;
|
||||
taglist_add_tag(&tag_list, "A new tag");
|
||||
taglist_add_tag(&tag_list, "A new tag 1");
|
||||
taglist_add_tag(&tag_list, "A new tag 2");
|
||||
taglist_add_tag(&tag_list, "A new tag 3");
|
||||
taglist_add_tag(&tag_list, "A new tag 4");
|
||||
taglist_add_tag(&tag_list, "A new tag 5");
|
||||
std::string tagstring = taglist_get_tagstring(tag_list);
|
||||
tag_list tags;
|
||||
taglist_add_tag(tags, "A new tag");
|
||||
taglist_add_tag(tags, "A new tag 1");
|
||||
taglist_add_tag(tags, "A new tag 2");
|
||||
taglist_add_tag(tags, "A new tag 3");
|
||||
taglist_add_tag(tags, "A new tag 4");
|
||||
taglist_add_tag(tags, "A new tag 5");
|
||||
std::string tagstring = taglist_get_tagstring(tags);
|
||||
QCOMPARE(QString::fromStdString(tagstring),
|
||||
QString::fromUtf8(
|
||||
"A new tag, "
|
||||
|
@ -50,11 +50,11 @@ void TestTagList::testGetTagstringMultipleTags()
|
|||
|
||||
void TestTagList::testGetTagstringWithAnEmptyTag()
|
||||
{
|
||||
struct tag_entry *tag_list = NULL;
|
||||
taglist_add_tag(&tag_list, "A new tag");
|
||||
taglist_add_tag(&tag_list, "A new tag 1");
|
||||
taglist_add_tag(&tag_list, "");
|
||||
std::string tagstring = taglist_get_tagstring(tag_list);
|
||||
tag_list tags;
|
||||
taglist_add_tag(tags, "A new tag");
|
||||
taglist_add_tag(tags, "A new tag 1");
|
||||
taglist_add_tag(tags, "");
|
||||
std::string tagstring = taglist_get_tagstring(tags);
|
||||
QCOMPARE(QString::fromStdString(tagstring),
|
||||
QString::fromUtf8(
|
||||
"A new tag, "
|
||||
|
@ -63,11 +63,40 @@ void TestTagList::testGetTagstringWithAnEmptyTag()
|
|||
|
||||
void TestTagList::testGetTagstringEmptyTagOnly()
|
||||
{
|
||||
struct tag_entry *tag_list = NULL;
|
||||
taglist_add_tag(&tag_list, "");
|
||||
std::string tagstring = taglist_get_tagstring(tag_list);
|
||||
tag_list tags;
|
||||
taglist_add_tag(tags, "");
|
||||
std::string tagstring = taglist_get_tagstring(tags);
|
||||
QCOMPARE(QString::fromStdString(tagstring),
|
||||
QString::fromUtf8(""));
|
||||
}
|
||||
|
||||
void TestTagList::testMergeTags()
|
||||
{
|
||||
tag_list tags1, tags2;
|
||||
taglist_add_tag(tags1, "A new tag");
|
||||
taglist_add_tag(tags1, "A new tag 6");
|
||||
taglist_add_tag(tags1, "A new tag 1");
|
||||
taglist_add_tag(tags1, "A new tag 2");
|
||||
taglist_add_tag(tags1, "");
|
||||
taglist_add_tag(tags1, "A new tag 2");
|
||||
taglist_add_tag(tags1, "A new tag 3");
|
||||
taglist_add_tag(tags1, "A new tag");
|
||||
taglist_add_tag(tags2, "");
|
||||
taglist_add_tag(tags2, "A new tag 1");
|
||||
taglist_add_tag(tags2, "A new tag 4");
|
||||
taglist_add_tag(tags2, "A new tag 2");
|
||||
taglist_add_tag(tags2, "A new tag 5");
|
||||
tag_list tags3 = taglist_merge(tags1, tags2);
|
||||
std::string tagstring = taglist_get_tagstring(tags3);
|
||||
QCOMPARE(QString::fromStdString(tagstring),
|
||||
QString::fromUtf8(
|
||||
"A new tag, "
|
||||
"A new tag 1, "
|
||||
"A new tag 2, "
|
||||
"A new tag 3, "
|
||||
"A new tag 4, "
|
||||
"A new tag 5, "
|
||||
"A new tag 6"));
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestTagList)
|
||||
|
|
|
@ -15,6 +15,7 @@ private slots:
|
|||
void testGetTagstringMultipleTags();
|
||||
void testGetTagstringWithAnEmptyTag();
|
||||
void testGetTagstringEmptyTagOnly();
|
||||
void testMergeTags();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue