core: convert weightsystem_t and weightsystem_table to C++

As for cylinders, this had to be done simultaneously,

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-29 07:03:03 +02:00 committed by bstoeger
parent 28520da655
commit 640ecb345b
28 changed files with 137 additions and 247 deletions

View file

@ -13,6 +13,7 @@
#include "core/divesite.h"
#include "core/picture.h"
#include "core/pref.h"
#include "core/range.h"
#include "core/sample.h"
#include "core/selection.h"
#include "core/taxonomy.h"
@ -155,11 +156,6 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
QString viz = star.repeated(dive->visibility);
QString rating = star.repeated(dive->rating);
int i;
int qty_cyl;
int qty_weight;
double total_weight;
if (need_pagebreak) {
if (plain)
put_format(&buf, "\\vfill\\eject\n");
@ -204,7 +200,7 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
// Print cylinder data
put_format(&buf, "\n%% Gas use information:\n");
qty_cyl = 0;
int qty_cyl = 0;
for (int i = 0; i < static_cast<int>(dive->cylinders.size()); i++){
const cylinder_t &cyl = dive->cylinders[i];
if (is_cylinder_used(dive, i) || (prefs.include_unused_tanks && !cyl.type.description.empty())){
@ -235,11 +231,10 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall
//Code block prints all weights listed in dive.
put_format(&buf, "\n%% Weighting information:\n");
qty_weight = 0;
total_weight = 0;
for (i = 0; i < dive->weightsystems.nr; i++) {
weightsystem_t w = dive->weightsystems.weightsystems[i];
put_format(&buf, "\\def\\%sweight%ctype{%s}\n", ssrf, 'a' + i, w.description);
int qty_weight = 0;
double total_weight = 0;
for (auto [i, w]: enumerated_range(dive->weightsystems)) {
put_format(&buf, "\\def\\%sweight%ctype{%s}\n", ssrf, 'a' + i, w.description.c_str());
put_format(&buf, "\\def\\%sweight%camt{%.3f\\%sweightunit}\n", ssrf, 'a' + i, get_weight_units(w.weight.grams, NULL, &unit), ssrf);
qty_weight += 1;
total_weight += get_weight_units(w.weight.grams, NULL, &unit);

View file

@ -6,6 +6,7 @@
#include "core/event.h"
#include "core/fulltext.h"
#include "core/qthelper.h" // for copy_qstring
#include "core/range.h"
#include "core/sample.h"
#include "core/selection.h"
#include "core/subsurface-string.h"
@ -629,7 +630,6 @@ static void swapCandQString(QString &q, char *&c)
PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dIn),
tags(nullptr)
{
memset(&weightsystems, 0, sizeof(weightsystems));
if (what.notes)
notes = data->notes;
if (what.diveguide)
@ -686,7 +686,7 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI
}
}
if (what.weights)
copy_weights(&data->weightsystems, &weightsystems);
weightsystems = data->weightsystems;
if (what.number)
number = data->number;
if (what.when)
@ -696,8 +696,6 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI
PasteState::~PasteState()
{
taglist_free(tags);
clear_weightsystem_table(&weightsystems);
free(weightsystems.weightsystems);
}
void PasteState::swap(dive_components what)
@ -952,10 +950,10 @@ bool AddWeight::workToBeDone()
void AddWeight::undo()
{
for (dive *d: dives) {
if (d->weightsystems.nr <= 0)
if (d->weightsystems.empty())
continue;
remove_weightsystem(d, d->weightsystems.nr - 1);
emit diveListNotifier.weightRemoved(d, d->weightsystems.nr);
d->weightsystems.pop_back();
emit diveListNotifier.weightRemoved(d, d->weightsystems.size());
invalidate_dive_cache(d); // Ensure that dive is written in git_save()
}
}
@ -963,31 +961,26 @@ void AddWeight::undo()
void AddWeight::redo()
{
for (dive *d: dives) {
add_cloned_weightsystem(&d->weightsystems, empty_weightsystem);
emit diveListNotifier.weightAdded(d, d->weightsystems.nr - 1);
d->weightsystems.emplace_back();
emit diveListNotifier.weightAdded(d, d->weightsystems.size() - 1);
invalidate_dive_cache(d); // Ensure that dive is written in git_save()
}
}
static int find_weightsystem_index(const struct dive *d, weightsystem_t ws)
static int find_weightsystem_index(const struct dive *d, const weightsystem_t &ws)
{
for (int idx = 0; idx < d->weightsystems.nr; ++idx) {
if (same_weightsystem(d->weightsystems.weightsystems[idx], ws))
return idx;
}
return -1;
return index_of_if(d->weightsystems, [&ws](auto &ws2) { return same_weightsystem(ws2, ws); });
}
EditWeightBase::EditWeightBase(int index, bool currentDiveOnly) :
EditDivesBase(currentDiveOnly),
ws(empty_weightsystem)
EditDivesBase(currentDiveOnly)
{
// Get the old weightsystem, bail if index is invalid
if (!current || index < 0 || index >= current->weightsystems.nr) {
if (!current || index < 0 || static_cast<size_t>(index) >= current->weightsystems.size()) {
dives.clear();
return;
}
ws = clone_weightsystem(current->weightsystems.weightsystems[index]);
ws = current->weightsystems[index];
// Deleting a weightsystem from multiple dives is semantically ill-defined.
// What we will do is trying to delete the same weightsystem if it exists.
@ -1013,7 +1006,6 @@ EditWeightBase::EditWeightBase(int index, bool currentDiveOnly) :
EditWeightBase::~EditWeightBase()
{
free_weightsystem(ws);
}
bool EditWeightBase::workToBeDone()
@ -1035,7 +1027,7 @@ RemoveWeight::RemoveWeight(int index, bool currentDiveOnly) :
void RemoveWeight::undo()
{
for (size_t i = 0; i < dives.size(); ++i) {
add_to_weightsystem_table(&dives[i]->weightsystems, indices[i], clone_weightsystem(ws));
add_to_weightsystem_table(&dives[i]->weightsystems, indices[i], ws);
emit diveListNotifier.weightAdded(dives[i], indices[i]);
invalidate_dive_cache(dives[i]); // Ensure that dive is written in git_save()
}
@ -1052,8 +1044,7 @@ void RemoveWeight::redo()
// ***** Edit Weight *****
EditWeight::EditWeight(int index, weightsystem_t wsIn, bool currentDiveOnly) :
EditWeightBase(index, currentDiveOnly),
new_ws(empty_weightsystem)
EditWeightBase(index, currentDiveOnly)
{
if (dives.empty())
return;
@ -1065,15 +1056,13 @@ EditWeight::EditWeight(int index, weightsystem_t wsIn, bool currentDiveOnly) :
setText(QStringLiteral("%1 [%2]").arg(Command::Base::tr("Edit weight (%n dive(s))", "", num_dives)).arg(getListOfDives(dives)));
// Try to untranslate the weightsystem name
new_ws = clone_weightsystem(wsIn);
QString vString(new_ws.description);
new_ws = std::move(wsIn);
QString vString = QString::fromStdString(new_ws.description);
auto it = std::find_if(ws_info_table.begin(), ws_info_table.end(),
[&vString](const ws_info &info)
{ return gettextFromC::tr(info.name.c_str()) == vString; });
if (it != ws_info_table.end()) {
free_weightsystem(new_ws);
new_ws.description = strdup(it->name.c_str());
}
if (it != ws_info_table.end())
new_ws.description = it->name;
// If that doesn't change anything, do nothing
if (same_weightsystem(ws, new_ws)) {
@ -1084,7 +1073,6 @@ EditWeight::EditWeight(int index, weightsystem_t wsIn, bool currentDiveOnly) :
EditWeight::~EditWeight()
{
free_weightsystem(new_ws);
}
void EditWeight::redo()

View file

@ -300,8 +300,8 @@ struct PasteState {
int surge;
int chill;
tag_entry *tags;
struct cylinder_table cylinders;
struct weightsystem_table weightsystems;
cylinder_table cylinders;
weightsystem_table weightsystems;
int number;
timestamp_t when;

View file

@ -631,7 +631,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 };
add_cloned_weightsystem(&dt_dive->weightsystems, ws);
dt_dive->weightsystems.push_back(std::move(ws));
}
/*

View file

@ -176,8 +176,7 @@ static void free_dive_structures(struct dive *d)
/* free tags, additional dive computers, and pictures */
taglist_free(d->tag_list);
d->cylinders.clear();
clear_weightsystem_table(&d->weightsystems);
free(d->weightsystems.weightsystems);
d->weightsystems.clear();
clear_picture_table(&d->pictures);
free(d->pictures.pictures);
}
@ -204,7 +203,6 @@ void copy_dive(const struct dive *s, struct dive *d)
* relevant components that are referenced through pointers,
* so all the strings and the structured lists */
*d = *s;
memset(&d->weightsystems, 0, sizeof(d->weightsystems));
memset(&d->pictures, 0, sizeof(d->pictures));
d->full_text = NULL;
invalidate_dive_cache(d);
@ -212,7 +210,6 @@ void copy_dive(const struct dive *s, struct dive *d)
d->diveguide = copy_string(s->diveguide);
d->notes = copy_string(s->notes);
d->suit = copy_string(s->suit);
copy_weights(&s->weightsystems, &d->weightsystems);
copy_pictures(&s->pictures, &d->pictures);
d->tag_list = taglist_copy(s->tag_list);
}
@ -260,7 +257,7 @@ void selective_copy_dive(const struct dive *s, struct dive *d, struct dive_compo
if (what.cylinders)
copy_cylinder_types(s, d);
if (what.weights)
copy_weights(&s->weightsystems, &d->weightsystems);
d->weightsystems = s->weightsystems;
if (what.number)
d->number = s->number;
if (what.when)
@ -289,11 +286,6 @@ void copy_events_until(const struct dive *sd, struct dive *dd, int dcNr, int tim
}
}
int nr_weightsystems(const struct dive *dive)
{
return dive->weightsystems.nr;
}
void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only)
{
if (!s || !d)
@ -1116,8 +1108,6 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer &dc)
struct dive *fixup_dive(struct dive *dive)
{
int i;
sanitize_cylinder_info(dive);
dive->maxcns = dive->cns;
@ -1146,10 +1136,8 @@ struct dive *fixup_dive(struct dive *dive)
cyl.end.mbar = 0;
}
update_cylinder_related_info(dive);
for (i = 0; i < dive->weightsystems.nr; i++) {
const weightsystem_t &ws = dive->weightsystems.weightsystems[i];
for (auto &ws: dive->weightsystems)
add_weightsystem_description(ws);
}
/* we should always have a uniq ID as that gets assigned during dive creation,
* but we want to make sure... */
if (!dive->id)
@ -1769,26 +1757,20 @@ static void merge_cylinders(struct dive *res, const struct dive *a, const struct
}
/* Check whether a weightsystem table contains a given weightsystem */
static bool has_weightsystem(const struct weightsystem_table *t, const weightsystem_t w)
static bool has_weightsystem(const weightsystem_table &t, const weightsystem_t &w)
{
int i;
for (i = 0; i < t->nr; i++) {
if (same_weightsystem(w, t->weightsystems[i]))
return true;
}
return false;
return any_of(t.begin(), t.end(), [&w] (auto &w2) { return same_weightsystem(w, w2); });
}
static void merge_equipment(struct dive *res, const struct dive *a, const struct dive *b)
{
int i;
for (i = 0; i < a->weightsystems.nr; i++) {
if (!has_weightsystem(&res->weightsystems, a->weightsystems.weightsystems[i]))
add_cloned_weightsystem(&res->weightsystems, a->weightsystems.weightsystems[i]);
for (auto &ws: a->weightsystems) {
if (!has_weightsystem(res->weightsystems, ws))
res->weightsystems.push_back(ws);
}
for (i = 0; i < b->weightsystems.nr; i++) {
if (!has_weightsystem(&res->weightsystems, b->weightsystems.weightsystems[i]))
add_cloned_weightsystem(&res->weightsystems, b->weightsystems.weightsystems[i]);
for (auto &ws: b->weightsystems) {
if (!has_weightsystem(res->weightsystems, ws))
res->weightsystems.push_back(ws);
}
}

View file

@ -6,7 +6,7 @@
#include "divemode.h"
#include "divecomputer.h"
#include "equipment.h" // TODO: remove
#include "equipment.h"
#include "picture.h" // TODO: remove
#include <string>
@ -30,8 +30,8 @@ struct dive {
struct dive_site *dive_site = nullptr;
char *notes = nullptr;
char *diveguide = nullptr, *buddy = nullptr;
struct cylinder_table cylinders;
struct weightsystem_table weightsystems = { };
cylinder_table cylinders;
weightsystem_table weightsystems;
char *suit = nullptr;
int number = 0;
int rating = 0;
@ -190,7 +190,6 @@ extern struct event create_gas_switch_event(struct dive *dive, struct divecomput
extern void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration);
extern int get_cylinder_index(const struct dive *dive, const struct event &ev);
extern struct gasmix get_gasmix_from_event(const struct dive *, const struct event &ev);
extern int nr_weightsystems(const struct dive *dive);
extern bool cylinder_with_sensor_sample(const struct dive *dive, int cylinder_id);
/* UI related protopypes */

View file

@ -64,11 +64,12 @@ void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2max_p)
int total_weight(const struct dive *dive)
{
int i, total_grams = 0;
int total_grams = 0;
if (dive)
for (i = 0; i < dive->weightsystems.nr; i++)
total_grams += dive->weightsystems.weightsystems[i].weight.grams;
if (dive) {
for (auto &ws: dive->weightsystems)
total_grams += ws.weight.grams;
}
return total_grams;
}

View file

@ -20,7 +20,6 @@
#include "pref.h"
#include "range.h"
#include "subsurface-string.h"
#include "table.h"
cylinder_t::cylinder_t() = default;
cylinder_t::~cylinder_t() = default;
@ -55,33 +54,13 @@ const cylinder_t &cylinder_table::operator[](size_t i) const
: surface_air_cylinder;
}
/* Warning: this has strange semantics for C-code! Not the weightsystem object
* is freed, but the data it references. The object itself is passed in by value.
* This is due to the fact how the table macros work.
*/
void free_weightsystem(weightsystem_t ws)
weightsystem_t::weightsystem_t() = default;
weightsystem_t::~weightsystem_t() = default;
weightsystem_t::weightsystem_t(weight_t w, std::string desc, bool auto_filled)
: weight(w), description(std::move(desc)), auto_filled(auto_filled)
{
free((void *)ws.description);
ws.description = NULL;
}
void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d)
{
clear_weightsystem_table(d);
for (int i = 0; i < s->nr; i++)
add_cloned_weightsystem(d, s->weightsystems[i]);
}
/* weightsystem table functions */
//static MAKE_GET_IDX(weightsystem_table, weightsystem_t, weightsystems)
static MAKE_GROW_TABLE(weightsystem_table, weightsystem_t, weightsystems)
//static MAKE_GET_INSERTION_INDEX(weightsystem_table, weightsystem_t, weightsystems, weightsystem_less_than)
MAKE_ADD_TO(weightsystem_table, weightsystem_t, weightsystems)
static MAKE_REMOVE_FROM(weightsystem_table, weightsystems)
//MAKE_SORT(weightsystem_table, weightsystem_t, weightsystems, comp_weightsystems)
//MAKE_REMOVE(weightsystem_table, weightsystem_t, weightsystem)
MAKE_CLEAR_TABLE(weightsystem_table, weightsystems, weightsystem)
const char *cylinderuse_text[NUM_GAS_USE] = {
QT_TRANSLATE_NOOP("gettextFromC", "OC-gas"), QT_TRANSLATE_NOOP("gettextFromC", "diluent"), QT_TRANSLATE_NOOP("gettextFromC", "oxygen"), QT_TRANSLATE_NOOP("gettextFromC", "not used")
};
@ -166,7 +145,7 @@ void add_cylinder_description(const cylinder_type_t &type)
void add_weightsystem_description(const weightsystem_t &weightsystem)
{
if (empty_string(weightsystem.description))
if (weightsystem.description.empty())
return;
auto it = std::find_if(ws_info_table.begin(), ws_info_table.end(),
@ -188,26 +167,6 @@ weight_t get_weightsystem_weight(const std::string &name)
return it != ws_info_table.end() ? it->weight : weight_t();
}
weightsystem_t clone_weightsystem(weightsystem_t ws)
{
weightsystem_t res = { ws.weight, copy_string(ws.description), ws.auto_filled };
return res;
}
/* Add a clone of a weightsystem to the end of a weightsystem table.
* Cloned means that the description-string is copied. */
void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws)
{
add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws));
}
/* Add a clone of a weightsystem to the end of a weightsystem table.
* Cloned means that the description-string is copied. */
void add_cloned_weightsystem_at(struct weightsystem_table *t, weightsystem_t ws)
{
add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws));
}
void add_cylinder(struct cylinder_table *t, int idx, cylinder_t cyl)
{
t->insert(t->begin() + idx, std::move(cyl));
@ -216,7 +175,7 @@ void add_cylinder(struct cylinder_table *t, int idx, cylinder_t cyl)
bool same_weightsystem(weightsystem_t w1, weightsystem_t w2)
{
return w1.weight.grams == w2.weight.grams &&
same_string(w1.description, w2.description);
w1.description == w2.description;
}
void get_gas_string(struct gasmix gasmix, char *text, int len)
@ -351,16 +310,20 @@ void remove_cylinder(struct dive *dive, int idx)
void remove_weightsystem(struct dive *dive, int idx)
{
remove_from_weightsystem_table(&dive->weightsystems, idx);
dive->weightsystems.erase(dive->weightsystems.begin() + idx);
}
void add_to_weightsystem_table(weightsystem_table *table, int idx, weightsystem_t ws)
{
idx = std::clamp(idx, 0, static_cast<int>(table->size()));
table->insert(table->begin() + idx, std::move(ws));
}
// ws is cloned.
void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws)
{
if (idx < 0 || idx >= dive->weightsystems.nr)
if (idx < 0 || static_cast<size_t>(idx) >= dive->weightsystems.size())
return;
free_weightsystem(dive->weightsystems.weightsystems[idx]);
dive->weightsystems.weightsystems[idx] = clone_weightsystem(ws);
dive->weightsystems[idx] = std::move(ws);
}
/* when planning a dive we need to make sure that all cylinders have a sane depth assigned

View file

@ -54,30 +54,22 @@ struct cylinder_table : public std::vector<cylinder_t> {
struct weightsystem_t
{
weight_t weight;
const char *description; /* "integrated", "belt", "ankle" */
bool auto_filled; /* weight was automatically derived from the type */
};
std::string description; /* "integrated", "belt", "ankle" */
bool auto_filled = false; /* weight was automatically derived from the type */
static const weightsystem_t empty_weightsystem = { { 0 }, 0, false };
weightsystem_t();
weightsystem_t(weight_t w, std::string desc, bool auto_filled);
~weightsystem_t();
};
/* Table of weightsystems. Attention: this stores weightsystems,
* *not* pointers * to weightsystems. This has two crucial
* consequences:
* 1) Pointers to weightsystems are not stable. They may be
* invalidated if the table is reallocated.
* 2) add_to_weightsystem_table(), etc. takes ownership of the
* weightsystem. Notably of the description string */
struct weightsystem_table {
int nr, allocated;
weightsystem_t *weightsystems;
};
* *not* pointers * to weightsystems. Therefore pointers to
* weightsystems are *not* stable.
*/
using weightsystem_table = std::vector<weightsystem_t>;
extern enum cylinderuse cylinderuse_from_text(const char *text);
extern void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d);
extern weightsystem_t clone_weightsystem(weightsystem_t ws);
extern void free_weightsystem(weightsystem_t ws);
extern void copy_cylinder_types(const struct dive *s, struct dive *d);
extern void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws);
extern cylinder_t *add_empty_cylinder(struct cylinder_table *t);
extern cylinder_t *get_cylinder(struct dive *d, int idx);
extern const cylinder_t *get_cylinder(const struct dive *d, int idx);
@ -99,8 +91,7 @@ extern void dump_cylinders(struct dive *dive, bool verbose);
#endif
/* Weightsystem table functions */
extern void clear_weightsystem_table(struct weightsystem_table *);
extern void add_to_weightsystem_table(struct weightsystem_table *, int idx, weightsystem_t ws);
extern void add_to_weightsystem_table(weightsystem_table *, int idx, weightsystem_t ws);
/* Cylinder table functions */
extern void add_cylinder(struct cylinder_table *, int idx, cylinder_t cyl);

View file

@ -848,8 +848,8 @@ static bool has_locations(const filter_constraint &c, const struct dive *d)
static bool has_weight_type(const filter_constraint &c, const struct dive *d)
{
QStringList weightsystemTypes;
for (int i = 0; i < d->weightsystems.nr; ++i)
weightsystemTypes.push_back(d->weightsystems.weightsystems[i].description);
for (auto &ws: d->weightsystems)
weightsystemTypes.push_back(QString::fromStdString(ws.description));
return check(c, weightsystemTypes);
}

View file

@ -127,10 +127,8 @@ static std::vector<QString> getWords(const dive *d)
tokenize(QString::fromStdString(tag->tag->name), res);
for (auto &cyl: d->cylinders)
tokenize(QString::fromStdString(cyl.type.description), res);
for (int i = 0; i < d->weightsystems.nr; ++i) {
const weightsystem_t &ws = d->weightsystems.weightsystems[i];
tokenize(QString(ws.description), res);
}
for (auto &ws: d->weightsystems)
tokenize(QString::fromStdString(ws.description), res);
// TODO: We should tokenize all dive-sites and trips first and then
// take the tokens from a cache.
if (d->dive_site) {

View file

@ -301,7 +301,7 @@ static int divinglog_dive(void *param, int, char **data, char **)
if (data[10]) {
weightsystem_t ws = { { atoi(data[10]) * 1000 }, translate("gettextFromC", "unknown"), false };
add_cloned_weightsystem(&state->cur_dive->weightsystems, ws);
state->cur_dive->weightsystems.push_back(std::move(ws));
}
if (data[11])

View file

@ -457,7 +457,7 @@ static void parse_weightsystem_keyvalue(void *_ws, const char *key, const std::s
return;
}
if (!strcmp(key, "description")) {
ws->description = strdup(value.c_str());
ws->description = value;
return;
}
report_error("Unknown weightsystem key/value pair (%s/%s)", key, value.c_str());
@ -465,7 +465,7 @@ static void parse_weightsystem_keyvalue(void *_ws, const char *key, const std::s
static void parse_dive_weightsystem(char *line, struct git_parser_state *state)
{
weightsystem_t ws = empty_weightsystem;
weightsystem_t ws;
for (;;) {
char c;
@ -476,7 +476,7 @@ static void parse_dive_weightsystem(char *line, struct git_parser_state *state)
line = parse_keyvalue_entry(parse_weightsystem_keyvalue, &ws, line, state);
}
add_to_weightsystem_table(&state->active_dive->weightsystems, state->active_dive->weightsystems.nr, ws);
state->active_dive->weightsystems.push_back(std::move(ws));
}
static int match_action(char *line, void *data,
@ -1688,7 +1688,7 @@ static int parse_dive_entry(struct git_parser_state *state, const git_tree_entry
return report_error("Unable to read dive file");
if (*suffix)
state->active_dive->number = atoi(suffix + 1);
clear_weightsystem_table(&state->active_dive->weightsystems);
state->active_dive->weightsystems.clear();
state->o2pressure_sensor = 1;
for_each_line(blob, dive_parser, state);
git_blob_free(blob);

View file

@ -1230,8 +1230,8 @@ static void gps_picture_location(const char *buffer, struct picture *pic)
static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, struct parser_state *state)
{
cylinder_t *cyl = !dive->cylinders.empty() ? &dive->cylinders.back() : NULL;
weightsystem_t *ws = dive->weightsystems.nr > 0 ?
&dive->weightsystems.weightsystems[dive->weightsystems.nr - 1] : NULL;
weightsystem_t *ws = !dive->weightsystems.empty() > 0 ?
&dive->weightsystems.back() : NULL;
pressure_t p;
weight_t w;
start_match("dive", name, buf);
@ -1339,15 +1339,15 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
if (MATCH_STATE("airpressure.dive", pressure, &dive->surface_pressure))
return;
if (ws) {
if (MATCH("description.weightsystem", utf8_string, (char **)&ws->description))
if (MATCH("description.weightsystem", utf8_string_std, &ws->description))
return;
if (MATCH_STATE("weight.weightsystem", weight, &ws->weight))
return;
}
if (MATCH_STATE("weight", weight, &w)) {
weightsystem_t ws = empty_weightsystem;
weightsystem_t ws;
ws.weight = w;
add_cloned_weightsystem(&dive->weightsystems, ws);
dive->weightsystems.push_back(std::move(ws));
return;
}
if (cyl) {

View file

@ -323,7 +323,7 @@ void cylinder_end(struct parser_state *state)
void ws_start(struct parser_state *state)
{
add_cloned_weightsystem(&state->cur_dive->weightsystems, empty_weightsystem);
state->cur_dive->weightsystems.emplace_back();
}
void ws_end(struct parser_state *state)

View file

@ -162,19 +162,14 @@ static void save_cylinder_info(struct membuffer *b, struct dive *dive)
}
}
static void save_weightsystem_info(struct membuffer *b, struct dive *dive)
static void save_weightsystem_info(struct membuffer *b, const struct dive *dive)
{
int i, nr;
nr = nr_weightsystems(dive);
for (i = 0; i < nr; i++) {
weightsystem_t ws = dive->weightsystems.weightsystems[i];
for (auto &ws: dive->weightsystems) {
int grams = ws.weight.grams;
const char *description = ws.description;
put_string(b, "weightsystem");
put_milli(b, " weight=", grams, "kg");
show_utf8(b, " description=", description, "");
show_utf8(b, " description=", ws.description.c_str(), "");
put_string(b, "\n");
}
}

View file

@ -96,24 +96,18 @@ static void put_HTML_bookmarks(struct membuffer *b, const struct dive *dive)
static void put_weightsystem_HTML(struct membuffer *b, const struct dive *dive)
{
int i, nr;
nr = nr_weightsystems(dive);
put_string(b, "\"Weights\":[");
const char *separator = "";
for (i = 0; i < nr; i++) {
weightsystem_t ws = dive->weightsystems.weightsystems[i];
for (auto &ws: dive->weightsystems) {
int grams = ws.weight.grams;
const char *description = ws.description;
put_string(b, separator);
separator = ", ";
put_string(b, "{");
put_HTML_weight_units(b, grams, "\"weight\":\"", "\",");
write_attribute(b, "description", description, " ");
write_attribute(b, "description", ws.description.c_str(), " ");
put_string(b, "}");
}
put_string(b, "],");

View file

@ -197,20 +197,14 @@ static void save_cylinder_info(struct membuffer *b, struct dive *dive)
}
}
static void save_weightsystem_info(struct membuffer *b, struct dive *dive)
static void save_weightsystem_info(struct membuffer *b, const struct dive *dive)
{
int i, nr;
nr = nr_weightsystems(dive);
for (i = 0; i < nr; i++) {
weightsystem_t ws = dive->weightsystems.weightsystems[i];
for (auto &ws: dive->weightsystems) {
int grams = ws.weight.grams;
const char *description = ws.description;
put_format(b, " <weightsystem");
put_milli(b, " weight='", grams, " kg'");
show_utf8(b, description, " description='", "'", 1);
show_utf8(b, ws.description.c_str(), " description='", "'", 1);
put_format(b, " />\n");
}
}

View file

@ -195,21 +195,19 @@ QString formatSumWeight(const dive *d)
return get_weight_string(weight_t { total_weight(d) }, true);
}
static QString getFormattedWeight(const struct dive *dive, int idx)
static QString getFormattedWeight(const weightsystem_t &weight)
{
const weightsystem_t *weight = &dive->weightsystems.weightsystems[idx];
if (!weight->description)
if (weight.description.empty())
return QString();
QString fmt = QString(weight->description);
fmt += ", " + get_weight_string(weight->weight, true);
return fmt;
return QString::fromStdString(weight.description) +
", " + get_weight_string(weight.weight, true);
}
QString formatWeightList(const dive *d)
{
QString weights;
for (int i = 0; i < d->weightsystems.nr; i++) {
QString w = getFormattedWeight(d, i);
for (auto &ws: d->weightsystems) {
QString w = getFormattedWeight(ws);
if (w.isEmpty())
continue;
weights += w + "; ";
@ -220,8 +218,8 @@ QString formatWeightList(const dive *d)
QStringList formatWeights(const dive *d)
{
QStringList weights;
for (int i = 0; i < d->weightsystems.nr; i++) {
QString w = getFormattedWeight(d, i);
for (auto &ws: d->weightsystems) {
QString w = getFormattedWeight(ws);
if (w.isEmpty())
continue;
weights << w;

View file

@ -745,9 +745,9 @@ static void parse_tag(struct dive *dive, std::string_view tag, std::string_view
} else if (tag == "altitude") {
uemis_get_index(val, dive->dcs[0].surface_pressure.mbar);
} else if (tag == "f32Weight") {
weightsystem_t ws = empty_weightsystem;
weightsystem_t ws;
uemis_get_weight(val, ws, dive->dcs[0].diveid);
add_cloned_weightsystem(&dive->weightsystems, ws);
dive->weightsystems.push_back(std::move(ws));
} else if (tag == "notes") {
uemis_add_string(val, &dive->notes, " ");
} else if (tag == "u8DiveSuit") {

View file

@ -335,10 +335,10 @@ void WSInfoDelegate::editorClosed(QWidget *, QAbstractItemDelegate::EndEditHint
void WSInfoDelegate::setModelData(QWidget *, QAbstractItemModel *, const QModelIndex &) const
{
WeightModel *mymodel = qobject_cast<WeightModel *>(currCombo.model);
QString weightName = currCombo.activeText;
weight_t weight = get_weightsystem_weight(qPrintable(weightName));
std::string weightName = currCombo.activeText.toStdString();
weight_t weight = get_weightsystem_weight(weightName.c_str());
mymodel->setTempWS(currCombo.currRow, weightsystem_t{ weight, copy_qstring(weightName), false });
mymodel->setTempWS(currCombo.currRow, weightsystem_t( weight, std::move(weightName), false ));
}
static QAbstractItemModel *createWSInfoModel(QWidget *parent)

View file

@ -356,12 +356,9 @@ void DiveComponentSelection::buttonClicked(QAbstractButton *button)
}
}
if (what->weights) {
int w;
text << tr("Weights:\n");
for (w = 0; w < current_dive->weightsystems.nr; w++) {
weightsystem_t ws = current_dive->weightsystems.weightsystems[w];
text << ws.description << ws.weight.grams / 1000 << "kg\n";
}
for (auto &ws: current_dive->weightsystems)
text << QString::fromStdString(ws.description) << ws.weight.grams / 1000 << "kg\n";
}
if (what->number)
text << tr("Dive number: ") << current_dive->number << "\n";

View file

@ -562,7 +562,7 @@ QVariant TemplateLayout::getValue(QString list, QString property, const State &s
} else if (property == "weights") {
return formatWeights(d);
} else if (property == "singleWeight") {
return d->weightsystems.nr <= 1;
return d->weightsystems.size() <= 1;
} else if (property == "suit") {
return d->suit;
} else if (property == "cylinderList") {

View file

@ -1228,11 +1228,11 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt
diveChanged = true;
// not sure what we'd do if there was more than one weight system
// defined - for now just ignore that case
if (d->weightsystems.nr == 0) {
weightsystem_t ws = { { parseWeightToGrams(weight) } , strdup(qPrintable(tr("weight"))), false };
add_to_weightsystem_table(&d->weightsystems, 0, ws); // takes ownership of the string
} else if (d->weightsystems.nr == 1) {
d->weightsystems.weightsystems[0].weight.grams = parseWeightToGrams(weight);
if (d->weightsystems.size() == 0) {
weightsystem_t ws = { { parseWeightToGrams(weight) } , tr("weight").toStdString(), false };
add_to_weightsystem_table(&d->weightsystems, 0, std::move(ws));
} else if (d->weightsystems.size() == 1) {
d->weightsystems[0].weight.grams = parseWeightToGrams(weight);
}
}
// start and end pressures

View file

@ -303,7 +303,7 @@ QVariant DiveTripModelBase::diveData(const struct dive *d, int column, int role)
case MobileListModel::CylinderRole: return formatGetCylinder(d).join(", ");
case MobileListModel::GetCylinderRole: return formatGetCylinder(d);
case MobileListModel::CylinderListRole: return formatFullCylinderList();
case MobileListModel::SingleWeightRole: return d->weightsystems.nr <= 1;
case MobileListModel::SingleWeightRole: return d->weightsystems.size() <= 1;
case MobileListModel::StartPressureRole: return formatStartPressure(d);
case MobileListModel::EndPressureRole: return formatEndPressure(d);
case MobileListModel::FirstGasRole: return formatFirstGas(d);

View file

@ -12,8 +12,7 @@
WeightModel::WeightModel(QObject *parent) : CleanerTableModel(parent),
d(nullptr),
tempRow(-1),
tempWS(empty_weightsystem)
tempRow(-1)
{
//enum Column {REMOVE, TYPE, WEIGHT};
setHeaderDataStrings(QStringList() << tr("") << tr("Type") << tr("Weight"));
@ -26,11 +25,11 @@ WeightModel::WeightModel(QObject *parent) : CleanerTableModel(parent),
weightsystem_t WeightModel::weightSystemAt(const QModelIndex &index) const
{
int row = index.row();
if (row < 0 || row >= d->weightsystems.nr) {
qWarning("WeightModel: Accessing invalid weightsystem %d (of %d)", row, d->weightsystems.nr);
return empty_weightsystem;
if (row < 0 || static_cast<size_t>(row) >= d->weightsystems.size()) {
qWarning("WeightModel: Accessing invalid weightsystem %d (of %d)", row, static_cast<int>(d->weightsystems.size()));
return weightsystem_t();
}
return d->weightsystems.weightsystems[index.row()];
return d->weightsystems[index.row()];
}
void WeightModel::clear()
@ -40,7 +39,7 @@ void WeightModel::clear()
QVariant WeightModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() >= d->weightsystems.nr)
if (!index.isValid() || static_cast<size_t>(index.row()) >= d->weightsystems.size())
return QVariant();
weightsystem_t ws = index.row() == tempRow ? tempWS : weightSystemAt(index);
@ -54,7 +53,7 @@ QVariant WeightModel::data(const QModelIndex &index, int role) const
case Qt::EditRole:
switch (index.column()) {
case TYPE:
return gettextFromC::tr(ws.description);
return gettextFromC::tr(ws.description.c_str());
case WEIGHT:
return get_weight_string(ws.weight, true);
}
@ -78,20 +77,16 @@ QVariant WeightModel::data(const QModelIndex &index, int role) const
// Ownership of passed in weight system will be taken. Caller must not use it any longer.
void WeightModel::setTempWS(int row, weightsystem_t ws)
{
if (!d || row < 0 || row >= d->weightsystems.nr) { // Sanity check: row must exist
free_weightsystem(ws);
if (!d || row < 0 || static_cast<size_t>(row) >= d->weightsystems.size()) // Sanity check: row must exist
return;
}
clearTempWS(); // Shouldn't be necessary, just in case: Reset old temporary row.
// It is really hard to get the editor-close-hints and setModelData calls under
// control. Therefore, if the row is set to the already existing entry, don't
// enter temporary mode.
const weightsystem_t &oldWS = d->weightsystems.weightsystems[row];
if (same_string(oldWS.description, ws.description)) {
free_weightsystem(ws);
} else {
const weightsystem_t &oldWS = d->weightsystems[row];
if (oldWS.description != ws.description) {
tempRow = row;
tempWS = ws;
@ -110,18 +105,18 @@ void WeightModel::clearTempWS()
return;
int oldRow = tempRow;
tempRow = -1;
free_weightsystem(tempWS);
tempWS = weightsystem_t();
dataChanged(index(oldRow, TYPE), index(oldRow, WEIGHT));
}
void WeightModel::commitTempWS()
{
#ifndef SUBSURFACE_MOBILE
if (tempRow < 0 || !d || tempRow > d->weightsystems.nr)
if (tempRow < 0 || !d || static_cast<size_t>(tempRow) > d->weightsystems.size())
return;
// Only submit a command if the type changed
weightsystem_t ws = d->weightsystems.weightsystems[tempRow];
if (!same_string(ws.description, tempWS.description) || gettextFromC::tr(ws.description) != QString(tempWS.description)) {
weightsystem_t ws = d->weightsystems[tempRow];
if (ws.description != tempWS.description || gettextFromC::tr(ws.description.c_str()) != QString::fromStdString(tempWS.description)) {
int count = Command::editWeight(tempRow, tempWS, false);
emit divesEdited(count);
}
@ -155,7 +150,7 @@ Qt::ItemFlags WeightModel::flags(const QModelIndex &index) const
int WeightModel::rowCount(const QModelIndex&) const
{
return d ? d->weightsystems.nr : 0;
return d ? static_cast<int>(d->weightsystems.size()) : 0;
}
void WeightModel::updateDive(dive *dIn)

View file

@ -1021,8 +1021,8 @@ void smartrak_import(const char *file, struct divelog *log)
/* No DC related data */
smtkdive->visibility = strtod((char *)col[coln(VISIBILITY)]->bind_ptr, NULL) > 25 ? 5 : lrint(strtod((char *)col[13]->bind_ptr, NULL) / 5);
weightsystem_t ws = { {(int)lrint(strtod((char *)col[coln(WEIGHT)]->bind_ptr, NULL) * 1000)}, "", false };
add_cloned_weightsystem(&smtkdive->weightsystems, ws);
weightsystem_t ws = { {(int)lrint(strtod((char *)col[coln(WEIGHT)]->bind_ptr, NULL) * 1000)}, std::string(), false };
smtkdive->weightsystems.push_back(std::move(ws));
smtkdive->suit = strdup(get(suit_list, atoi((char *)col[coln(SUITIDX)]->bind_ptr) - 1).c_str());
smtk_build_location(mdb_clon, (char *)col[coln(SITEIDX)]->bind_ptr, &smtkdive->dive_site, log);
smtkdive->buddy = strdup(smtk_locate_buddy(mdb_clon, (char *)col[0]->bind_ptr, buddy_list).c_str());

View file

@ -1768,9 +1768,9 @@ struct SuitVariable : public StatsVariableTemplate<StatsVariable::Type::Discrete
static std::vector<QString> weightsystems(const dive *d)
{
std::vector<QString> res;
res.reserve(d->weightsystems.nr);
for (int i = 0; i < d->weightsystems.nr; ++i)
add_to_vector_unique(res, QString(d->weightsystems.weightsystems[i].description).trimmed());
res.reserve(d->weightsystems.size());
for (auto &ws: d->weightsystems)
add_to_vector_unique(res, QString::fromStdString(ws.description).trimmed());
return res;
}