mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-27 20:58:47 +00:00
Import: Add option to sync time on dive computer download
Add an option for users to sync the dive computer time with the PC time every time dives are downloaded. Obviously this will only work on dive computers that have time synchronisation support in libdivecomputer, for other computers a notice is logged. The selection for this option is persisted as a preference. Signed-off-by: Michael Keller <github@ike.ch>
This commit is contained in:
parent
cb410fe1ba
commit
a38ea971a0
18 changed files with 130 additions and 1 deletions
|
@ -1,3 +1,4 @@
|
|||
import: add option to synchronise dive computer time when downloading dives
|
||||
core: fix bug when save sea water salinity given by DC
|
||||
desktop: add option to force firmware update on OSTC4
|
||||
desktop: add column for dive notes to the dive list table
|
||||
|
|
|
@ -374,6 +374,13 @@ of the dive computer (at least for those not charging while connected via USB).
|
|||
- Do *not* check the checkboxes labelled _Save libdivecomputer logfile_ and
|
||||
_Save libdivecomputer dumpfile_. These are only used as diagnostic tools
|
||||
when there are problems with downloads(see below).
|
||||
|
||||
- With some dive computers it is possible to adjust the clock on the dive
|
||||
computer based on the PC clock. This can be very helpful when dealing with
|
||||
daylight savings time changes, or when travelling between different time
|
||||
zones. In order to synchronise the dive computer clock with the PC clock
|
||||
every time dives are imported, check _Sync dive computer time_.
|
||||
|
||||
- Then select the _Download_ button.
|
||||
With communication established, you can see how the data are
|
||||
retrieved from the dive computer.
|
||||
|
@ -398,6 +405,7 @@ of the dive computer (at least for those not charging while connected via USB).
|
|||
(Puck Pro)". Refer to the text in the box below.
|
||||
|
||||
|
||||
|
||||
****
|
||||
*PROBLEMS WITH DATA DOWNLOAD FROM A DIVE COMPUTER?*
|
||||
[icon="images/icons/important.png"]
|
||||
|
|
|
@ -29,6 +29,7 @@ void cliDownloader(const char *vendor, const char *product, const char *device)
|
|||
data->setForceDownload(false);
|
||||
data->setSaveLog(true);
|
||||
data->setSaveDump(false);
|
||||
data->setSyncTime(false);
|
||||
|
||||
diveImportedModel.startDownload();
|
||||
diveImportedModel.waitForDownload();
|
||||
|
|
|
@ -227,6 +227,7 @@ DCDeviceData::DCDeviceData()
|
|||
#if defined(Q_OS_ANDROID)
|
||||
data.androidUsbDeviceDescriptor = nullptr;
|
||||
#endif
|
||||
data.sync_time = false;
|
||||
}
|
||||
|
||||
DCDeviceData *DCDeviceData::instance()
|
||||
|
@ -291,6 +292,11 @@ int DCDeviceData::diveId() const
|
|||
return data.diveid;
|
||||
}
|
||||
|
||||
bool DCDeviceData::syncTime() const
|
||||
{
|
||||
return data.sync_time;
|
||||
}
|
||||
|
||||
void DCDeviceData::setVendor(const QString &vendor)
|
||||
{
|
||||
data.vendor = copy_qstring(vendor);
|
||||
|
@ -350,6 +356,11 @@ void DCDeviceData::setDiveId(int diveId)
|
|||
data.diveid = diveId;
|
||||
}
|
||||
|
||||
void DCDeviceData::setSyncTime(bool syncTime)
|
||||
{
|
||||
data.sync_time = syncTime;
|
||||
}
|
||||
|
||||
void DCDeviceData::setSaveDump(bool save)
|
||||
{
|
||||
data.libdc_dump = save;
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
bool forceDownload() const;
|
||||
bool saveLog() const;
|
||||
int diveId() const;
|
||||
bool syncTime() const;
|
||||
|
||||
/* this needs to be a pointer to make the C-API happy */
|
||||
device_data_t *internalData();
|
||||
|
@ -54,6 +55,7 @@ public:
|
|||
#if defined(Q_OS_ANDROID)
|
||||
void setUsbDevice(const android_usb_serial_device_descriptor &usbDescriptor);
|
||||
#endif
|
||||
void setSyncTime(bool syncTime);
|
||||
private:
|
||||
#if defined(Q_OS_ANDROID)
|
||||
struct android_usb_serial_device_descriptor androidUsbDescriptor;
|
||||
|
|
|
@ -1413,6 +1413,14 @@ dc_status_t divecomputer_device_open(device_data_t *data)
|
|||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static dc_status_t sync_divecomputer_time(dc_device_t *device)
|
||||
{
|
||||
dc_datetime_t now;
|
||||
dc_datetime_localtime(&now, dc_datetime_now());
|
||||
|
||||
return dc_device_timesync(device, &now);
|
||||
}
|
||||
|
||||
const char *do_libdivecomputer_import(device_data_t *data)
|
||||
{
|
||||
dc_status_t rc;
|
||||
|
@ -1463,6 +1471,28 @@ const char *do_libdivecomputer_import(device_data_t *data)
|
|||
dev_info(data, "Starting import ...");
|
||||
err = do_device_import(data);
|
||||
/* TODO: Show the logfile to the user on error. */
|
||||
dev_info(data, "Import complete");
|
||||
|
||||
if (!err && data->sync_time) {
|
||||
dev_info(data, "Syncing dive computer time ...");
|
||||
rc = sync_divecomputer_time(data->device);
|
||||
|
||||
switch (rc) {
|
||||
case DC_STATUS_SUCCESS:
|
||||
dev_info(data, "Time sync complete");
|
||||
|
||||
break;
|
||||
case DC_STATUS_UNSUPPORTED:
|
||||
dev_info(data, "Time sync not supported by dive computer");
|
||||
|
||||
break;
|
||||
default:
|
||||
dev_info(data, "Time sync failed");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dc_device_close(data->device);
|
||||
data->device = NULL;
|
||||
if (!data->log->dives->nr)
|
||||
|
|
|
@ -46,6 +46,7 @@ typedef struct {
|
|||
bool libdc_log;
|
||||
bool libdc_dump;
|
||||
bool bluetooth_mode;
|
||||
bool sync_time;
|
||||
FILE *libdc_logfile;
|
||||
struct divelog *log;
|
||||
void *androidUsbDeviceDescriptor;
|
||||
|
|
|
@ -93,6 +93,7 @@ struct preferences default_prefs = {
|
|||
.extract_video_thumbnails = true,
|
||||
.extract_video_thumbnails_position = 20, // The first fifth seems like a reasonable place
|
||||
.three_m_based_grid = false,
|
||||
.sync_dc_time = false,
|
||||
};
|
||||
|
||||
/* copy a preferences block, including making copies of all included strings */
|
||||
|
|
|
@ -96,6 +96,7 @@ struct preferences {
|
|||
dive_computer_prefs_t dive_computer2;
|
||||
dive_computer_prefs_t dive_computer3;
|
||||
dive_computer_prefs_t dive_computer4;
|
||||
bool sync_dc_time;
|
||||
|
||||
// ********** Display *************
|
||||
bool display_invalid_dives;
|
||||
|
|
|
@ -29,6 +29,8 @@ void qPrefDiveComputer::loadSync(bool doSync)
|
|||
DISK_DC(2)
|
||||
DISK_DC(3)
|
||||
DISK_DC(4)
|
||||
|
||||
disk_sync_dc_time(doSync);
|
||||
}
|
||||
|
||||
// these are the 'active' settings
|
||||
|
@ -54,3 +56,5 @@ HANDLE_PREFERENCE_TXT_EXT_ALT(DiveComputer, "dive_computer_vendor1", vendor, div
|
|||
HANDLE_PREFERENCE_TXT_EXT_ALT(DiveComputer, "dive_computer_vendor2", vendor, dive_computer, 2)
|
||||
HANDLE_PREFERENCE_TXT_EXT_ALT(DiveComputer, "dive_computer_vendor3", vendor, dive_computer, 3)
|
||||
HANDLE_PREFERENCE_TXT_EXT_ALT(DiveComputer, "dive_computer_vendor4", vendor, dive_computer, 4)
|
||||
|
||||
HANDLE_PREFERENCE_BOOL(DiveComputer, "sync_dive_computer_time", sync_dc_time);
|
||||
|
|
|
@ -35,6 +35,8 @@ class qPrefDiveComputer : public QObject {
|
|||
Q_PROPERTY(QString vendor3 READ vendor3 WRITE set_vendor3 NOTIFY vendor3Changed)
|
||||
Q_PROPERTY(QString vendor4 READ vendor4 WRITE set_vendor4 NOTIFY vendor4Changed)
|
||||
|
||||
Q_PROPERTY(bool sync_dc_time READ sync_dc_time WRITE set_sync_dc_time NOTIFY sync_dc_timeChanged)
|
||||
|
||||
public:
|
||||
static qPrefDiveComputer *instance();
|
||||
|
||||
|
@ -49,6 +51,8 @@ public:
|
|||
IMPLEMENT5GETTERS(product)
|
||||
IMPLEMENT5GETTERS(vendor)
|
||||
|
||||
static bool sync_dc_time() { return prefs.sync_dc_time; }
|
||||
|
||||
public slots:
|
||||
static void set_device(const QString &device);
|
||||
static void set_device1(const QString &device);
|
||||
|
@ -74,6 +78,8 @@ public slots:
|
|||
static void set_vendor3(const QString &vendor);
|
||||
static void set_vendor4(const QString &vendor);
|
||||
|
||||
static void set_sync_dc_time(bool value);
|
||||
|
||||
signals:
|
||||
void deviceChanged(const QString &device);
|
||||
void device1Changed(const QString &device);
|
||||
|
@ -99,6 +105,8 @@ signals:
|
|||
void vendor3Changed(const QString &vendor);
|
||||
void vendor4Changed(const QString &vendor);
|
||||
|
||||
void sync_dc_timeChanged(bool value);
|
||||
|
||||
private:
|
||||
qPrefDiveComputer() {}
|
||||
|
||||
|
@ -127,6 +135,8 @@ private:
|
|||
static void disk_vendor2(bool doSync);
|
||||
static void disk_vendor3(bool doSync);
|
||||
static void disk_vendor4(bool doSync);
|
||||
|
||||
static void disk_sync_dc_time(bool doSync);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1518,6 +1518,9 @@ const char *do_uemis_import(device_data_t *data)
|
|||
if (uemis_mem_status != UEMIS_MEM_OK)
|
||||
result = translate("gettextFromC", ERR_FS_ALMOST_FULL);
|
||||
|
||||
if (data->sync_time)
|
||||
uemis_info(translate("gettextFromC", "Time sync not supported by dive computer"));
|
||||
|
||||
bail:
|
||||
(void)uemis_get_answer(mountpath, "terminateSync", 0, 3, &result);
|
||||
if (!strcmp(param_buff[0], "error")) {
|
||||
|
|
|
@ -60,6 +60,7 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent) : QDialog(parent, QF
|
|||
ui.vendor->setModel(&vendorModel);
|
||||
ui.search->setEnabled(is_vendor_searchable(ui.vendor->currentText()));
|
||||
ui.product->setModel(&productModel);
|
||||
ui.syncDiveComputerTime->setChecked(prefs.sync_dc_time);
|
||||
|
||||
progress_bar_text = "";
|
||||
|
||||
|
@ -72,6 +73,7 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent) : QDialog(parent, QF
|
|||
connect(ui.logToFile, SIGNAL(stateChanged(int)), this, SLOT(checkLogFile(int)));
|
||||
connect(ui.selectAllButton, SIGNAL(clicked()), diveImportedModel, SLOT(selectAll()));
|
||||
connect(ui.unselectAllButton, SIGNAL(clicked()), diveImportedModel, SLOT(selectNone()));
|
||||
connect(ui.syncDiveComputerTime, &QAbstractButton::toggled, qPrefDiveComputer::instance(), &qPrefDiveComputer::set_sync_dc_time);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
|
||||
connect(close, SIGNAL(activated()), this, SLOT(close()));
|
||||
connect(quit, SIGNAL(activated()), parent, SLOT(close()));
|
||||
|
@ -419,6 +421,7 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
|
|||
data->setForceDownload(ui.forceDownload->isChecked());
|
||||
data->setSaveLog(ui.logToFile->isChecked());
|
||||
data->setSaveDump(ui.dumpToFile->isChecked());
|
||||
data->setSyncTime(ui.syncDiveComputerTime->isChecked());
|
||||
|
||||
qPrefDiveComputer::set_vendor(data->vendor());
|
||||
qPrefDiveComputer::set_product(data->product());
|
||||
|
@ -582,6 +585,7 @@ void DownloadFromDCWidget::markChildrenAsDisabled()
|
|||
ui.unselectAllButton->setEnabled(false);
|
||||
ui.bluetoothMode->setEnabled(false);
|
||||
ui.chooseBluetoothDevice->setEnabled(false);
|
||||
ui.syncDiveComputerTime->setEnabled(false);
|
||||
}
|
||||
|
||||
void DownloadFromDCWidget::markChildrenAsEnabled()
|
||||
|
@ -605,6 +609,7 @@ void DownloadFromDCWidget::markChildrenAsEnabled()
|
|||
ui.bluetoothMode->setEnabled(true);
|
||||
ui.chooseBluetoothDevice->setEnabled(true);
|
||||
#endif
|
||||
ui.syncDiveComputerTime->setEnabled(true);
|
||||
}
|
||||
|
||||
#if defined(BT_SUPPORT)
|
||||
|
|
|
@ -85,6 +85,7 @@ private:
|
|||
BtDeviceSelectionDialog *btDeviceSelectionDialog;
|
||||
BTDiscovery *btd;
|
||||
#endif
|
||||
void setSyncDiveComputerTime(bool value);
|
||||
|
||||
public:
|
||||
bool preferDownloaded();
|
||||
|
|
|
@ -185,6 +185,16 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QCheckBox" name="syncDiveComputerTime">
|
||||
<property name="text">
|
||||
<string>Sync dive computer time</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Adjust the time on the dive computer to match the time on the PC (if supported by the dive computer model).</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
@ -397,7 +397,7 @@ Kirigami.Page {
|
|||
}
|
||||
|
||||
RowLayout {
|
||||
id: downloadOptions
|
||||
id: forceDownloadOption
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 0
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
@ -421,6 +421,31 @@ Kirigami.Page {
|
|||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: syncTimeOption
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 0
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
TemplateCheckBox {
|
||||
id: syncTimeWithDiveComputer
|
||||
checked: Backend.sync_dc_time
|
||||
enabled: syncTimeLabel.visible
|
||||
visible: enabled
|
||||
height: syncTimeLabel.height - Kirigami.Units.smallSpacing;
|
||||
width: height
|
||||
onClicked: {
|
||||
Backend.sync_dc_time = checked
|
||||
}
|
||||
}
|
||||
TemplateLabel {
|
||||
id: syncTimeLabel
|
||||
text: qsTr("Sync dive computer time")
|
||||
visible: comboVendor.currentIndex != -1 && comboProduct.currentIndex != -1 &&
|
||||
comboConnection.currentIndex != -1
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: dlList
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing * 4
|
||||
|
|
|
@ -79,6 +79,9 @@ QMLInterface::QMLInterface()
|
|||
this, &QMLInterface::verbatim_planChanged);
|
||||
connect(qPrefDivePlanner::instance(), &qPrefDivePlanner::display_variationsChanged,
|
||||
this, &QMLInterface::display_variationsChanged);
|
||||
|
||||
connect(qPrefDiveComputer::instance(), &qPrefDiveComputer::sync_dc_timeChanged,
|
||||
this, &QMLInterface::sync_dc_timeChanged);
|
||||
}
|
||||
|
||||
void QMLInterface::setup(QQmlContext *ct)
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
#ifndef QMLINTERFACE_H
|
||||
#define QMLINTERFACE_H
|
||||
#include "core/qthelper.h"
|
||||
#include "core/downloadfromdcthread.h"
|
||||
#include "core/settings/qPrefCloudStorage.h"
|
||||
#include "core/settings/qPrefUnit.h"
|
||||
#include "core/settings/qPrefDivePlanner.h"
|
||||
#include "core/settings/qPrefTechnicalDetails.h"
|
||||
#include "core/settings/qPrefDiveComputer.h"
|
||||
#include "qt-models/diveplannermodel.h"
|
||||
#include "backend-shared/plannershared.h"
|
||||
|
||||
|
@ -78,6 +80,8 @@ class QMLInterface : public QObject {
|
|||
Q_PROPERTY(bool verbatim_plan READ verbatim_plan WRITE set_verbatim_plan NOTIFY verbatim_planChanged);
|
||||
Q_PROPERTY(bool display_variations READ display_variations WRITE set_display_variations NOTIFY display_variationsChanged);
|
||||
|
||||
Q_PROPERTY(bool sync_dc_time READ sync_dc_time WRITE set_sync_dc_time NOTIFY sync_dc_timeChanged);
|
||||
|
||||
public:
|
||||
// function to do the needed setup
|
||||
static void setup(QQmlContext *ct);
|
||||
|
@ -212,6 +216,8 @@ public:
|
|||
bool verbatim_plan() { return prefs.verbatim_plan; }
|
||||
bool display_variations() { return prefs.display_variations; }
|
||||
|
||||
bool sync_dc_time() { return prefs.sync_dc_time; }
|
||||
|
||||
public slots:
|
||||
void set_cloud_verification_status(CLOUD_STATUS value) { qPrefCloudStorage::set_cloud_verification_status(value); }
|
||||
void set_duration_units(DURATION value) { qPrefUnits::set_duration_units((units::DURATION)value); }
|
||||
|
@ -258,6 +264,10 @@ public slots:
|
|||
void set_display_transitions(bool value) { DivePlannerPointsModel::instance()->setDisplayTransitions(value); }
|
||||
void set_verbatim_plan(bool value) { DivePlannerPointsModel::instance()->setVerbatim(value); }
|
||||
void set_display_variations(bool value) { DivePlannerPointsModel::instance()->setDisplayVariations(value); }
|
||||
void set_sync_dc_time(bool value) {
|
||||
qPrefDiveComputer::set_sync_dc_time(value);
|
||||
DCDeviceData::instance()->setSyncTime(value);
|
||||
}
|
||||
QString firstDiveDate() { return get_first_dive_date_string(); }
|
||||
QString lastDiveDate() { return get_last_dive_date_string(); }
|
||||
|
||||
|
@ -307,6 +317,8 @@ signals:
|
|||
void display_transitionsChanged(bool value);
|
||||
void verbatim_planChanged(bool value);
|
||||
void display_variationsChanged(bool value);
|
||||
|
||||
void sync_dc_timeChanged(bool value);
|
||||
private:
|
||||
QMLInterface();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue