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 \
|
||||
libdivecomputer.c \
|
||||
qt-gui.cpp \
|
||||
qthelper.cpp \
|
||||
qt-ui/divelistview.cpp \
|
||||
qt-ui/maintab.cpp \
|
||||
qt-ui/mainwindow.cpp \
|
||||
|
|
113
device.c
113
device.c
|
@ -2,119 +2,6 @@
|
|||
#include "dive.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)
|
||||
{
|
||||
static struct sample fake[4];
|
||||
|
|
19
device.h
19
device.h
|
@ -6,23 +6,10 @@
|
|||
extern "C" {
|
||||
#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 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
|
||||
}
|
||||
|
|
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 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 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)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
int preexisting = dive_table.preexisting;
|
||||
struct dive *last;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <QString>
|
||||
#include "dive.h"
|
||||
#include "qthelper.h"
|
||||
|
||||
QString get_depth_string(depth_t depth, 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_device(const char *name);
|
||||
QString getSubsurfaceDataPath(QString folderToFind);
|
||||
extern const QString get_dc_nickname(const char *model, uint32_t deviceid);
|
||||
|
||||
extern DiveComputerList dcList;
|
||||
|
||||
#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)
|
||||
{
|
||||
struct device_info *info;
|
||||
unsigned int serial = devinfo->serial;
|
||||
char serial_nr[13] = "";
|
||||
char firmware[13] = "";
|
||||
|
||||
first_temp_is_air = 1;
|
||||
|
||||
serial = undo_libdivecomputer_suunto_nr_changes(serial);
|
||||
|
||||
info = create_device_info(devdata->model, devdata->deviceid);
|
||||
if (!info)
|
||||
return serial;
|
||||
|
||||
if (!info->serial_nr && serial) {
|
||||
char serial_nr[13];
|
||||
|
||||
if (serial) {
|
||||
snprintf(serial_nr, sizeof(serial_nr), "%02d%02d%02d%02d",
|
||||
(devinfo->serial >> 24) & 0xff,
|
||||
(devinfo->serial >> 16) & 0xff,
|
||||
(devinfo->serial >> 8) & 0xff,
|
||||
(devinfo->serial >> 0) & 0xff);
|
||||
info->serial_nr = strdup(serial_nr);
|
||||
}
|
||||
|
||||
if (!info->firmware && devinfo->firmware) {
|
||||
char firmware[13];
|
||||
if (devinfo->firmware) {
|
||||
snprintf(firmware, sizeof(firmware), "%d.%d.%d",
|
||||
(devinfo->firmware >> 16) & 0xff,
|
||||
(devinfo->firmware >> 8) & 0xff,
|
||||
(devinfo->firmware >> 0) & 0xff);
|
||||
info->firmware = strdup(firmware);
|
||||
}
|
||||
create_device_node(devdata->model, devdata->deviceid, serial_nr, firmware, "");
|
||||
|
||||
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)
|
||||
{
|
||||
struct device_info *info;
|
||||
|
||||
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);
|
||||
}
|
||||
create_device_node(cur_settings.dc.model, cur_settings.dc.deviceid, cur_settings.dc.serial_nr,
|
||||
cur_settings.dc.firmware, cur_settings.dc.nickname);
|
||||
reset_dc_settings();
|
||||
}
|
||||
|
||||
|
|
67
qt-gui.cpp
67
qt-gui.cpp
|
@ -21,6 +21,7 @@
|
|||
#include "libdivecomputer.h"
|
||||
#include "qt-ui/mainwindow.h"
|
||||
#include "helpers.h"
|
||||
#include "qthelper.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFileDialog>
|
||||
|
@ -32,10 +33,13 @@
|
|||
#include <QDesktopWidget>
|
||||
#include <QStyle>
|
||||
#include <QDebug>
|
||||
#include <QMap>
|
||||
#include <QMultiMap>
|
||||
|
||||
const char *default_dive_computer_vendor;
|
||||
const char *default_dive_computer_product;
|
||||
const char *default_dive_computer_device;
|
||||
DiveComputerList dcList;
|
||||
|
||||
class Translator: public QTranslator
|
||||
{
|
||||
|
@ -142,30 +146,15 @@ void set_filename(const char *filename, gboolean force)
|
|||
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);
|
||||
if (known) {
|
||||
if (known->nickname && *known->nickname)
|
||||
return known->nickname;
|
||||
else
|
||||
return known->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);
|
||||
const DiveComputerNode *existNode = dcList.getExact(model, deviceid);
|
||||
if (!existNode)
|
||||
return QString("");
|
||||
if (existNode->nickName != "")
|
||||
return existNode->nickName;
|
||||
else
|
||||
return model;
|
||||
}
|
||||
|
||||
void set_dc_nickname(struct dive *dive)
|
||||
|
@ -176,16 +165,20 @@ void set_dc_nickname(struct dive *dive)
|
|||
struct divecomputer *dc = &dive->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
|
||||
struct device_info *nn_entry = get_different_device_info(dc->model, dc->deviceid);
|
||||
if (nn_entry) {
|
||||
const DiveComputerNode *existNode = dcList.get(dc->model);
|
||||
if (existNode) {
|
||||
// we already have this model but a different deviceid
|
||||
QString simpleNick(dc->model);
|
||||
simpleNick.append(" (").append(QString::number(dc->deviceid, 16)).append(")");
|
||||
remember_dc(dc->model, dc->deviceid, simpleNick.toUtf8().data());
|
||||
if (dc->deviceid == 0)
|
||||
simpleNick.append(" (unknown deviceid)");
|
||||
else
|
||||
simpleNick.append(" (").append(QString::number(dc->deviceid, 16)).append(")");
|
||||
dcList.addDC(dc->model, dc->deviceid, simpleNick);
|
||||
} else {
|
||||
remember_dc(dc->model, dc->deviceid, NULL);
|
||||
dcList.addDC(dc->model, dc->deviceid);
|
||||
}
|
||||
}
|
||||
dc = dc->next;
|
||||
|
@ -330,4 +323,20 @@ QString getSubsurfaceDataPath(QString folderToFind)
|
|||
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"
|
||||
|
|
|
@ -3,16 +3,26 @@
|
|||
#include "ui_divecomputermanagementdialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include <QMessageBox>
|
||||
#include "../qthelper.h"
|
||||
#include "../helpers.h"
|
||||
|
||||
DiveComputerManagementDialog::DiveComputerManagementDialog(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f)
|
||||
, ui( new Ui::DiveComputerManagementDialog())
|
||||
DiveComputerManagementDialog::DiveComputerManagementDialog(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f),
|
||||
ui( new Ui::DiveComputerManagementDialog()),
|
||||
model(0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
model = new DiveComputerModel();
|
||||
ui->tableView->setModel(model);
|
||||
init();
|
||||
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()
|
||||
{
|
||||
static DiveComputerManagementDialog *self = new DiveComputerManagementDialog();
|
||||
|
@ -44,3 +54,17 @@ void DiveComputerManagementDialog::tryRemove(const QModelIndex& 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:
|
||||
static DiveComputerManagementDialog *instance();
|
||||
void update();
|
||||
void init();
|
||||
|
||||
public slots:
|
||||
void tryRemove(const QModelIndex& index);
|
||||
void accept();
|
||||
void reject();
|
||||
|
||||
private:
|
||||
explicit DiveComputerManagementDialog(QWidget* parent = 0, Qt::WindowFlags f = 0);
|
||||
|
@ -24,4 +27,4 @@ private:
|
|||
DiveComputerModel *model;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
<string>Edit Dive Computer Nicknames</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
|
@ -21,8 +21,51 @@
|
|||
</attribute>
|
||||
</widget>
|
||||
</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>
|
||||
</widget>
|
||||
<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>
|
||||
|
|
|
@ -206,6 +206,7 @@ void MainWindow::on_actionDownloadWeb_triggered()
|
|||
|
||||
void MainWindow::on_actionEditDeviceNames_triggered()
|
||||
{
|
||||
DiveComputerManagementDialog::instance()->init();
|
||||
DiveComputerManagementDialog::instance()->update();
|
||||
DiveComputerManagementDialog::instance()->show();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "../helpers.h"
|
||||
#include "../dive.h"
|
||||
#include "../device.h"
|
||||
|
||||
#include "../qthelper.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#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
|
||||
|
@ -1188,17 +1189,15 @@ QVariant DiveComputerModel::headerData(int section, Qt::Orientation orientation,
|
|||
|
||||
QVariant DiveComputerModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
struct device_info *device = head_of_device_info_list();
|
||||
for(int i = 0; i < index.row(); i++){
|
||||
device = device->next;
|
||||
}
|
||||
QList<DiveComputerNode> values = dcWorkingMap.values();
|
||||
DiveComputerNode node = values.at(index.row());
|
||||
|
||||
QVariant ret;
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole){
|
||||
switch(index.column()){
|
||||
case ID: ret = QString("0x").append(QString::number(device->deviceid, 16)); break;
|
||||
case MODEL: ret = device->model; break;
|
||||
case NICKNAME: ret = device->nickname; break;
|
||||
case ID: ret = QString("0x").append(QString::number(node.deviceId, 16)); break;
|
||||
case MODEL: ret = node.model; break;
|
||||
case NICKNAME: ret = node.nickName; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1215,12 +1214,8 @@ int DiveComputerModel::rowCount(const QModelIndex& parent) const
|
|||
|
||||
void DiveComputerModel::update()
|
||||
{
|
||||
int count = 0;
|
||||
struct device_info *nnl = head_of_device_info_list();
|
||||
while (nnl) {
|
||||
nnl = nnl->next;
|
||||
count++;
|
||||
}
|
||||
QList<DiveComputerNode> values = dcWorkingMap.values();
|
||||
int count = values.count();
|
||||
|
||||
if(numRows){
|
||||
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)
|
||||
{
|
||||
struct device_info *nnl = head_of_device_info_list();
|
||||
|
||||
for(int i = 0; i < index.row(); i++){
|
||||
nnl = nnl->next;
|
||||
}
|
||||
|
||||
|
||||
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?
|
||||
|
||||
QList<DiveComputerNode> values = dcWorkingMap.values();
|
||||
DiveComputerNode node = values.at(index.row());
|
||||
dcWorkingMap.remove(node.model, node);
|
||||
node.nickName = value.toString();
|
||||
dcWorkingMap.insert(node.model, node);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiveComputerModel::remove(const QModelIndex& i)
|
||||
void DiveComputerModel::remove(const QModelIndex& index)
|
||||
{
|
||||
QByteArray model = data(index(i.row(), (int)MODEL)).toByteArray();
|
||||
uint32_t deviceid = data(index(i.row(), (int) ID)).toUInt();
|
||||
remove_dive_computer(model.data(), deviceid);
|
||||
QList<DiveComputerNode> values = dcWorkingMap.values();
|
||||
DiveComputerNode node = values.at(index.row());
|
||||
dcWorkingMap.remove(node.model, node);
|
||||
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 "../divelist.h"
|
||||
#include "../qthelper.h"
|
||||
|
||||
QFont defaultModelFont();
|
||||
|
||||
|
@ -177,20 +178,22 @@ class DiveComputerModel : public QAbstractTableModel
|
|||
Q_OBJECT
|
||||
public:
|
||||
enum {REMOVE, MODEL, ID, NICKNAME, COLUMNS};
|
||||
explicit DiveComputerModel(QObject* parent = 0);
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
|
||||
DiveComputerModel(QMultiMap<QString, DiveComputerNode> &dcMap, QObject *parent = 0);
|
||||
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
|
||||
void update();
|
||||
|
||||
void keepWorkingList();
|
||||
void dropWorkingList();
|
||||
|
||||
public slots:
|
||||
void remove(const QModelIndex& index);
|
||||
private:
|
||||
int numRows;
|
||||
|
||||
QMultiMap<QString, DiveComputerNode> dcWorkingMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "../dive.h"
|
||||
#include "../profile.h"
|
||||
#include "../device.h"
|
||||
#include "../helpers.h"
|
||||
|
||||
#include <libdivecomputer/parser.h>
|
||||
#include <libdivecomputer/version.h>
|
||||
|
@ -273,7 +274,7 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
|
|||
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())
|
||||
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");
|
||||
}
|
||||
|
||||
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 */
|
||||
nickname = info->nickname;
|
||||
if (nickname) {
|
||||
if (!*nickname || !strcmp(info->model, nickname))
|
||||
if (!*nickname || !strcmp(model, nickname))
|
||||
nickname = NULL;
|
||||
}
|
||||
|
||||
/* Serial numbers that are empty are not interesting */
|
||||
serial_nr = info->serial_nr;
|
||||
if (serial_nr && !*serial_nr)
|
||||
serial_nr = NULL;
|
||||
|
||||
/* Firmware strings that are empty are not interesting */
|
||||
firmware = info->firmware;
|
||||
if (firmware && !*firmware)
|
||||
firmware = NULL;
|
||||
|
||||
|
@ -538,25 +534,14 @@ static void save_one_device(FILE *f, struct device_info *info)
|
|||
return;
|
||||
|
||||
fprintf(f, "<divecomputerid");
|
||||
show_utf8(f, info->model, " model='", "'", 1);
|
||||
fprintf(f, " deviceid='%08x'", info->deviceid);
|
||||
show_utf8(f, model, " model='", "'", 1);
|
||||
fprintf(f, " deviceid='%08x'", deviceid);
|
||||
show_utf8(f, serial_nr, " serial='", "'", 1);
|
||||
show_utf8(f, firmware, " firmware='", "'", 1);
|
||||
show_utf8(f, nickname, " nickname='", "'", 1);
|
||||
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
|
||||
|
||||
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);
|
||||
|
||||
/* save the dive computer nicknames, if any */
|
||||
save_device_info(f);
|
||||
call_for_each_dc(f, save_one_device);
|
||||
if (autogroup)
|
||||
fprintf(f, "<autogroup state='1' />\n");
|
||||
fprintf(f, "</settings>\n<dives>\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue