mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Converting the device_info list into a Qt data structure
This data structure was quite fragile and made 'undo' when editing rather hard to implement. So instead I decided to turn this into a QMultiMap which seemed like the ideal data structure for it. This map holds all the dive computer related data indexed by the model. As QMultiMap it allows multiple entries per key (model string) and disambiguates between them with the deviceId. This commit turned out much larger than I wanted. But I didn't manage to find a clean way to break it up and make the pieces make sense. So this brings back the Ok / Cancel button for the dive computer edit dialog. And it makes those two buttons actually do the right thing (which is what started this whole process). For this to work we simply copy the map to a working copy and do all edits on that one - and then copy that over the 'real' map when we accept the changes. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
14ccbbf6e8
commit
29b242c703
19 changed files with 302 additions and 253 deletions
1
Makefile
1
Makefile
|
@ -69,6 +69,7 @@ SOURCES = \
|
||||||
time.c \
|
time.c \
|
||||||
libdivecomputer.c \
|
libdivecomputer.c \
|
||||||
qt-gui.cpp \
|
qt-gui.cpp \
|
||||||
|
qthelper.cpp \
|
||||||
qt-ui/divelistview.cpp \
|
qt-ui/divelistview.cpp \
|
||||||
qt-ui/maintab.cpp \
|
qt-ui/maintab.cpp \
|
||||||
qt-ui/mainwindow.cpp \
|
qt-ui/mainwindow.cpp \
|
||||||
|
|
113
device.c
113
device.c
|
@ -2,119 +2,6 @@
|
||||||
#include "dive.h"
|
#include "dive.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
static struct device_info *device_info_list;
|
|
||||||
|
|
||||||
struct device_info *head_of_device_info_list(void)
|
|
||||||
{
|
|
||||||
return device_info_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_dive_computer(const char *model, uint32_t deviceid)
|
|
||||||
{
|
|
||||||
free(remove_device_info(model, deviceid));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int match_device_info(struct device_info *entry, const char *model, uint32_t deviceid)
|
|
||||||
{
|
|
||||||
return !strcmp(entry->model, model) && entry->deviceid == deviceid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* just find the entry for this divecomputer */
|
|
||||||
struct device_info *get_device_info(const char *model, uint32_t deviceid)
|
|
||||||
{
|
|
||||||
struct device_info *known = device_info_list;
|
|
||||||
|
|
||||||
/* a 0 deviceid doesn't get a nickname - those come from development
|
|
||||||
* versions of Subsurface that didn't store the deviceid in the divecomputer entries */
|
|
||||||
if (!deviceid || !model)
|
|
||||||
return NULL;
|
|
||||||
while (known) {
|
|
||||||
if (match_device_info(known, model, deviceid))
|
|
||||||
return known;
|
|
||||||
known = known->next;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sort the device_info list, so that we write it out
|
|
||||||
* in a stable order. Otherwise we'll end up having the
|
|
||||||
* XML file have the devices listed in some arbitrary
|
|
||||||
* order, which is annoying.
|
|
||||||
*/
|
|
||||||
static void add_entry_sorted(struct device_info *entry)
|
|
||||||
{
|
|
||||||
struct device_info *p, **pp = &device_info_list;
|
|
||||||
|
|
||||||
while ((p = *pp) != NULL) {
|
|
||||||
int cmp = strcmp(p->model, entry->model);
|
|
||||||
if (cmp > 0)
|
|
||||||
break;
|
|
||||||
if (!cmp && p->deviceid > entry->deviceid)
|
|
||||||
break;
|
|
||||||
pp = &p->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry->next = p;
|
|
||||||
*pp = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get an existing device info model or create a new one if valid */
|
|
||||||
struct device_info *create_device_info(const char *model, uint32_t deviceid)
|
|
||||||
{
|
|
||||||
struct device_info *entry;
|
|
||||||
|
|
||||||
if (!deviceid || !model || !*model)
|
|
||||||
return NULL;
|
|
||||||
entry = get_device_info(model, deviceid);
|
|
||||||
if (entry)
|
|
||||||
return entry;
|
|
||||||
entry = calloc(1, sizeof(*entry));
|
|
||||||
if (entry) {
|
|
||||||
entry->model = strdup(model);
|
|
||||||
entry->deviceid = deviceid;
|
|
||||||
add_entry_sorted(entry);
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do we have a DIFFERENT divecomputer of the same model? */
|
|
||||||
struct device_info *get_different_device_info(const char *model, uint32_t deviceid)
|
|
||||||
{
|
|
||||||
struct device_info *known = device_info_list;
|
|
||||||
|
|
||||||
/* a 0 deviceid matches any DC of the same model - those come from development
|
|
||||||
* versions of Subsurface that didn't store the deviceid in the divecomputer entries */
|
|
||||||
if (!deviceid)
|
|
||||||
return NULL;
|
|
||||||
if (!model)
|
|
||||||
model = "";
|
|
||||||
while (known) {
|
|
||||||
if (known->model && !strcmp(known->model, model) &&
|
|
||||||
known->deviceid != deviceid)
|
|
||||||
return known;
|
|
||||||
known = known->next;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct device_info *remove_device_info(const char *model, uint32_t deviceid)
|
|
||||||
{
|
|
||||||
struct device_info *entry, **p;
|
|
||||||
|
|
||||||
if (!deviceid || !model || !*model)
|
|
||||||
return NULL;
|
|
||||||
p = &device_info_list;
|
|
||||||
while ((entry = *p) != NULL) {
|
|
||||||
if (match_device_info(entry, model, deviceid)) {
|
|
||||||
*p = entry->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p = &entry->next;
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct divecomputer* fake_dc(struct divecomputer* dc)
|
struct divecomputer* fake_dc(struct divecomputer* dc)
|
||||||
{
|
{
|
||||||
static struct sample fake[4];
|
static struct sample fake[4];
|
||||||
|
|
19
device.h
19
device.h
|
@ -6,23 +6,10 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct device_info {
|
|
||||||
const char *model;
|
|
||||||
uint32_t deviceid;
|
|
||||||
|
|
||||||
const char *serial_nr;
|
|
||||||
const char *firmware;
|
|
||||||
const char *nickname;
|
|
||||||
struct device_info *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct device_info *get_device_info(const char *model, uint32_t deviceid);
|
|
||||||
extern struct device_info *get_different_device_info(const char *model, uint32_t deviceid);
|
|
||||||
extern struct device_info *create_device_info(const char *model, uint32_t deviceid);
|
|
||||||
extern struct device_info *remove_device_info(const char *model, uint32_t deviceid);
|
|
||||||
extern struct device_info *head_of_device_info_list(void);
|
|
||||||
extern struct divecomputer *fake_dc(struct divecomputer* dc);
|
extern struct divecomputer *fake_dc(struct divecomputer* dc);
|
||||||
extern void remove_dive_computer(const char *model, uint32_t deviceid);
|
extern void create_device_node(const char *model, uint32_t deviceid, const char *serial, const char *firmware, const char *nickname);
|
||||||
|
extern void call_for_each_dc(FILE *f, void (*callback)(FILE *, const char *, uint32_t,
|
||||||
|
const char *, const char *, const char *));
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
1
dive.h
1
dive.h
|
@ -653,7 +653,6 @@ extern void dive_list_update_dives(void);
|
||||||
extern void flush_divelist(struct dive *dive);
|
extern void flush_divelist(struct dive *dive);
|
||||||
|
|
||||||
extern void set_dc_nickname(struct dive *dive);
|
extern void set_dc_nickname(struct dive *dive);
|
||||||
extern const char *get_dc_nickname(const char *model, uint32_t deviceid);
|
|
||||||
extern void set_autogroup(gboolean value);
|
extern void set_autogroup(gboolean value);
|
||||||
extern int total_weight(struct dive *);
|
extern int total_weight(struct dive *);
|
||||||
|
|
||||||
|
|
|
@ -1059,7 +1059,7 @@ static void try_to_renumber(struct dive *last, int preexisting)
|
||||||
|
|
||||||
void process_dives(bool is_imported, bool prefer_imported)
|
void process_dives(bool is_imported, bool prefer_imported)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int preexisting = dive_table.preexisting;
|
int preexisting = dive_table.preexisting;
|
||||||
struct dive *last;
|
struct dive *last;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include "dive.h"
|
#include "dive.h"
|
||||||
|
#include "qthelper.h"
|
||||||
|
|
||||||
QString get_depth_string(depth_t depth, bool showunit);
|
QString get_depth_string(depth_t depth, bool showunit);
|
||||||
QString get_weight_string(weight_t weight, bool showunit);
|
QString get_weight_string(weight_t weight, bool showunit);
|
||||||
|
@ -18,5 +19,8 @@ QString get_pressure_string(pressure_t pressure, bool showunit);
|
||||||
void set_default_dive_computer(const char *vendor, const char *product);
|
void set_default_dive_computer(const char *vendor, const char *product);
|
||||||
void set_default_dive_computer_device(const char *name);
|
void set_default_dive_computer_device(const char *name);
|
||||||
QString getSubsurfaceDataPath(QString folderToFind);
|
QString getSubsurfaceDataPath(QString folderToFind);
|
||||||
|
extern const QString get_dc_nickname(const char *model, uint32_t deviceid);
|
||||||
|
|
||||||
|
extern DiveComputerList dcList;
|
||||||
|
|
||||||
#endif /* HELPER_H */
|
#endif /* HELPER_H */
|
||||||
|
|
|
@ -578,36 +578,29 @@ static unsigned int undo_libdivecomputer_suunto_nr_changes(unsigned int serial)
|
||||||
|
|
||||||
static unsigned int fixup_suunto_versions(device_data_t *devdata, const dc_event_devinfo_t *devinfo)
|
static unsigned int fixup_suunto_versions(device_data_t *devdata, const dc_event_devinfo_t *devinfo)
|
||||||
{
|
{
|
||||||
struct device_info *info;
|
|
||||||
unsigned int serial = devinfo->serial;
|
unsigned int serial = devinfo->serial;
|
||||||
|
char serial_nr[13] = "";
|
||||||
|
char firmware[13] = "";
|
||||||
|
|
||||||
first_temp_is_air = 1;
|
first_temp_is_air = 1;
|
||||||
|
|
||||||
serial = undo_libdivecomputer_suunto_nr_changes(serial);
|
serial = undo_libdivecomputer_suunto_nr_changes(serial);
|
||||||
|
|
||||||
info = create_device_info(devdata->model, devdata->deviceid);
|
if (serial) {
|
||||||
if (!info)
|
|
||||||
return serial;
|
|
||||||
|
|
||||||
if (!info->serial_nr && serial) {
|
|
||||||
char serial_nr[13];
|
|
||||||
|
|
||||||
snprintf(serial_nr, sizeof(serial_nr), "%02d%02d%02d%02d",
|
snprintf(serial_nr, sizeof(serial_nr), "%02d%02d%02d%02d",
|
||||||
(devinfo->serial >> 24) & 0xff,
|
(devinfo->serial >> 24) & 0xff,
|
||||||
(devinfo->serial >> 16) & 0xff,
|
(devinfo->serial >> 16) & 0xff,
|
||||||
(devinfo->serial >> 8) & 0xff,
|
(devinfo->serial >> 8) & 0xff,
|
||||||
(devinfo->serial >> 0) & 0xff);
|
(devinfo->serial >> 0) & 0xff);
|
||||||
info->serial_nr = strdup(serial_nr);
|
|
||||||
}
|
}
|
||||||
|
if (devinfo->firmware) {
|
||||||
if (!info->firmware && devinfo->firmware) {
|
|
||||||
char firmware[13];
|
|
||||||
snprintf(firmware, sizeof(firmware), "%d.%d.%d",
|
snprintf(firmware, sizeof(firmware), "%d.%d.%d",
|
||||||
(devinfo->firmware >> 16) & 0xff,
|
(devinfo->firmware >> 16) & 0xff,
|
||||||
(devinfo->firmware >> 8) & 0xff,
|
(devinfo->firmware >> 8) & 0xff,
|
||||||
(devinfo->firmware >> 0) & 0xff);
|
(devinfo->firmware >> 0) & 0xff);
|
||||||
info->firmware = strdup(firmware);
|
|
||||||
}
|
}
|
||||||
|
create_device_node(devdata->model, devdata->deviceid, serial_nr, firmware, "");
|
||||||
|
|
||||||
return serial;
|
return serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
parse-xml.c
13
parse-xml.c
|
@ -1222,17 +1222,8 @@ static void dc_settings_start(void)
|
||||||
|
|
||||||
static void dc_settings_end(void)
|
static void dc_settings_end(void)
|
||||||
{
|
{
|
||||||
struct device_info *info;
|
create_device_node(cur_settings.dc.model, cur_settings.dc.deviceid, cur_settings.dc.serial_nr,
|
||||||
|
cur_settings.dc.firmware, cur_settings.dc.nickname);
|
||||||
info = create_device_info(cur_settings.dc.model, cur_settings.dc.deviceid);
|
|
||||||
if (info) {
|
|
||||||
if (!info->serial_nr && cur_settings.dc.serial_nr)
|
|
||||||
info->serial_nr = strdup(cur_settings.dc.serial_nr);
|
|
||||||
if (!info->firmware && cur_settings.dc.firmware)
|
|
||||||
info->firmware = strdup(cur_settings.dc.firmware);
|
|
||||||
if (!info->nickname && cur_settings.dc.nickname)
|
|
||||||
info->nickname = strdup(cur_settings.dc.nickname);
|
|
||||||
}
|
|
||||||
reset_dc_settings();
|
reset_dc_settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
67
qt-gui.cpp
67
qt-gui.cpp
|
@ -21,6 +21,7 @@
|
||||||
#include "libdivecomputer.h"
|
#include "libdivecomputer.h"
|
||||||
#include "qt-ui/mainwindow.h"
|
#include "qt-ui/mainwindow.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "qthelper.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
@ -32,10 +33,13 @@
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QMultiMap>
|
||||||
|
|
||||||
const char *default_dive_computer_vendor;
|
const char *default_dive_computer_vendor;
|
||||||
const char *default_dive_computer_product;
|
const char *default_dive_computer_product;
|
||||||
const char *default_dive_computer_device;
|
const char *default_dive_computer_device;
|
||||||
|
DiveComputerList dcList;
|
||||||
|
|
||||||
class Translator: public QTranslator
|
class Translator: public QTranslator
|
||||||
{
|
{
|
||||||
|
@ -142,30 +146,15 @@ void set_filename(const char *filename, gboolean force)
|
||||||
existing_filename = NULL;
|
existing_filename = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *get_dc_nickname(const char *model, uint32_t deviceid)
|
const QString get_dc_nickname(const char *model, uint32_t deviceid)
|
||||||
{
|
{
|
||||||
struct device_info *known = get_device_info(model, deviceid);
|
const DiveComputerNode *existNode = dcList.getExact(model, deviceid);
|
||||||
if (known) {
|
if (!existNode)
|
||||||
if (known->nickname && *known->nickname)
|
return QString("");
|
||||||
return known->nickname;
|
if (existNode->nickName != "")
|
||||||
else
|
return existNode->nickName;
|
||||||
return known->model;
|
else
|
||||||
}
|
return model;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remember_dc(const char *model, uint32_t deviceid, const char *nickname)
|
|
||||||
{
|
|
||||||
struct device_info *nn_entry;
|
|
||||||
|
|
||||||
nn_entry = create_device_info(model, deviceid);
|
|
||||||
if (!nn_entry)
|
|
||||||
return;
|
|
||||||
if (!nickname || !*nickname) {
|
|
||||||
nn_entry->nickname = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nn_entry->nickname = strdup(nickname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_dc_nickname(struct dive *dive)
|
void set_dc_nickname(struct dive *dive)
|
||||||
|
@ -176,16 +165,20 @@ void set_dc_nickname(struct dive *dive)
|
||||||
struct divecomputer *dc = &dive->dc;
|
struct divecomputer *dc = &dive->dc;
|
||||||
|
|
||||||
while (dc) {
|
while (dc) {
|
||||||
if (get_dc_nickname(dc->model, dc->deviceid) == NULL) {
|
if (dc->model && *dc->model && dc->deviceid &&
|
||||||
|
!dcList.getExact(dc->model, dc->deviceid)) {
|
||||||
// we don't have this one, yet
|
// we don't have this one, yet
|
||||||
struct device_info *nn_entry = get_different_device_info(dc->model, dc->deviceid);
|
const DiveComputerNode *existNode = dcList.get(dc->model);
|
||||||
if (nn_entry) {
|
if (existNode) {
|
||||||
// we already have this model but a different deviceid
|
// we already have this model but a different deviceid
|
||||||
QString simpleNick(dc->model);
|
QString simpleNick(dc->model);
|
||||||
simpleNick.append(" (").append(QString::number(dc->deviceid, 16)).append(")");
|
if (dc->deviceid == 0)
|
||||||
remember_dc(dc->model, dc->deviceid, simpleNick.toUtf8().data());
|
simpleNick.append(" (unknown deviceid)");
|
||||||
|
else
|
||||||
|
simpleNick.append(" (").append(QString::number(dc->deviceid, 16)).append(")");
|
||||||
|
dcList.addDC(dc->model, dc->deviceid, simpleNick);
|
||||||
} else {
|
} else {
|
||||||
remember_dc(dc->model, dc->deviceid, NULL);
|
dcList.addDC(dc->model, dc->deviceid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dc = dc->next;
|
dc = dc->next;
|
||||||
|
@ -330,4 +323,20 @@ QString getSubsurfaceDataPath(QString folderToFind)
|
||||||
return QString("");
|
return QString("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create_device_node(const char *model, uint32_t deviceid, const char *serial, const char *firmware, const char *nickname)
|
||||||
|
{
|
||||||
|
dcList.addDC(model, deviceid, nickname, serial, firmware);
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_for_each_dc(FILE *f, void (*callback)(FILE *, const char *, uint32_t,
|
||||||
|
const char *, const char *, const char *))
|
||||||
|
{
|
||||||
|
QList<DiveComputerNode> values = dcList.dcMap.values();
|
||||||
|
for (int i = 0; i < values.size(); i++) {
|
||||||
|
const DiveComputerNode *node = &values.at(i);
|
||||||
|
callback(f, node->model.toUtf8().data(), node->deviceId, node->nickName.toUtf8().data(),
|
||||||
|
node->serialNumber.toUtf8().data(), node->firmware.toUtf8().data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#include "qt-gui.moc"
|
#include "qt-gui.moc"
|
||||||
|
|
|
@ -3,16 +3,26 @@
|
||||||
#include "ui_divecomputermanagementdialog.h"
|
#include "ui_divecomputermanagementdialog.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include "../qthelper.h"
|
||||||
|
#include "../helpers.h"
|
||||||
|
|
||||||
DiveComputerManagementDialog::DiveComputerManagementDialog(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f)
|
DiveComputerManagementDialog::DiveComputerManagementDialog(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f),
|
||||||
, ui( new Ui::DiveComputerManagementDialog())
|
ui( new Ui::DiveComputerManagementDialog()),
|
||||||
|
model(0)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
model = new DiveComputerModel();
|
init();
|
||||||
ui->tableView->setModel(model);
|
|
||||||
connect(ui->tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(tryRemove(QModelIndex)));
|
connect(ui->tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(tryRemove(QModelIndex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiveComputerManagementDialog::init()
|
||||||
|
{
|
||||||
|
if (model)
|
||||||
|
delete model;
|
||||||
|
model = new DiveComputerModel(dcList.dcMap);
|
||||||
|
ui->tableView->setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
DiveComputerManagementDialog* DiveComputerManagementDialog::instance()
|
DiveComputerManagementDialog* DiveComputerManagementDialog::instance()
|
||||||
{
|
{
|
||||||
static DiveComputerManagementDialog *self = new DiveComputerManagementDialog();
|
static DiveComputerManagementDialog *self = new DiveComputerManagementDialog();
|
||||||
|
@ -44,3 +54,17 @@ void DiveComputerManagementDialog::tryRemove(const QModelIndex& index)
|
||||||
model->remove(index);
|
model->remove(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiveComputerManagementDialog::accept()
|
||||||
|
{
|
||||||
|
model->keepWorkingList();
|
||||||
|
hide();
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiveComputerManagementDialog::reject()
|
||||||
|
{
|
||||||
|
model->dropWorkingList();
|
||||||
|
hide();
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
|
@ -14,9 +14,12 @@ Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static DiveComputerManagementDialog *instance();
|
static DiveComputerManagementDialog *instance();
|
||||||
void update();
|
void update();
|
||||||
|
void init();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void tryRemove(const QModelIndex& index);
|
void tryRemove(const QModelIndex& index);
|
||||||
|
void accept();
|
||||||
|
void reject();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit DiveComputerManagementDialog(QWidget* parent = 0, Qt::WindowFlags f = 0);
|
explicit DiveComputerManagementDialog(QWidget* parent = 0, Qt::WindowFlags f = 0);
|
||||||
|
@ -24,4 +27,4 @@ private:
|
||||||
DiveComputerModel *model;
|
DiveComputerModel *model;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Dialog</string>
|
<string>Edit Dive Computer Nicknames</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -21,8 +21,51 @@
|
||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>DiveComputerManagementDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>DiveComputerManagementDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -206,6 +206,7 @@ void MainWindow::on_actionDownloadWeb_triggered()
|
||||||
|
|
||||||
void MainWindow::on_actionEditDeviceNames_triggered()
|
void MainWindow::on_actionEditDeviceNames_triggered()
|
||||||
{
|
{
|
||||||
|
DiveComputerManagementDialog::instance()->init();
|
||||||
DiveComputerManagementDialog::instance()->update();
|
DiveComputerManagementDialog::instance()->update();
|
||||||
DiveComputerManagementDialog::instance()->show();
|
DiveComputerManagementDialog::instance()->show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "../helpers.h"
|
#include "../helpers.h"
|
||||||
#include "../dive.h"
|
#include "../dive.h"
|
||||||
#include "../device.h"
|
#include "../device.h"
|
||||||
|
#include "../qthelper.h"
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
@ -1162,9 +1162,10 @@ void DiveTripModel::setLayout(DiveTripModel::Layout layout)
|
||||||
*####################################################################
|
*####################################################################
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DiveComputerModel::DiveComputerModel(QObject* parent): QAbstractTableModel(parent)
|
DiveComputerModel::DiveComputerModel(QMultiMap<QString, DiveComputerNode> &dcMap, QObject* parent): QAbstractTableModel(parent)
|
||||||
{
|
{
|
||||||
|
dcWorkingMap = dcMap;
|
||||||
|
numRows = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DiveComputerModel::columnCount(const QModelIndex& parent) const
|
int DiveComputerModel::columnCount(const QModelIndex& parent) const
|
||||||
|
@ -1188,17 +1189,15 @@ QVariant DiveComputerModel::headerData(int section, Qt::Orientation orientation,
|
||||||
|
|
||||||
QVariant DiveComputerModel::data(const QModelIndex& index, int role) const
|
QVariant DiveComputerModel::data(const QModelIndex& index, int role) const
|
||||||
{
|
{
|
||||||
struct device_info *device = head_of_device_info_list();
|
QList<DiveComputerNode> values = dcWorkingMap.values();
|
||||||
for(int i = 0; i < index.row(); i++){
|
DiveComputerNode node = values.at(index.row());
|
||||||
device = device->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant ret;
|
QVariant ret;
|
||||||
if (role == Qt::DisplayRole || role == Qt::EditRole){
|
if (role == Qt::DisplayRole || role == Qt::EditRole){
|
||||||
switch(index.column()){
|
switch(index.column()){
|
||||||
case ID: ret = QString("0x").append(QString::number(device->deviceid, 16)); break;
|
case ID: ret = QString("0x").append(QString::number(node.deviceId, 16)); break;
|
||||||
case MODEL: ret = device->model; break;
|
case MODEL: ret = node.model; break;
|
||||||
case NICKNAME: ret = device->nickname; break;
|
case NICKNAME: ret = node.nickName; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1215,12 +1214,8 @@ int DiveComputerModel::rowCount(const QModelIndex& parent) const
|
||||||
|
|
||||||
void DiveComputerModel::update()
|
void DiveComputerModel::update()
|
||||||
{
|
{
|
||||||
int count = 0;
|
QList<DiveComputerNode> values = dcWorkingMap.values();
|
||||||
struct device_info *nnl = head_of_device_info_list();
|
int count = values.count();
|
||||||
while (nnl) {
|
|
||||||
nnl = nnl->next;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(numRows){
|
if(numRows){
|
||||||
beginRemoveRows(QModelIndex(), 0, numRows-1);
|
beginRemoveRows(QModelIndex(), 0, numRows-1);
|
||||||
|
@ -1245,24 +1240,30 @@ Qt::ItemFlags DiveComputerModel::flags(const QModelIndex& index) const
|
||||||
|
|
||||||
bool DiveComputerModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
bool DiveComputerModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||||
{
|
{
|
||||||
struct device_info *nnl = head_of_device_info_list();
|
QList<DiveComputerNode> values = dcWorkingMap.values();
|
||||||
|
DiveComputerNode node = values.at(index.row());
|
||||||
for(int i = 0; i < index.row(); i++){
|
dcWorkingMap.remove(node.model, node);
|
||||||
nnl = nnl->next;
|
node.nickName = value.toString();
|
||||||
}
|
dcWorkingMap.insert(node.model, node);
|
||||||
|
|
||||||
|
|
||||||
QByteArray v = value.toByteArray();
|
|
||||||
nnl->nickname = strdup(v.data()); // how should I free this before setting a new one?
|
|
||||||
// set_dc_nickname(dive); -> should this be used instead?
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiveComputerModel::remove(const QModelIndex& i)
|
void DiveComputerModel::remove(const QModelIndex& index)
|
||||||
{
|
{
|
||||||
QByteArray model = data(index(i.row(), (int)MODEL)).toByteArray();
|
QList<DiveComputerNode> values = dcWorkingMap.values();
|
||||||
uint32_t deviceid = data(index(i.row(), (int) ID)).toUInt();
|
DiveComputerNode node = values.at(index.row());
|
||||||
remove_dive_computer(model.data(), deviceid);
|
dcWorkingMap.remove(node.model, node);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiveComputerModel::dropWorkingList()
|
||||||
|
{
|
||||||
|
// how do I prevent the memory leak ?
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiveComputerModel::keepWorkingList()
|
||||||
|
{
|
||||||
|
if (dcList.dcMap != dcWorkingMap)
|
||||||
|
mark_divelist_changed(TRUE);
|
||||||
|
dcList.dcMap = dcWorkingMap;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "../dive.h"
|
#include "../dive.h"
|
||||||
#include "../divelist.h"
|
#include "../divelist.h"
|
||||||
|
#include "../qthelper.h"
|
||||||
|
|
||||||
QFont defaultModelFont();
|
QFont defaultModelFont();
|
||||||
|
|
||||||
|
@ -177,20 +178,22 @@ class DiveComputerModel : public QAbstractTableModel
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum {REMOVE, MODEL, ID, NICKNAME, COLUMNS};
|
enum {REMOVE, MODEL, ID, NICKNAME, COLUMNS};
|
||||||
explicit DiveComputerModel(QObject* parent = 0);
|
DiveComputerModel(QMultiMap<QString, DiveComputerNode> &dcMap, QObject *parent = 0);
|
||||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||||
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||||
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||||
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
|
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
|
||||||
void update();
|
void update();
|
||||||
|
void keepWorkingList();
|
||||||
|
void dropWorkingList();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void remove(const QModelIndex& index);
|
void remove(const QModelIndex& index);
|
||||||
private:
|
private:
|
||||||
int numRows;
|
int numRows;
|
||||||
|
QMultiMap<QString, DiveComputerNode> dcWorkingMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "../dive.h"
|
#include "../dive.h"
|
||||||
#include "../profile.h"
|
#include "../profile.h"
|
||||||
#include "../device.h"
|
#include "../device.h"
|
||||||
|
#include "../helpers.h"
|
||||||
|
|
||||||
#include <libdivecomputer/parser.h>
|
#include <libdivecomputer/parser.h>
|
||||||
#include <libdivecomputer/version.h>
|
#include <libdivecomputer/version.h>
|
||||||
|
@ -273,7 +274,7 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
|
||||||
dc = fake_dc(dc);
|
dc = fake_dc(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString nick(get_dc_nickname(dc->model, dc->deviceid));
|
QString nick = get_dc_nickname(dc->model, dc->deviceid);
|
||||||
if (nick.isEmpty())
|
if (nick.isEmpty())
|
||||||
nick = QString(dc->model);
|
nick = QString(dc->model);
|
||||||
|
|
||||||
|
|
82
qthelper.cpp
Normal file
82
qthelper.cpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#include "qthelper.h"
|
||||||
|
|
||||||
|
DiveComputerList::DiveComputerList()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DiveComputerList::~DiveComputerList()
|
||||||
|
{
|
||||||
|
dcMap.~QMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiveComputerNode::operator == (const DiveComputerNode &a) const {
|
||||||
|
return this->model == a.model &&
|
||||||
|
this->deviceId == a.deviceId &&
|
||||||
|
this->firmware == a.firmware &&
|
||||||
|
this->serialNumber == a.serialNumber &&
|
||||||
|
this->nickName == a.nickName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiveComputerNode::operator !=(const DiveComputerNode &a) const {
|
||||||
|
return !(*this == a);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiveComputerNode::changesValues(const DiveComputerNode &b) const
|
||||||
|
{
|
||||||
|
if (this->model != b.model || this->deviceId != b.deviceId) {
|
||||||
|
qDebug("DiveComputerNodes were not for the same DC");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (b.firmware != "" && this->firmware != b.firmware) ||
|
||||||
|
(b.serialNumber != "" && this->serialNumber != b.serialNumber) ||
|
||||||
|
(b.nickName != "" && this->nickName != b.nickName);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DiveComputerNode *DiveComputerList::getExact(QString m, uint32_t d)
|
||||||
|
{
|
||||||
|
if (dcMap.contains(m)) {
|
||||||
|
QList<DiveComputerNode> values = dcMap.values(m);
|
||||||
|
for (int i = 0; i < values.size(); i++)
|
||||||
|
if (values.at(i).deviceId == d)
|
||||||
|
return &values.at(i);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DiveComputerNode *DiveComputerList::get(QString m)
|
||||||
|
{
|
||||||
|
if (dcMap.contains(m)) {
|
||||||
|
QList<DiveComputerNode> values = dcMap.values(m);
|
||||||
|
return &values.at(0);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiveComputerList::addDC(QString m, uint32_t d, QString n, QString s, QString f)
|
||||||
|
{
|
||||||
|
if (m == "" || d == 0)
|
||||||
|
return;
|
||||||
|
const DiveComputerNode *existNode = this->getExact(m, d);
|
||||||
|
DiveComputerNode newNode(m, d, s, f, n);
|
||||||
|
if (existNode) {
|
||||||
|
if (newNode.changesValues(*existNode)) {
|
||||||
|
if (n != "" && existNode->nickName != n)
|
||||||
|
qDebug("new nickname %s for DC model %s deviceId 0x%x", n.toUtf8().data(), m.toUtf8().data(), d);
|
||||||
|
if (f != "" && existNode->firmware != f)
|
||||||
|
qDebug("new firmware version %s for DC model %s deviceId 0x%x", f.toUtf8().data(), m.toUtf8().data(), d);
|
||||||
|
if (s != "" && existNode->serialNumber != s)
|
||||||
|
qDebug("new serial number %s for DC model %s deviceId 0x%x", s.toUtf8().data(), m.toUtf8().data(), d);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dcMap.remove(m, *existNode);
|
||||||
|
}
|
||||||
|
dcMap.insert(m, newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiveComputerList::rmDC(QString m, uint32_t d)
|
||||||
|
{
|
||||||
|
const DiveComputerNode *existNode = this->getExact(m, d);
|
||||||
|
dcMap.remove(m, *existNode);
|
||||||
|
}
|
35
qthelper.h
Normal file
35
qthelper.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef QTHELPER_H
|
||||||
|
#define QTHELPER_H
|
||||||
|
|
||||||
|
#include <QMultiMap>
|
||||||
|
#include <QString>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class DiveComputerNode {
|
||||||
|
public:
|
||||||
|
DiveComputerNode(QString m, uint32_t d, QString s, QString f, QString n) : model(m), deviceId(d), serialNumber(s), firmware(f), nickName(n) {};
|
||||||
|
bool operator ==(const DiveComputerNode &a) const;
|
||||||
|
bool operator !=(const DiveComputerNode &a) const;
|
||||||
|
bool changesValues(const DiveComputerNode &b) const;
|
||||||
|
QString model;
|
||||||
|
uint32_t deviceId;
|
||||||
|
QString serialNumber;
|
||||||
|
QString firmware;
|
||||||
|
QString nickName;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DiveComputerList {
|
||||||
|
public:
|
||||||
|
DiveComputerList();
|
||||||
|
~DiveComputerList();
|
||||||
|
const DiveComputerNode *getExact(QString m, uint32_t d);
|
||||||
|
const DiveComputerNode *get(QString m);
|
||||||
|
void addDC(QString m, uint32_t d, QString n = "", QString s = "", QString f = "");
|
||||||
|
void rmDC(QString m, uint32_t d);
|
||||||
|
DiveComputerNode matchDC(QString m, uint32_t d);
|
||||||
|
DiveComputerNode matchModel(QString m);
|
||||||
|
QMultiMap<QString, struct DiveComputerNode> dcMap;
|
||||||
|
QMultiMap<QString, struct DiveComputerNode> dcWorkingMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QTHELPER_H
|
27
save-xml.c
27
save-xml.c
|
@ -512,24 +512,20 @@ static void save_trip(FILE *f, dive_trip_t *trip)
|
||||||
fprintf(f, "</trip>\n");
|
fprintf(f, "</trip>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_one_device(FILE *f, struct device_info *info)
|
static void save_one_device(FILE *f, const char * model, uint32_t deviceid,
|
||||||
|
const char *nickname, const char *serial_nr, const char *firmware)
|
||||||
{
|
{
|
||||||
const char *nickname, *serial_nr, *firmware;
|
|
||||||
|
|
||||||
/* Nicknames that are empty or the same as the device model are not interesting */
|
/* Nicknames that are empty or the same as the device model are not interesting */
|
||||||
nickname = info->nickname;
|
|
||||||
if (nickname) {
|
if (nickname) {
|
||||||
if (!*nickname || !strcmp(info->model, nickname))
|
if (!*nickname || !strcmp(model, nickname))
|
||||||
nickname = NULL;
|
nickname = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Serial numbers that are empty are not interesting */
|
/* Serial numbers that are empty are not interesting */
|
||||||
serial_nr = info->serial_nr;
|
|
||||||
if (serial_nr && !*serial_nr)
|
if (serial_nr && !*serial_nr)
|
||||||
serial_nr = NULL;
|
serial_nr = NULL;
|
||||||
|
|
||||||
/* Firmware strings that are empty are not interesting */
|
/* Firmware strings that are empty are not interesting */
|
||||||
firmware = info->firmware;
|
|
||||||
if (firmware && !*firmware)
|
if (firmware && !*firmware)
|
||||||
firmware = NULL;
|
firmware = NULL;
|
||||||
|
|
||||||
|
@ -538,25 +534,14 @@ static void save_one_device(FILE *f, struct device_info *info)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(f, "<divecomputerid");
|
fprintf(f, "<divecomputerid");
|
||||||
show_utf8(f, info->model, " model='", "'", 1);
|
show_utf8(f, model, " model='", "'", 1);
|
||||||
fprintf(f, " deviceid='%08x'", info->deviceid);
|
fprintf(f, " deviceid='%08x'", deviceid);
|
||||||
show_utf8(f, serial_nr, " serial='", "'", 1);
|
show_utf8(f, serial_nr, " serial='", "'", 1);
|
||||||
show_utf8(f, firmware, " firmware='", "'", 1);
|
show_utf8(f, firmware, " firmware='", "'", 1);
|
||||||
show_utf8(f, nickname, " nickname='", "'", 1);
|
show_utf8(f, nickname, " nickname='", "'", 1);
|
||||||
fprintf(f, "/>\n");
|
fprintf(f, "/>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_device_info(FILE *f)
|
|
||||||
{
|
|
||||||
struct device_info *info;
|
|
||||||
|
|
||||||
info = head_of_device_info_list();
|
|
||||||
while (info) {
|
|
||||||
save_one_device(f, info);
|
|
||||||
info = info->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VERSION 2
|
#define VERSION 2
|
||||||
|
|
||||||
void save_dives(const char *filename)
|
void save_dives(const char *filename)
|
||||||
|
@ -578,7 +563,7 @@ void save_dives_logic(const char *filename, const gboolean select_only)
|
||||||
fprintf(f, "<divelog program='subsurface' version='%d'>\n<settings>\n", VERSION);
|
fprintf(f, "<divelog program='subsurface' version='%d'>\n<settings>\n", VERSION);
|
||||||
|
|
||||||
/* save the dive computer nicknames, if any */
|
/* save the dive computer nicknames, if any */
|
||||||
save_device_info(f);
|
call_for_each_dc(f, save_one_device);
|
||||||
if (autogroup)
|
if (autogroup)
|
||||||
fprintf(f, "<autogroup state='1' />\n");
|
fprintf(f, "<autogroup state='1' />\n");
|
||||||
fprintf(f, "</settings>\n<dives>\n");
|
fprintf(f, "</settings>\n<dives>\n");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue