diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2013-06-17 15:58:26 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-06-18 00:24:28 -0700 |
commit | 29b242c70349cbd67aacc3e4f1206630d22c54eb (patch) | |
tree | 21edbec2770ddf9fb9eb333429c013aefca2f99d | |
parent | 14ccbbf6e87b69267426ae69c402c1bae70ec5d5 (diff) | |
download | subsurface-29b242c70349cbd67aacc3e4f1206630d22c54eb.tar.gz |
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>
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | device.c | 113 | ||||
-rw-r--r-- | device.h | 19 | ||||
-rw-r--r-- | dive.h | 1 | ||||
-rw-r--r-- | divelist.c | 2 | ||||
-rw-r--r-- | helpers.h | 4 | ||||
-rw-r--r-- | libdivecomputer.c | 19 | ||||
-rw-r--r-- | parse-xml.c | 13 | ||||
-rw-r--r-- | qt-gui.cpp | 67 | ||||
-rw-r--r-- | qt-ui/divecomputermanagementdialog.cpp | 32 | ||||
-rw-r--r-- | qt-ui/divecomputermanagementdialog.h | 5 | ||||
-rw-r--r-- | qt-ui/divecomputermanagementdialog.ui | 47 | ||||
-rw-r--r-- | qt-ui/mainwindow.cpp | 1 | ||||
-rw-r--r-- | qt-ui/models.cpp | 63 | ||||
-rw-r--r-- | qt-ui/models.h | 21 | ||||
-rw-r--r-- | qt-ui/profilegraphics.cpp | 3 | ||||
-rw-r--r-- | qthelper.cpp | 82 | ||||
-rw-r--r-- | qthelper.h | 35 | ||||
-rw-r--r-- | save-xml.c | 27 |
19 files changed, 302 insertions, 253 deletions
@@ -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 \ @@ -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]; @@ -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 } @@ -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 *); diff --git a/divelist.c b/divelist.c index 606c30e01..6e3fc598e 100644 --- a/divelist.c +++ b/divelist.c @@ -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 */ diff --git a/libdivecomputer.c b/libdivecomputer.c index 6397018a3..2638376b8 100644 --- a/libdivecomputer.c +++ b/libdivecomputer.c @@ -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; } diff --git a/parse-xml.c b/parse-xml.c index ba952957f..aa2f737ec 100644 --- a/parse-xml.c +++ b/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(); } diff --git a/qt-gui.cpp b/qt-gui.cpp index e15e4128e..10b7d8086 100644 --- a/qt-gui.cpp +++ b/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" diff --git a/qt-ui/divecomputermanagementdialog.cpp b/qt-ui/divecomputermanagementdialog.cpp index 4d9770a4d..2a1bb8bff 100644 --- a/qt-ui/divecomputermanagementdialog.cpp +++ b/qt-ui/divecomputermanagementdialog.cpp @@ -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(); +} diff --git a/qt-ui/divecomputermanagementdialog.h b/qt-ui/divecomputermanagementdialog.h index e10a96db2..72d48cd2a 100644 --- a/qt-ui/divecomputermanagementdialog.h +++ b/qt-ui/divecomputermanagementdialog.h @@ -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
\ No newline at end of file +#endif diff --git a/qt-ui/divecomputermanagementdialog.ui b/qt-ui/divecomputermanagementdialog.ui index ae011fc9c..8b916f925 100644 --- a/qt-ui/divecomputermanagementdialog.ui +++ b/qt-ui/divecomputermanagementdialog.ui @@ -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> diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index f477a0d4f..2ab3a6771 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -206,6 +206,7 @@ void MainWindow::on_actionDownloadWeb_triggered() void MainWindow::on_actionEditDeviceNames_triggered() { + DiveComputerManagementDialog::instance()->init(); DiveComputerManagementDialog::instance()->update(); DiveComputerManagementDialog::instance()->show(); } diff --git a/qt-ui/models.cpp b/qt-ui/models.cpp index 9e076930d..c56fa2f44 100644 --- a/qt-ui/models.cpp +++ b/qt-ui/models.cpp @@ -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; +} diff --git a/qt-ui/models.h b/qt-ui/models.h index b61c79cd6..e371ce1ea 100644 --- a/qt-ui/models.h +++ b/qt-ui/models.h @@ -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 diff --git a/qt-ui/profilegraphics.cpp b/qt-ui/profilegraphics.cpp index 126690750..e580a2b44 100644 --- a/qt-ui/profilegraphics.cpp +++ b/qt-ui/profilegraphics.cpp @@ -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); diff --git a/qthelper.cpp b/qthelper.cpp new file mode 100644 index 000000000..9c74a74cf --- /dev/null +++ b/qthelper.cpp @@ -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); +} diff --git a/qthelper.h b/qthelper.h new file mode 100644 index 000000000..fcbcbff9a --- /dev/null +++ b/qthelper.h @@ -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 diff --git a/save-xml.c b/save-xml.c index 0e770ec62..454da8484 100644 --- a/save-xml.c +++ b/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"); |