cleanup: fold core/divecomputer.cpp into core/device.c

core/device.h was declaring a number of functions that were related
to divecomputers (dcs): creating a fake dc for manually entered dives
and registering / accessing dc nicknames. On could argue whether
these should be lumped together, but it is what it is.

However, part of that was implemented in C++/Qt code in a separate
core/divecomputer.cpp file. Some function therein where only
accessible to C++ and declared in core/divecomputer.h.

All in all, a big mess. Let's simply combine the files and
conditionally compile the C++-only functions depending on
the __cplusplus define.

Yes, that means turning device.c into device.cpp. A brave soul
might turn the C++/Qt code into C code if they whish later on.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2020-09-13 19:08:41 +02:00 committed by Dirk Hohndel
parent fcdb48779b
commit a01ab81713
8 changed files with 200 additions and 216 deletions

View file

@ -57,15 +57,13 @@ set(SUBSURFACE_CORE_LIB_SRCS
datatrak.h datatrak.h
deco.c deco.c
deco.h deco.h
device.c device.cpp
device.h device.h
devicedetails.cpp devicedetails.cpp
devicedetails.h devicedetails.h
display.h display.h
dive.c dive.c
dive.h dive.h
divecomputer.cpp
divecomputer.h
divefilter.cpp divefilter.cpp
divefilter.h divefilter.h
divelist.c divelist.c

View file

@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include "ssrf.h" #include "ssrf.h"
#include <string.h>
#include "dive.h" #include "dive.h"
#include "subsurface-string.h" #include "subsurface-string.h"
#include "device.h" #include "device.h"
#include "errorhelper.h" // for verbose flag
#include "core/settings/qPrefDiveComputer.h"
/* /*
* Good fake dive profiles are hard. * Good fake dive profiles are hard.
@ -111,7 +112,7 @@ static void fill_samples_no_avg(struct sample *s, int max_d, int max_t, double s
} }
} }
void fake_dc(struct divecomputer *dc) extern "C" void fake_dc(struct divecomputer *dc)
{ {
alloc_samples(dc, 6); alloc_samples(dc, 6);
struct sample *fake = dc->sample; struct sample *fake = dc->sample;
@ -190,12 +191,9 @@ void fake_dc(struct divecomputer *dc)
} }
static void match_id(void *_dc, const char *model, uint32_t deviceid, static void match_id(void *_dc, const char *model, uint32_t deviceid,
const char *nickname, const char *serial, const char *firmware) const char *, const char *serial, const char *firmware)
{ {
// here nickname is unused struct divecomputer *dc = (divecomputer *)_dc;
UNUSED(nickname);
struct divecomputer *dc = _dc;
if (dc->deviceid != deviceid) if (dc->deviceid != deviceid)
return; return;
@ -212,10 +210,168 @@ static void match_id(void *_dc, const char *model, uint32_t deviceid,
* When setting the device ID, we also fill in the * When setting the device ID, we also fill in the
* serial number and firmware version data * serial number and firmware version data
*/ */
void set_dc_deviceid(struct divecomputer *dc, unsigned int deviceid) extern "C" void set_dc_deviceid(struct divecomputer *dc, unsigned int deviceid)
{ {
if (deviceid) { if (deviceid) {
dc->deviceid = deviceid; dc->deviceid = deviceid;
call_for_each_dc(dc, match_id, false); call_for_each_dc(dc, match_id, false);
} }
} }
DiveComputerList dcList;
bool DiveComputerNode::operator==(const DiveComputerNode &a) const
{
return model == a.model &&
deviceId == a.deviceId &&
firmware == a.firmware &&
serialNumber == a.serialNumber &&
nickName == a.nickName;
}
bool DiveComputerNode::operator!=(const DiveComputerNode &a) const
{
return !(*this == a);
}
bool DiveComputerNode::operator<(const DiveComputerNode &a) const
{
return std::tie(model, deviceId) < std::tie(a.model, a.deviceId);
}
const DiveComputerNode *DiveComputerList::getExact(const QString &m, uint32_t d)
{
auto it = std::lower_bound(dcs.begin(), dcs.end(), DiveComputerNode{m, d, {}, {}, {}});
return it != dcs.end() && it->model == m && it->deviceId == d ? &*it : NULL;
}
const DiveComputerNode *DiveComputerList::get(const QString &m)
{
auto it = std::lower_bound(dcs.begin(), dcs.end(), DiveComputerNode{m, 0, {}, {}, {}});
return it != dcs.end() && it->model == m ? &*it : NULL;
}
void DiveComputerNode::showchanges(const QString &n, const QString &s, const QString &f) const
{
if (nickName != n && !n.isEmpty())
qDebug("new nickname %s for DC model %s deviceId 0x%x", qPrintable(n), qPrintable(model), deviceId);
if (serialNumber != s && !s.isEmpty())
qDebug("new serial number %s for DC model %s deviceId 0x%x", qPrintable(s), qPrintable(model), deviceId);
if (firmware != f && !f.isEmpty())
qDebug("new firmware version %s for DC model %s deviceId 0x%x", qPrintable(f), qPrintable(model), deviceId);
}
void DiveComputerList::addDC(QString m, uint32_t d, QString n, QString s, QString f)
{
if (m.isEmpty() || d == 0)
return;
auto it = std::lower_bound(dcs.begin(), dcs.end(), DiveComputerNode{m, d, {}, {}, {}});
if (it != dcs.end() && it->model == m && it->deviceId == d) {
// debugging: show changes
if (verbose)
it->showchanges(n, s, f);
// Update any non-existent fields from the old entry
if (!n.isEmpty())
it->nickName = n;
if (!s.isEmpty())
it->serialNumber = s;
if (!f.isEmpty())
it->firmware = f;
} else {
dcs.insert(it, DiveComputerNode{m, d, s, f, n});
}
}
extern "C" 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);
}
extern "C" void clear_device_nodes()
{
dcList.dcs.clear();
}
static bool compareDCById(const DiveComputerNode &a, const DiveComputerNode &b)
{
return a.deviceId < b.deviceId;
}
extern "C" void call_for_each_dc (void *f, void (*callback)(void *, const char *, uint32_t, const char *, const char *, const char *),
bool select_only)
{
QVector<DiveComputerNode> values = dcList.dcs;
std::sort(values.begin(), values.end(), compareDCById);
for (const DiveComputerNode &node : values) {
bool found = false;
if (select_only) {
int j;
struct dive *d;
for_each_dive (j, d) {
struct divecomputer *dc;
if (!d->selected)
continue;
for_each_dc (d, dc) {
if (dc->deviceid == node.deviceId) {
found = true;
break;
}
}
if (found)
break;
}
} else {
found = true;
}
if (found)
callback(f, qPrintable(node.model), node.deviceId, qPrintable(node.nickName),
qPrintable(node.serialNumber), qPrintable(node.firmware));
}
}
extern "C" int is_default_dive_computer(const char *vendor, const char *product)
{
return qPrefDiveComputer::vendor() == vendor && qPrefDiveComputer::product() == product;
}
extern "C" int is_default_dive_computer_device(const char *name)
{
return qPrefDiveComputer::device() == name;
}
extern "C" void set_dc_nickname(struct dive *dive)
{
if (!dive)
return;
struct divecomputer *dc;
for_each_dc (dive, dc) {
if (!empty_string(dc->model) && dc->deviceid &&
!dcList.getExact(dc->model, dc->deviceid)) {
// we don't have this one, yet
const DiveComputerNode *existNode = dcList.get(dc->model);
if (existNode) {
// we already have this model but a different deviceid
QString simpleNick(dc->model);
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 {
dcList.addDC(dc->model, dc->deviceid);
}
}
}
}
QString get_dc_nickname(const struct divecomputer *dc)
{
const DiveComputerNode *existNode = dcList.getExact(dc->model, dc->deviceid);
if (existNode && !existNode->nickName.isEmpty())
return existNode->nickName;
else
return dc->model;
}

View file

@ -21,4 +21,37 @@ extern void clear_device_nodes();
} }
#endif #endif
// Functions and global variables that are only available to C++ code
#ifdef __cplusplus
#include <QString>
#include <QVector>
class DiveComputerNode {
public:
bool operator==(const DiveComputerNode &a) const;
bool operator!=(const DiveComputerNode &a) const;
bool operator<(const DiveComputerNode &a) const;
void showchanges(const QString &n, const QString &s, const QString &f) const;
QString model;
uint32_t deviceId;
QString serialNumber;
QString firmware;
QString nickName;
};
class DiveComputerList {
public:
const DiveComputerNode *getExact(const QString &m, uint32_t d);
const DiveComputerNode *get(const QString &m);
void addDC(QString m, uint32_t d, QString n = QString(), QString s = QString(), QString f = QString());
// Keep the dive computers in a vector sorted by (model, deviceId)
QVector<DiveComputerNode> dcs;
};
QString get_dc_nickname(const struct divecomputer *dc);
extern DiveComputerList dcList;
#endif
#endif // DEVICE_H #endif // DEVICE_H

View file

@ -1,164 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "divecomputer.h"
#include "dive.h"
#include "errorhelper.h"
#include "core/settings/qPrefDiveComputer.h"
#include "subsurface-string.h"
DiveComputerList dcList;
bool DiveComputerNode::operator==(const DiveComputerNode &a) const
{
return model == a.model &&
deviceId == a.deviceId &&
firmware == a.firmware &&
serialNumber == a.serialNumber &&
nickName == a.nickName;
}
bool DiveComputerNode::operator!=(const DiveComputerNode &a) const
{
return !(*this == a);
}
bool DiveComputerNode::operator<(const DiveComputerNode &a) const
{
return std::tie(model, deviceId) < std::tie(a.model, a.deviceId);
}
const DiveComputerNode *DiveComputerList::getExact(const QString &m, uint32_t d)
{
auto it = std::lower_bound(dcs.begin(), dcs.end(), DiveComputerNode{m, d, {}, {}, {}});
return it != dcs.end() && it->model == m && it->deviceId == d ? &*it : NULL;
}
const DiveComputerNode *DiveComputerList::get(const QString &m)
{
auto it = std::lower_bound(dcs.begin(), dcs.end(), DiveComputerNode{m, 0, {}, {}, {}});
return it != dcs.end() && it->model == m ? &*it : NULL;
}
void DiveComputerNode::showchanges(const QString &n, const QString &s, const QString &f) const
{
if (nickName != n && !n.isEmpty())
qDebug("new nickname %s for DC model %s deviceId 0x%x", qPrintable(n), qPrintable(model), deviceId);
if (serialNumber != s && !s.isEmpty())
qDebug("new serial number %s for DC model %s deviceId 0x%x", qPrintable(s), qPrintable(model), deviceId);
if (firmware != f && !f.isEmpty())
qDebug("new firmware version %s for DC model %s deviceId 0x%x", qPrintable(f), qPrintable(model), deviceId);
}
void DiveComputerList::addDC(QString m, uint32_t d, QString n, QString s, QString f)
{
if (m.isEmpty() || d == 0)
return;
auto it = std::lower_bound(dcs.begin(), dcs.end(), DiveComputerNode{m, d, {}, {}, {}});
if (it != dcs.end() && it->model == m && it->deviceId == d) {
// debugging: show changes
if (verbose)
it->showchanges(n, s, f);
// Update any non-existent fields from the old entry
if (!n.isEmpty())
it->nickName = n;
if (!s.isEmpty())
it->serialNumber = s;
if (!f.isEmpty())
it->firmware = f;
} else {
dcs.insert(it, DiveComputerNode{m, d, s, f, n});
}
}
extern "C" 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);
}
extern "C" void clear_device_nodes()
{
dcList.dcs.clear();
}
static bool compareDCById(const DiveComputerNode &a, const DiveComputerNode &b)
{
return a.deviceId < b.deviceId;
}
extern "C" void call_for_each_dc (void *f, void (*callback)(void *, const char *, uint32_t, const char *, const char *, const char *),
bool select_only)
{
QVector<DiveComputerNode> values = dcList.dcs;
std::sort(values.begin(), values.end(), compareDCById);
for (const DiveComputerNode &node : values) {
bool found = false;
if (select_only) {
int j;
struct dive *d;
for_each_dive (j, d) {
struct divecomputer *dc;
if (!d->selected)
continue;
for_each_dc (d, dc) {
if (dc->deviceid == node.deviceId) {
found = true;
break;
}
}
if (found)
break;
}
} else {
found = true;
}
if (found)
callback(f, qPrintable(node.model), node.deviceId, qPrintable(node.nickName),
qPrintable(node.serialNumber), qPrintable(node.firmware));
}
}
extern "C" int is_default_dive_computer(const char *vendor, const char *product)
{
return qPrefDiveComputer::vendor() == vendor && qPrefDiveComputer::product() == product;
}
extern "C" int is_default_dive_computer_device(const char *name)
{
return qPrefDiveComputer::device() == name;
}
extern "C" void set_dc_nickname(struct dive *dive)
{
if (!dive)
return;
struct divecomputer *dc;
for_each_dc (dive, dc) {
if (!empty_string(dc->model) && dc->deviceid &&
!dcList.getExact(dc->model, dc->deviceid)) {
// we don't have this one, yet
const DiveComputerNode *existNode = dcList.get(dc->model);
if (existNode) {
// we already have this model but a different deviceid
QString simpleNick(dc->model);
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 {
dcList.addDC(dc->model, dc->deviceid);
}
}
}
}
QString get_dc_nickname(const struct divecomputer *dc)
{
const DiveComputerNode *existNode = dcList.getExact(dc->model, dc->deviceid);
if (existNode && !existNode->nickName.isEmpty())
return existNode->nickName;
else
return dc->model;
}

View file

@ -1,35 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef DIVECOMPUTER_H
#define DIVECOMPUTER_H
#include <QString>
#include <QVector>
#include <stdint.h>
class DiveComputerNode {
public:
bool operator==(const DiveComputerNode &a) const;
bool operator!=(const DiveComputerNode &a) const;
bool operator<(const DiveComputerNode &a) const;
void showchanges(const QString &n, const QString &s, const QString &f) const;
QString model;
uint32_t deviceId;
QString serialNumber;
QString firmware;
QString nickName;
};
class DiveComputerList {
public:
const DiveComputerNode *getExact(const QString &m, uint32_t d);
const DiveComputerNode *get(const QString &m);
void addDC(QString m, uint32_t d, QString n = QString(), QString s = QString(), QString f = QString());
// Keep the dive computers in a vector sorted by (model, deviceId)
QVector<DiveComputerNode> dcs;
};
QString get_dc_nickname(const struct divecomputer *dc);
extern DiveComputerList dcList;
#endif

View file

@ -36,7 +36,6 @@ SOURCES += ../../subsurface-mobile-main.cpp \
../../core/checkcloudconnection.cpp \ ../../core/checkcloudconnection.cpp \
../../core/color.cpp \ ../../core/color.cpp \
../../core/configuredivecomputer.cpp \ ../../core/configuredivecomputer.cpp \
../../core/divecomputer.cpp \
../../core/divelogexportlogic.cpp \ ../../core/divelogexportlogic.cpp \
../../core/divesitehelpers.cpp \ ../../core/divesitehelpers.cpp \
../../core/errorhelper.c \ ../../core/errorhelper.c \
@ -52,7 +51,7 @@ SOURCES += ../../subsurface-mobile-main.cpp \
../../core/subsurfacestartup.c \ ../../core/subsurfacestartup.c \
../../core/ios.cpp \ ../../core/ios.cpp \
../../core/profile.c \ ../../core/profile.c \
../../core/device.c \ ../../core/device.cpp \
../../core/dive.c \ ../../core/dive.c \
../../core/divefilter.cpp \ ../../core/divefilter.cpp \
../../core/divelist.c \ ../../core/divelist.c \
@ -217,7 +216,6 @@ HEADERS += \
../../core/datatrak.h \ ../../core/datatrak.h \
../../core/deco.h \ ../../core/deco.h \
../../core/display.h \ ../../core/display.h \
../../core/divecomputer.h \
../../core/divefilter.h \ ../../core/divefilter.h \
../../core/divelist.h \ ../../core/divelist.h \
../../core/divelogexportlogic.h \ ../../core/divelogexportlogic.h \
@ -232,7 +230,6 @@ HEADERS += \
../../core/metrics.h \ ../../core/metrics.h \
../../core/qt-gui.h \ ../../core/qt-gui.h \
../../core/selection.h \ ../../core/selection.h \
../../core/divecomputer.h \
../../core/sha1.h \ ../../core/sha1.h \
../../core/strndup.h \ ../../core/strndup.h \
../../core/subsurfacestartup.h \ ../../core/subsurfacestartup.h \

View file

@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include "profile-widget/profilewidget2.h" #include "profile-widget/profilewidget2.h"
#include "qt-models/diveplotdatamodel.h" #include "qt-models/diveplotdatamodel.h"
#include "core/divecomputer.h"
#include "core/subsurface-string.h" #include "core/subsurface-string.h"
#include "core/qthelper.h" #include "core/qthelper.h"
#include "core/picture.h" #include "core/picture.h"

View file

@ -3,7 +3,7 @@
#define DIVECOMPUTERMODEL_H #define DIVECOMPUTERMODEL_H
#include "qt-models/cleanertablemodel.h" #include "qt-models/cleanertablemodel.h"
#include "core/divecomputer.h" #include "core/device.h"
class DiveComputerModel : public CleanerTableModel { class DiveComputerModel : public CleanerTableModel {
Q_OBJECT Q_OBJECT