core: convert dive computer extra data to C++

Use std::string and std::vector. Much simpler code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-18 21:04:58 +02:00 committed by bstoeger
parent b9a2eff3c9
commit bc761344d4
14 changed files with 101 additions and 161 deletions

View file

@ -21,6 +21,7 @@
#include "qthelper.h"
#include "membuffer.h"
#include "picture.h"
#include "range.h"
#include "sample.h"
#include "tag.h"
#include "trip.h"
@ -174,13 +175,6 @@ int dive_getUniqID()
return maxId;
}
/* copy an element in a list of dive computer extra data */
static void copy_extra_data(struct extra_data *sed, struct extra_data *ded)
{
ded->key = copy_string(sed->key);
ded->value = copy_string(sed->value);
}
/* this is very different from the copy_dive_computer later in this file;
* this function actually makes full copies of the content */
static void copy_dc(const struct divecomputer *sdc, struct divecomputer *ddc)
@ -188,7 +182,6 @@ static void copy_dc(const struct divecomputer *sdc, struct divecomputer *ddc)
*ddc = *sdc;
copy_samples(sdc, ddc);
copy_events(sdc, ddc);
STRUCTURED_LIST_COPY(struct extra_data, sdc->extra_data, ddc->extra_data, copy_extra_data);
}
static void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, const int mapping[]);
@ -1453,26 +1446,9 @@ static void merge_samples(struct divecomputer *res,
}
}
/*
* Does the extradata key/value pair already exist in the
* supplied dive computer data?
*
* This is not hugely efficient (with the whole "do this for
* every value you merge" it's O(n**2)) but it's not like we
* have very many extra_data entries per dive computer anyway.
*/
static bool extra_data_exists(const struct extra_data *ed, const struct divecomputer *dc)
static bool operator==(const struct extra_data &e1, const struct extra_data &e2)
{
const struct extra_data *p;
for (p = dc->extra_data; p; p = p->next) {
if (strcmp(p->key, ed->key))
continue;
if (strcmp(p->value, ed->value))
continue;
return true;
}
return false;
return std::tie(e1.key, e1.value) == std::tie(e2.key, e2.value);
}
/*
@ -1480,29 +1456,20 @@ static bool extra_data_exists(const struct extra_data *ed, const struct divecomp
*
* The extra data from 'a' has already been copied into 'res'. So
* we really should just copy over the data from 'b' too.
*
* This is not hugely efficient (with the whole "check this for
* every value you merge" it's O(n**2)) but it's not like we
* have very many extra_data entries per dive computer anyway.
*/
static void merge_extra_data(struct divecomputer *res,
const struct divecomputer *a, const struct divecomputer *b)
{
struct extra_data **ed, *src;
// Find the place to add things in the result
ed = &res->extra_data;
while (*ed)
ed = &(*ed)->next;
for (src = b->extra_data; src; src = src->next) {
if (extra_data_exists(src, a))
for (auto &ed: b->extra_data) {
if (range_contains(a->extra_data, ed))
continue;
*ed = (extra_data *)malloc(sizeof(struct extra_data));
if (!*ed)
break;
copy_extra_data(src, *ed);
ed = &(*ed)->next;
}
// Terminate the result list
*ed = NULL;
res->extra_data.push_back(ed);
}
}
static char *merge_text(const char *a, const char *b, const char *sep)
@ -2449,7 +2416,6 @@ static const struct divecomputer *find_matching_computer(const struct divecomput
static void copy_dive_computer(struct divecomputer *res, const struct divecomputer *a)
{
*res = *a;
STRUCTURED_LIST_COPY(struct extra_data, a->extra_data, res->extra_data, copy_extra_data);
res->samples = res->alloc_samples = 0;
res->sample = NULL;
res->events = NULL;
@ -3415,19 +3381,19 @@ int dive_has_gps_location(const struct dive *dive)
* or GPS2 extra data fields */
static location_t dc_get_gps_location(const struct divecomputer *dc)
{
location_t res = { };
location_t res;
for (struct extra_data *data = dc->extra_data; data; data = data->next) {
if (!strcmp(data->key, "GPS1")) {
parse_location(data->value, &res);
for (const auto &data: dc->extra_data) {
if (data.key == "GPS1") {
parse_location(data.value.c_str(), &res);
/* If we found a valid GPS1 field exit early since
* it has priority over GPS2 */
if (has_location(&res))
break;
} else if (!strcmp(data->key, "GPS2")) {
} else if (data.key == "GPS2") {
/* For GPS2 fields continue searching, as we might
* still find a GPS1 field */
parse_location(data->value, &res);
parse_location(data.value.c_str(), &res);
}
}
return res;

View file

@ -20,6 +20,8 @@ divecomputer::~divecomputer()
free_dc_contents(this);
}
divecomputer::divecomputer(divecomputer &&) = default;
/*
* Good fake dive profiles are hard.
*
@ -483,26 +485,16 @@ void remove_event_from_dc(struct divecomputer *dc, struct event *event)
}
}
void add_extra_data(struct divecomputer *dc, const char *key, const char *value)
void add_extra_data(struct divecomputer *dc, const std::string &key, const std::string &value)
{
struct extra_data **ed = &dc->extra_data;
if (!strcasecmp(key, "Serial")) {
dc->deviceid = calculate_string_hash(value);
if (key == "Serial") {
dc->deviceid = calculate_string_hash(value.c_str());
dc->serial = value;
}
if (!strcmp(key, "FW Version")) {
if (key == "FW Version")
dc->fw_version = value;
}
while (*ed)
ed = &(*ed)->next;
*ed = (struct extra_data *)malloc(sizeof(struct extra_data));
if (*ed) {
(*ed)->key = strdup(key);
(*ed)->value = strdup(value);
(*ed)->next = NULL;
}
dc->extra_data.push_back(extra_data { key, value });
}
/*
@ -534,17 +526,10 @@ int match_one_dc(const struct divecomputer *a, const struct divecomputer *b)
return a->diveid == b->diveid && a->when == b->when ? 1 : -1;
}
static void free_extra_data(struct extra_data *ed)
{
free((void *)ed->key);
free((void *)ed->value);
}
void free_dc_contents(struct divecomputer *dc)
{
free(dc->sample);
free_events(dc->events);
STRUCTURED_LIST_FREE(struct extra_data, dc->extra_data, free_extra_data);
}
static const char *planner_dc_name = "planned dive";

View file

@ -5,6 +5,7 @@
#include "divemode.h"
#include "units.h"
#include <string>
#include <vector>
struct extra_data;
struct sample;
@ -39,11 +40,12 @@ struct divecomputer {
int samples = 0, alloc_samples = 0;
struct sample *sample = nullptr;
struct event *events = nullptr;
struct extra_data *extra_data = nullptr;
std::vector<struct extra_data> extra_data;
struct divecomputer *next = nullptr;
divecomputer();
~divecomputer();
divecomputer(divecomputer &&);
};
extern void fake_dc(struct divecomputer *dc);
@ -65,7 +67,7 @@ extern void copy_samples(const struct divecomputer *s, struct divecomputer *d);
extern void add_event_to_dc(struct divecomputer *dc, struct event *ev);
extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const std::string &name);
extern void remove_event_from_dc(struct divecomputer *dc, struct event *event);
extern void add_extra_data(struct divecomputer *dc, const char *key, const char *value);
extern void add_extra_data(struct divecomputer *dc, const std::string &key, const std::string &value);
extern uint32_t calculate_string_hash(const char *str);
extern bool is_dc_planner(const struct divecomputer *dc);
extern void make_planner_dc(struct divecomputer *dc);

View file

@ -616,12 +616,6 @@ void update_cylinder_related_info(struct dive *dive)
}
}
/* Like strcmp(), but don't crash on null-pointers */
static int safe_strcmp(const char *s1, const char *s2)
{
return strcmp(s1 ? s1 : "", s2 ? s2 : "");
}
/* Compare a list of dive computers by model name */
static int comp_dc(const struct divecomputer *dc1, const struct divecomputer *dc2)
{

View file

@ -2,10 +2,11 @@
#ifndef EXTRADATA_H
#define EXTRADATA_H
#include <string>
struct extra_data {
const char *key;
const char *value;
struct extra_data *next;
std::string key;
std::string value;
};
#endif

View file

@ -548,7 +548,7 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log)
std::string value = parse_mkvi_value(lineptr, key.c_str());
if (value.empty())
break;
add_extra_data(&dive->dc, key.c_str(), value.c_str());
add_extra_data(&dive->dc, key, value);
}
dc = &dive->dc;

View file

@ -832,7 +832,7 @@ static void parse_dc_keyvalue(char *line, struct git_parser_state *state)
if (state->converted_strings.size() != 2)
return;
add_extra_data(state->active_dc, state->converted_strings[0].c_str(), state->converted_strings[1].c_str());
add_extra_data(state->active_dc, state->converted_strings[0], state->converted_strings[1]);
}
static void parse_dc_event(char *line, struct git_parser_state *state)

View file

@ -52,7 +52,6 @@ void ostctools_import(const char *file, struct divelog *log)
dc_status_t rc = DC_STATUS_SUCCESS;
int model, ret, i = 0, c;
unsigned int serial;
struct extra_data *ptr;
const char *failed_to_read_msg = translate("gettextFromC", "Failed to read '%s'");
// Open the archive
@ -161,21 +160,16 @@ void ostctools_import(const char *file, struct divelog *log)
report_error(translate("gettextFromC", "Error - %s - parsing dive %d"), errmsg(rc), ostcdive->number);
// Serial number is not part of the header nor the profile, so libdc won't
// catch it. If Serial is part of the extra_data, and set to zero, remove
// it from the list and add again.
// catch it. If Serial is part of the extra_data, and set to zero, replace it.
ostcdive->dc.serial = std::to_string(serial);
if (ostcdive->dc.extra_data) {
ptr = ostcdive->dc.extra_data;
while (strcmp(ptr->key, "Serial"))
ptr = ptr->next;
if (!strcmp(ptr->value, "0")) {
add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial.c_str());
*ptr = *(ptr)->next;
}
} else {
add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial.c_str());
}
auto it = find_if(ostcdive->dc.extra_data.begin(), ostcdive->dc.extra_data.end(),
[](auto &ed) { return ed.key == "Serial"; });
if (it != ostcdive->dc.extra_data.end() && it->value == "0")
it->value = ostcdive->dc.serial.c_str();
else if (it == ostcdive->dc.extra_data.end())
add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial);
record_dive_to_table(ostcdive.release(), log->dives.get());
sort_dive_table(log->dives.get());
}

View file

@ -2114,20 +2114,21 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
/* device configuration */
switch (((ptr[3] & 0x7f) << 3) + ((ptr[2] & 0xe0) >> 5)) {
// Buffer to print extra string into
char config_buf[256];
// Local variables to temporary decode into
struct tm tm;
const char *device;
const char *deep_stops;
case 0: // TEST_CCR_FULL_1
utc_mkdate(parse_dlf_timestamp(ptr + 12), &tm);
snprintf(config_buf, sizeof(config_buf), "START=%04u-%02u-%02u %02u:%02u:%02u,TEST=%02X%02X%02X%02X,RESULT=%02X%02X%02X%02X", tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ptr[7], ptr[6], ptr[5], ptr[4], ptr[11], ptr[10], ptr[9], ptr[8]);
add_extra_data(state.cur_dc, "TEST_CCR_FULL_1", config_buf);
add_extra_data(state.cur_dc, "TEST_CCR_FULL_1",
format_string_std("START=%04u-%02u-%02u %02u:%02u:%02u,TEST=%02X%02X%02X%02X,RESULT=%02X%02X%02X%02X",
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ptr[7], ptr[6], ptr[5], ptr[4], ptr[11], ptr[10], ptr[9], ptr[8]));
break;
case 1: // TEST_CCR_PARTIAL_1
utc_mkdate(parse_dlf_timestamp(ptr + 12), &tm);
snprintf(config_buf, sizeof(config_buf), "START=%04u-%02u-%02u %02u:%02u:%02u,TEST=%02X%02X%02X%02X,RESULT=%02X%02X%02X%02X", tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ptr[7], ptr[6], ptr[5], ptr[4], ptr[11], ptr[10], ptr[9], ptr[8]);
add_extra_data(state.cur_dc, "TEST_CCR_PARTIAL_1", config_buf);
add_extra_data(state.cur_dc, "TEST_CCR_PARTIAL_1",
format_string_std("START=%04u-%02u-%02u %02u:%02u:%02u,TEST=%02X%02X%02X%02X,RESULT=%02X%02X%02X%02X",
tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ptr[7], ptr[6], ptr[5], ptr[4], ptr[11], ptr[10], ptr[9], ptr[8]));
break;
case 2: // CFG_OXYGEN_CALIBRATION
utc_mkdate(parse_dlf_timestamp(ptr + 12), &tm);
@ -2135,12 +2136,14 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
o2_sensor_calibration_values[1] = (ptr[7] << 8) + ptr[6];
o2_sensor_calibration_values[2] = (ptr[9] << 8) + ptr[8];
o2_sensor_calibration_values[3] = (ptr[11] << 8) + ptr[10];
snprintf(config_buf, sizeof(config_buf), "%04u,%04u,%04u,%04u,TIME=%04u-%02u-%02u %02u:%02u:%02u", o2_sensor_calibration_values[0], o2_sensor_calibration_values[1], o2_sensor_calibration_values[2], o2_sensor_calibration_values[3], tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
add_extra_data(state.cur_dc, "CFG_OXYGEN_CALIBRATION", config_buf);
add_extra_data(state.cur_dc, "CFG_OXYGEN_CALIBRATION",
format_string_std("%04u,%04u,%04u,%04u,TIME=%04u-%02u-%02u %02u:%02u:%02u",
o2_sensor_calibration_values[0], o2_sensor_calibration_values[1], o2_sensor_calibration_values[2], o2_sensor_calibration_values[3], tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec));
break;
case 3: // CFG_SERIAL
snprintf(config_buf, sizeof(config_buf), "PRODUCT=%c%c%c%c,SERIAL=%c%c%c%c%c%c%c%c", ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]);
add_extra_data(state.cur_dc, "CFG_SERIAL", config_buf);
add_extra_data(state.cur_dc, "CFG_SERIAL",
format_string_std("PRODUCT=%c%c%c%c,SERIAL=%c%c%c%c%c%c%c%c",
ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]));
break;
case 4: // CFG_CONFIG_DECO
switch ((ptr[5] & 0xC0) >> 6) {
@ -2158,12 +2161,15 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
break;
}
snprintf(config_buf, sizeof(config_buf), "%s,%s,%s,safety stop required=%s,last_stop=%s,deco_algorithm=%s,stop_rounding=%u,deep_stops=%s", (ptr[4] & 0x80) ? "imperial" : "metric", (ptr[4] & 0x40) ? "sea" : "fresh", (ptr[4] & 0x30) ? "stops" : "ceiling", (ptr[4] & 0x10) ? "yes" : "no", (ptr[4] & 0x08) ? "6m" : "3m", (ptr[4] & 0x04) ? "VPM" : "Buhlmann+GF", (ptr[4] & 0x03) ? (ptr[4] & 0x03) * 30 : 1, deep_stops);
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 1", config_buf);
snprintf(config_buf, sizeof(config_buf), "deep_stop_len=%u min,gas_switch_len=%u min,gf_low=%u,gf_high=%u,gf_low_bailout=%u,gf_high_bailout=%u,ppO2_low=%4.2f,ppO2_high=%4.2f", (ptr[5] & 0x38) >> 3, ptr[5] & 0x07, ptr[6], ptr[7], ptr[8], ptr[9], ptr[10] / 100.0f, ptr[11] / 100.0f);
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 2", config_buf);
snprintf(config_buf, sizeof(config_buf), "alarm_global=%u,alarm_cns=%u,alarm_ppO2=%u,alarm_ceiling=%u,alarm_stop_miss=%u,alarm_decentrate=%u,alarm_ascentrate=%u", (ptr[12] & 0x80) >> 7, (ptr[12] & 0x40) >> 6, (ptr[12] & 0x20) >> 5, (ptr[12] & 0x10) >> 4, (ptr[12] & 0x08) >> 3, (ptr[12] & 0x04) >> 2, (ptr[12] & 0x02) >> 1);
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 3", config_buf);
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 1",
format_string_std("%s,%s,%s,safety stop required=%s,last_stop=%s,deco_algorithm=%s,stop_rounding=%u,deep_stops=%s",
(ptr[4] & 0x80) ? "imperial" : "metric", (ptr[4] & 0x40) ? "sea" : "fresh", (ptr[4] & 0x30) ? "stops" : "ceiling", (ptr[4] & 0x10) ? "yes" : "no", (ptr[4] & 0x08) ? "6m" : "3m", (ptr[4] & 0x04) ? "VPM" : "Buhlmann+GF", (ptr[4] & 0x03) ? (ptr[4] & 0x03) * 30 : 1, deep_stops));
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 2",
format_string_std("deep_stop_len=%u min,gas_switch_len=%u min,gf_low=%u,gf_high=%u,gf_low_bailout=%u,gf_high_bailout=%u,ppO2_low=%4.2f,ppO2_high=%4.2f",
(ptr[5] & 0x38) >> 3, ptr[5] & 0x07, ptr[6], ptr[7], ptr[8], ptr[9], ptr[10] / 100.0f, ptr[11] / 100.0f));
add_extra_data(state.cur_dc, "CFG_CONFIG_DECO part 3",
format_string_std("alarm_global=%u,alarm_cns=%u,alarm_ppO2=%u,alarm_ceiling=%u,alarm_stop_miss=%u,alarm_decentrate=%u,alarm_ascentrate=%u",
(ptr[12] & 0x80) >> 7, (ptr[12] & 0x40) >> 6, (ptr[12] & 0x20) >> 5, (ptr[12] & 0x10) >> 4, (ptr[12] & 0x08) >> 3, (ptr[12] & 0x04) >> 2, (ptr[12] & 0x02) >> 1));
break;
case 5: // CFG_VERSION
switch (ptr[4]) {
@ -2180,8 +2186,9 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log)
device = "UNKNOWN";
break;
}
snprintf(config_buf, sizeof(config_buf), "DEVICE=%s,HW=%d.%d,FW=%d.%d.%d.%d,FLAGS=%04X", device, ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], (ptr[15] << 24) + (ptr[14] << 16) + (ptr[13] << 8) + (ptr[12]), (ptr[11] << 8) + ptr[10]);
add_extra_data(state.cur_dc, "CFG_VERSION", config_buf);
add_extra_data(state.cur_dc, "CFG_VERSION",
format_string_std("DEVICE=%s,HW=%d.%d,FW=%d.%d.%d.%d,FLAGS=%04X",
device, ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], (ptr[15] << 24) + (ptr[14] << 16) + (ptr[13] << 8) + (ptr[12]), (ptr[11] << 8) + ptr[10]));
break;
}
break;

View file

@ -119,12 +119,11 @@ static void save_tags(struct membuffer *b, struct tag_entry *tags)
put_string(b, "\n");
}
static void save_extra_data(struct membuffer *b, struct extra_data *ed)
static void save_extra_data(struct membuffer *b, const struct divecomputer *dc)
{
while (ed) {
if (ed->key && ed->value)
put_format(b, "keyvalue \"%s\" \"%s\"\n", ed->key ? : "", ed->value ? : "");
ed = ed->next;
for (const auto &ed: dc->extra_data) {
if (!ed.key.empty() && !ed.value.empty())
put_format(b, "keyvalue \"%s\" \"%s\"\n", ed.key.c_str(), ed.value.c_str());
}
}
@ -442,7 +441,7 @@ static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer
save_salinity(b, dc);
put_duration(b, dc->surfacetime, "surfacetime ", "min\n");
save_extra_data(b, dc->extra_data);
save_extra_data(b, dc);
save_events(b, dive, dc->events);
save_samples(b, dive, dc);
}

View file

@ -396,16 +396,15 @@ static void save_tags(struct membuffer *b, struct tag_entry *entry)
}
}
static void save_extra_data(struct membuffer *b, struct extra_data *ed)
static void save_extra_data(struct membuffer *b, const struct divecomputer *dc)
{
while (ed) {
if (ed->key && ed->value) {
for (const auto &ed: dc->extra_data) {
if (!ed.key.empty() && !ed.value.empty()) {
put_string(b, " <extradata");
show_utf8(b, ed->key, " key='", "'", 1);
show_utf8(b, ed->value, " value='", "'", 1);
show_utf8(b, ed.key.c_str(), " key='", "'", 1);
show_utf8(b, ed.value.c_str(), " value='", "'", 1);
put_string(b, " />\n");
}
ed = ed->next;
}
}
@ -471,7 +470,7 @@ static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer
save_airpressure(b, dc);
save_salinity(b, dc);
put_duration(b, dc->surfacetime, " <surfacetime>", " min</surfacetime>\n");
save_extra_data(b, dc->extra_data);
save_extra_data(b, dc);
save_events(b, dive, dc->events);
save_samples(b, dive, dc);

View file

@ -18,6 +18,7 @@
#include "divecomputer.h"
#include "divesite.h"
#include "errorhelper.h"
#include "format.h"
#include "sample.h"
#include <libdivecomputer/parser.h>
#include <libdivecomputer/version.h>
@ -356,22 +357,20 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive)
dive->dc.duration.seconds = sample->time.seconds - 1;
/* get data from the footer */
char buffer[24];
snprintf(buffer, sizeof(buffer), "%1u.%02u", data[18], data[17]);
add_extra_data(dc, "FW Version", buffer);
snprintf(buffer, sizeof(buffer), "%08x", *(uint32_t *)(data.data() + 9));
add_extra_data(dc, "Serial", buffer);
snprintf(buffer, sizeof(buffer), "%d", *(uint16_t *)(data.data() + i + 35));
add_extra_data(dc, "main battery after dive", buffer);
snprintf(buffer, sizeof(buffer), "%0u:%02u", FRACTION_TUPLE(*(uint16_t *)(data.data() + i + 24), 60));
add_extra_data(dc, "no fly time", buffer);
snprintf(buffer, sizeof(buffer), "%0u:%02u", FRACTION_TUPLE(*(uint16_t *)(data.data() + i + 26), 60));
add_extra_data(dc, "no dive time", buffer);
snprintf(buffer, sizeof(buffer), "%0u:%02u", FRACTION_TUPLE(*(uint16_t *)(data.data() + i + 28), 60));
add_extra_data(dc, "desat time", buffer);
snprintf(buffer, sizeof(buffer), "%u", *(uint16_t *)(data.data() + i + 30));
add_extra_data(dc, "allowed altitude", buffer);
add_extra_data(dc, "FW Version",
format_string_std("%1u.%02u", data[18], data[17]));
add_extra_data(dc, "Serial",
format_string_std("%08x", *(uint32_t *)(data.data() + 9)));
add_extra_data(dc, "main battery after dive",
std::to_string(*(uint16_t *)(data.data() + i + 35)));
add_extra_data(dc, "no fly time",
format_string_std("%0u:%02u", FRACTION_TUPLE(*(uint16_t *)(data.data() + i + 24), 60)));
add_extra_data(dc, "no dive time",
format_string_std("%0u:%02u", FRACTION_TUPLE(*(uint16_t *)(data.data() + i + 26), 60)));
add_extra_data(dc, "desat time",
format_string_std("%0u:%02u", FRACTION_TUPLE(*(uint16_t *)(data.data() + i + 28), 60)));
add_extra_data(dc, "allowed altitude",
std::to_string(*(uint16_t *)(data.data() + i + 30)));
return;
}

View file

@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include "qt-models/divecomputerextradatamodel.h"
#include "core/divecomputer.h"
#include "core/extradata.h"
#include "core/metrics.h"
ExtraDataModel::ExtraDataModel(QObject *parent) : CleanerTableModel(parent)
@ -21,7 +20,7 @@ QVariant ExtraDataModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() > (int)items.size())
return QVariant();
const Item &item = items[index.row()];
const extra_data &item = items[index.row()];
switch (role) {
case Qt::FontRole:
@ -31,9 +30,9 @@ QVariant ExtraDataModel::data(const QModelIndex &index, int role) const
case Qt::DisplayRole:
switch (index.column()) {
case KEY:
return item.key;
return QString::fromStdString(item.key);
case VALUE:
return item.value;
return QString::fromStdString(item.value);
}
return QVariant();
}
@ -48,11 +47,9 @@ int ExtraDataModel::rowCount(const QModelIndex&) const
void ExtraDataModel::updateDiveComputer(const struct divecomputer *dc)
{
beginResetModel();
struct extra_data *ed = dc ? dc->extra_data : nullptr;
items.clear();
while (ed) {
items.push_back({ ed->key, ed->value });
ed = ed->next;
}
if (dc)
items = dc->extra_data;
else
items.clear();
endResetModel();
}

View file

@ -3,6 +3,7 @@
#define DIVECOMPUTEREXTRADATAMODEL_H
#include "cleanertablemodel.h"
#include "core/extradata.h"
struct divecomputer;
@ -22,11 +23,7 @@ public:
void updateDiveComputer(const struct divecomputer *dc);
private:
struct Item {
QString key;
QString value;
};
std::vector<Item> items;
std::vector<extra_data> items;
};
#endif