2017-04-27 18:26:05 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2016-04-05 05:02:03 +00:00
|
|
|
#include "desktop-widgets/downloadfromdivecomputer.h"
|
2019-11-13 14:08:40 +00:00
|
|
|
#include "commands/command.h"
|
2018-07-26 01:40:19 +00:00
|
|
|
#include "core/qthelper.h"
|
2022-11-12 11:44:29 +00:00
|
|
|
#include "core/device.h"
|
2019-07-15 21:44:39 +00:00
|
|
|
#include "core/divelist.h"
|
core: introduce divelog structure
The parser API was very annoying, as a number of tables
to-be-filled were passed in as pointers. The goal of this
commit is to collect all these tables in a single struct.
This should make it (more or less) clear what is actually
written into the divelog files.
Moreover, it should now be rather easy to search for
instances, where the global logfile is accessed (and it
turns out that there are many!).
The divelog struct does not contain the tables as substructs,
but only collects pointers. The idea is that the "divelog.h"
file can be included without all the other files describing
the numerous tables.
To make it easier to use from C++ parts of the code, the
struct implements a constructor and a destructor. Sadly,
we can't use smart pointers, since the pointers are accessed
from C code. Therfore the constructor and destructor are
quite complex.
The whole commit is large, but was mostly an automatic
conversion.
One oddity of note: the divelog structure also contains
the "autogroup" flag, since that is saved in the divelog.
This actually fixes a bug: Before, when importing dives
from a different log, the autogroup flag was overwritten.
This was probably not intended and does not happen anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2022-11-08 20:31:08 +00:00
|
|
|
#include "core/divelog.h"
|
2024-03-24 20:03:08 +00:00
|
|
|
#include "core/errorhelper.h"
|
2018-08-15 09:56:17 +00:00
|
|
|
#include "core/settings/qPrefDiveComputer.h"
|
2022-08-30 16:13:13 +00:00
|
|
|
#include "core/subsurface-float.h"
|
2018-05-11 15:25:41 +00:00
|
|
|
#include "core/subsurface-string.h"
|
2019-09-25 18:49:13 +00:00
|
|
|
#include "core/downloadfromdcthread.h"
|
2018-07-26 01:40:19 +00:00
|
|
|
#include "desktop-widgets/divelistview.h"
|
|
|
|
#include "desktop-widgets/mainwindow.h"
|
2017-04-18 15:32:10 +00:00
|
|
|
#include "qt-models/diveimportedmodel.h"
|
2018-07-26 01:40:19 +00:00
|
|
|
#include "qt-models/models.h"
|
2015-02-09 21:51:31 +00:00
|
|
|
|
2013-12-25 00:26:00 +00:00
|
|
|
#include <QFileDialog>
|
2013-09-01 14:14:54 +00:00
|
|
|
#include <QMessageBox>
|
2014-04-25 17:44:23 +00:00
|
|
|
#include <QShortcut>
|
2018-07-26 01:40:19 +00:00
|
|
|
#include <QTimer>
|
2018-07-21 19:29:49 +00:00
|
|
|
#include <QUndoStack>
|
2013-05-20 20:58:06 +00:00
|
|
|
|
2023-02-27 05:41:46 +00:00
|
|
|
static bool is_vendor_searchable(QString vendor)
|
|
|
|
{
|
2024-05-05 05:19:15 +00:00
|
|
|
return vendor == "Uemis" || vendor == "Garmin" || vendor == "FIT";
|
2023-02-27 05:41:46 +00:00
|
|
|
}
|
|
|
|
|
2024-03-16 09:02:54 +00:00
|
|
|
DownloadFromDCWidget::DownloadFromDCWidget(const QString &filename, QWidget *parent) : QDialog(parent, QFlag(0)),
|
|
|
|
filename(filename),
|
2014-02-09 18:38:26 +00:00
|
|
|
downloading(false),
|
|
|
|
previousLast(0),
|
|
|
|
timer(new QTimer(this)),
|
|
|
|
dumpWarningShown(false),
|
2018-09-25 00:31:33 +00:00
|
|
|
#if defined (BT_SUPPORT)
|
|
|
|
btd(nullptr),
|
|
|
|
#endif
|
2014-12-29 23:25:54 +00:00
|
|
|
currentState(INITIAL)
|
2013-05-20 19:43:33 +00:00
|
|
|
{
|
2017-04-18 17:14:03 +00:00
|
|
|
diveImportedModel = new DiveImportedModel(this);
|
2017-11-11 18:40:47 +00:00
|
|
|
vendorModel.setStringList(vendorList);
|
2022-02-08 19:24:53 +00:00
|
|
|
QShortcut *close = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_W), this);
|
|
|
|
QShortcut *quit = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q), this);
|
2017-04-18 17:14:03 +00:00
|
|
|
|
|
|
|
int startingWidth = defaultModelFont().pointSize();
|
|
|
|
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.setupUi(this);
|
|
|
|
ui.progressBar->hide();
|
|
|
|
ui.progressBar->setMinimum(0);
|
|
|
|
ui.progressBar->setMaximum(100);
|
2015-01-08 13:29:28 +00:00
|
|
|
ui.downloadedView->setModel(diveImportedModel);
|
2015-01-08 19:19:01 +00:00
|
|
|
ui.downloadedView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
|
ui.downloadedView->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
ui.downloadedView->setColumnWidth(0, startingWidth * 20);
|
2015-01-13 08:20:32 +00:00
|
|
|
ui.downloadedView->setColumnWidth(1, startingWidth * 10);
|
2015-01-08 19:19:01 +00:00
|
|
|
ui.downloadedView->setColumnWidth(2, startingWidth * 10);
|
2017-04-18 17:14:03 +00:00
|
|
|
ui.chooseDumpFile->setEnabled(ui.dumpToFile->isChecked());
|
|
|
|
ui.chooseLogFile->setEnabled(ui.logToFile->isChecked());
|
|
|
|
ui.selectAllButton->setEnabled(false);
|
|
|
|
ui.unselectAllButton->setEnabled(false);
|
2017-11-11 18:40:47 +00:00
|
|
|
ui.vendor->setModel(&vendorModel);
|
2023-02-27 05:41:46 +00:00
|
|
|
ui.search->setEnabled(is_vendor_searchable(ui.vendor->currentText()));
|
2017-11-11 18:40:47 +00:00
|
|
|
ui.product->setModel(&productModel);
|
2023-04-02 06:28:33 +00:00
|
|
|
ui.syncDiveComputerTime->setChecked(prefs.sync_dc_time);
|
2013-09-16 21:04:42 +00:00
|
|
|
|
2024-06-08 20:43:04 +00:00
|
|
|
progress_bar_text.clear();
|
2014-02-26 16:37:13 +00:00
|
|
|
|
2017-04-18 17:14:03 +00:00
|
|
|
timer->setInterval(200);
|
2013-05-20 20:58:06 +00:00
|
|
|
|
2017-04-18 17:14:03 +00:00
|
|
|
connect(ui.downloadedView, SIGNAL(clicked(QModelIndex)), diveImportedModel, SLOT(changeSelected(QModelIndex)));
|
2013-12-25 00:26:00 +00:00
|
|
|
connect(ui.chooseDumpFile, SIGNAL(clicked()), this, SLOT(pickDumpFile()));
|
|
|
|
connect(ui.dumpToFile, SIGNAL(stateChanged(int)), this, SLOT(checkDumpFile(int)));
|
|
|
|
connect(ui.chooseLogFile, SIGNAL(clicked()), this, SLOT(pickLogFile()));
|
|
|
|
connect(ui.logToFile, SIGNAL(stateChanged(int)), this, SLOT(checkLogFile(int)));
|
2015-01-08 20:54:53 +00:00
|
|
|
connect(ui.selectAllButton, SIGNAL(clicked()), diveImportedModel, SLOT(selectAll()));
|
|
|
|
connect(ui.unselectAllButton, SIGNAL(clicked()), diveImportedModel, SLOT(selectNone()));
|
2023-04-02 06:28:33 +00:00
|
|
|
connect(ui.syncDiveComputerTime, &QAbstractButton::toggled, qPrefDiveComputer::instance(), &qPrefDiveComputer::set_sync_dc_time);
|
2017-04-18 17:14:03 +00:00
|
|
|
connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
|
|
|
|
connect(close, SIGNAL(activated()), this, SLOT(close()));
|
|
|
|
connect(quit, SIGNAL(activated()), parent, SLOT(close()));
|
2016-08-10 21:10:15 +00:00
|
|
|
|
2019-09-25 18:49:13 +00:00
|
|
|
connect(diveImportedModel, &DiveImportedModel::downloadFinished, this, &DownloadFromDCWidget::onDownloadThreadFinished);
|
2017-10-16 11:29:21 +00:00
|
|
|
|
2018-08-15 09:56:17 +00:00
|
|
|
if (!qPrefDiveComputer::vendor().isEmpty()) {
|
|
|
|
ui.vendor->setCurrentIndex(ui.vendor->findText(qPrefDiveComputer::vendor()));
|
|
|
|
productModel.setStringList(productList[qPrefDiveComputer::vendor()]);
|
|
|
|
if (!qPrefDiveComputer::product().isEmpty())
|
|
|
|
ui.product->setCurrentIndex(ui.product->findText(qPrefDiveComputer::product()));
|
2013-05-23 06:24:33 +00:00
|
|
|
}
|
2013-08-25 22:02:30 +00:00
|
|
|
|
2018-09-20 21:19:03 +00:00
|
|
|
// now lets set the four shortcuts for previously used dive computers
|
2018-09-21 22:41:28 +00:00
|
|
|
showRememberedDCs();
|
2018-09-20 21:19:03 +00:00
|
|
|
|
2013-08-25 22:02:30 +00:00
|
|
|
updateState(INITIAL);
|
2015-01-08 17:39:47 +00:00
|
|
|
ui.ok->setEnabled(false);
|
2015-01-09 23:01:48 +00:00
|
|
|
ui.downloadCancelRetryButton->setEnabled(true);
|
|
|
|
ui.downloadCancelRetryButton->setText(tr("Download"));
|
2015-07-06 13:35:13 +00:00
|
|
|
|
2018-08-15 09:56:17 +00:00
|
|
|
QString deviceText = qPrefDiveComputer::device();
|
2018-04-17 01:14:59 +00:00
|
|
|
#if defined(BT_SUPPORT)
|
2015-09-04 22:25:35 +00:00
|
|
|
ui.bluetoothMode->setText(tr("Choose Bluetooth download mode"));
|
2018-10-15 11:40:26 +00:00
|
|
|
ui.bluetoothMode->setChecked(isBluetoothAddress(qPrefDiveComputer::device()));
|
2015-07-06 13:35:13 +00:00
|
|
|
btDeviceSelectionDialog = 0;
|
2017-05-28 10:29:26 +00:00
|
|
|
connect(ui.bluetoothMode, SIGNAL(stateChanged(int)), this, SLOT(enableBluetoothMode(int)));
|
|
|
|
connect(ui.chooseBluetoothDevice, SIGNAL(clicked()), this, SLOT(selectRemoteBluetoothDevice()));
|
2015-07-06 13:18:06 +00:00
|
|
|
ui.chooseBluetoothDevice->setEnabled(ui.bluetoothMode->isChecked());
|
2017-11-12 11:33:20 +00:00
|
|
|
if (ui.bluetoothMode->isChecked())
|
2018-08-15 09:56:17 +00:00
|
|
|
deviceText = BtDeviceSelectionDialog::formatDeviceText(qPrefDiveComputer::device(), qPrefDiveComputer::device_name());
|
2015-07-20 16:35:00 +00:00
|
|
|
#else
|
|
|
|
ui.bluetoothMode->hide();
|
|
|
|
ui.chooseBluetoothDevice->hide();
|
|
|
|
#endif
|
2017-11-12 11:33:20 +00:00
|
|
|
if (!deviceText.isEmpty())
|
|
|
|
ui.device->setEditText(deviceText);
|
2013-05-20 20:58:06 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 22:41:28 +00:00
|
|
|
#define SETUPDC(num) \
|
|
|
|
if (!qPrefDiveComputer::vendor##num().isEmpty()) { \
|
|
|
|
ui.DC##num->setVisible(true); \
|
2024-04-21 13:18:02 +00:00
|
|
|
ui.DCFrame##num->setVisible(true); \
|
|
|
|
ui.DeleteDC##num->setVisible(true); \
|
2018-09-21 22:41:28 +00:00
|
|
|
ui.DC##num->setText(qPrefDiveComputer::vendor##num() + " - " + qPrefDiveComputer::product##num()); \
|
|
|
|
connect(ui.DC##num, &QPushButton::clicked, this, &DownloadFromDCWidget::DC##num##Clicked, Qt::UniqueConnection); \
|
2024-04-21 13:18:02 +00:00
|
|
|
connect(ui.DeleteDC##num, &QPushButton::clicked, this, &DownloadFromDCWidget::DeleteDC##num##Clicked, Qt::UniqueConnection); \
|
2018-09-21 22:41:28 +00:00
|
|
|
} else { \
|
|
|
|
ui.DC##num->setVisible(false); \
|
2024-04-21 13:18:02 +00:00
|
|
|
ui.DCFrame##num->setVisible(false); \
|
|
|
|
ui.DeleteDC##num->setVisible(false); \
|
2018-09-21 22:41:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::showRememberedDCs()
|
|
|
|
{
|
|
|
|
SETUPDC(1)
|
|
|
|
SETUPDC(2)
|
|
|
|
SETUPDC(3)
|
|
|
|
SETUPDC(4)
|
|
|
|
}
|
|
|
|
|
2018-09-24 14:04:21 +00:00
|
|
|
int DownloadFromDCWidget::deviceIndex(QString deviceText)
|
|
|
|
{
|
|
|
|
int rv = ui.device->findText(deviceText);
|
|
|
|
if (rv == -1) {
|
|
|
|
// we need to insert the device text into the model
|
|
|
|
ui.device->addItem(deviceText);
|
|
|
|
rv = ui.device->findText(deviceText);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2024-04-20 09:55:43 +00:00
|
|
|
|
2018-09-21 19:16:42 +00:00
|
|
|
// DC button slots
|
2019-07-04 04:49:37 +00:00
|
|
|
// we need two versions as one of the helper functions used is only available if
|
|
|
|
// Bluetooth support is enabled
|
|
|
|
#ifdef BT_SUPPORT
|
|
|
|
#define DCBUTTON(num) \
|
|
|
|
void DownloadFromDCWidget::DC##num##Clicked() \
|
|
|
|
{ \
|
|
|
|
ui.vendor->setCurrentIndex(ui.vendor->findText(qPrefDiveComputer::vendor##num())); \
|
|
|
|
productModel.setStringList(productList[qPrefDiveComputer::vendor##num()]); \
|
|
|
|
ui.product->setCurrentIndex(ui.product->findText(qPrefDiveComputer::product##num())); \
|
2024-04-16 09:38:47 +00:00
|
|
|
ui.device->setCurrentIndex(deviceIndex(qPrefDiveComputer::device##num())); \
|
|
|
|
ui.bluetoothMode->setChecked(isBluetoothAddress(qPrefDiveComputer::device##num())); \
|
2019-07-04 04:49:37 +00:00
|
|
|
}
|
|
|
|
#else
|
2018-09-21 19:16:42 +00:00
|
|
|
#define DCBUTTON(num) \
|
|
|
|
void DownloadFromDCWidget::DC##num##Clicked() \
|
|
|
|
{ \
|
|
|
|
ui.vendor->setCurrentIndex(ui.vendor->findText(qPrefDiveComputer::vendor##num())); \
|
|
|
|
productModel.setStringList(productList[qPrefDiveComputer::vendor##num()]); \
|
|
|
|
ui.product->setCurrentIndex(ui.product->findText(qPrefDiveComputer::product##num())); \
|
2018-09-24 14:04:21 +00:00
|
|
|
ui.device->setCurrentIndex(deviceIndex(qPrefDiveComputer::device##num())); \
|
2018-09-21 19:16:42 +00:00
|
|
|
}
|
2019-07-04 04:49:37 +00:00
|
|
|
#endif
|
|
|
|
|
2018-09-21 19:16:42 +00:00
|
|
|
DCBUTTON(1)
|
|
|
|
DCBUTTON(2)
|
|
|
|
DCBUTTON(3)
|
|
|
|
DCBUTTON(4)
|
|
|
|
|
2024-04-20 09:55:43 +00:00
|
|
|
// Delete DC button slots
|
2024-04-21 13:18:02 +00:00
|
|
|
#define DELETEDCBUTTON(num) \
|
|
|
|
void DownloadFromDCWidget::DeleteDC##num##Clicked() \
|
2024-04-20 09:55:43 +00:00
|
|
|
{ \
|
|
|
|
ui.DC##num->setVisible(false); \
|
2024-04-21 13:18:02 +00:00
|
|
|
ui.DeleteDC##num->setVisible(false); \
|
2024-04-20 09:55:43 +00:00
|
|
|
int dc = num; \
|
|
|
|
switch (dc) { \
|
|
|
|
case 1: \
|
|
|
|
qPrefDiveComputer::set_vendor1(qPrefDiveComputer::vendor2()); \
|
|
|
|
qPrefDiveComputer::set_product1(qPrefDiveComputer::product2()); \
|
|
|
|
qPrefDiveComputer::set_device1(qPrefDiveComputer::device2()); \
|
|
|
|
case 2: \
|
|
|
|
qPrefDiveComputer::set_vendor2(qPrefDiveComputer::vendor3()); \
|
|
|
|
qPrefDiveComputer::set_product2(qPrefDiveComputer::product3()); \
|
|
|
|
qPrefDiveComputer::set_device2(qPrefDiveComputer::device3()); \
|
|
|
|
case 3: \
|
|
|
|
qPrefDiveComputer::set_vendor3(qPrefDiveComputer::vendor4()); \
|
|
|
|
qPrefDiveComputer::set_product3(qPrefDiveComputer::product4()); \
|
|
|
|
qPrefDiveComputer::set_device3(qPrefDiveComputer::device4()); \
|
|
|
|
case 4: \
|
|
|
|
qPrefDiveComputer::set_vendor4(QString()); \
|
|
|
|
qPrefDiveComputer::set_product4(QString()); \
|
|
|
|
qPrefDiveComputer::set_device4(QString()); \
|
|
|
|
} \
|
2024-04-21 13:18:02 +00:00
|
|
|
DownloadFromDCWidget::showRememberedDCs(); \
|
2024-04-20 09:55:43 +00:00
|
|
|
}
|
|
|
|
|
2024-04-21 13:18:02 +00:00
|
|
|
DELETEDCBUTTON(1)
|
|
|
|
DELETEDCBUTTON(2)
|
|
|
|
DELETEDCBUTTON(3)
|
|
|
|
DELETEDCBUTTON(4)
|
2024-04-20 09:55:43 +00:00
|
|
|
|
2013-08-25 22:02:30 +00:00
|
|
|
void DownloadFromDCWidget::updateProgressBar()
|
2013-05-30 09:21:08 +00:00
|
|
|
{
|
2024-06-08 20:43:04 +00:00
|
|
|
if (last_text.empty()) {
|
2017-04-22 20:49:03 +00:00
|
|
|
// if we get the first actual text after the download is finished
|
|
|
|
// (which happens for example on the OSTC), then don't bother
|
2024-06-08 20:43:04 +00:00
|
|
|
if (!progress_bar_text.empty() && nearly_equal(progress_bar_fraction, 1.0))
|
|
|
|
progress_bar_text.clear();
|
2017-04-22 20:49:03 +00:00
|
|
|
}
|
2024-06-08 20:43:04 +00:00
|
|
|
if (!progress_bar_text.empty()) {
|
2018-09-26 03:34:25 +00:00
|
|
|
// once the progress bar text is set, setup the maximum so the user sees actual progress
|
2024-06-08 20:43:04 +00:00
|
|
|
ui.progressBar->setFormat(QString::fromStdString(progress_bar_text));
|
2018-09-26 03:34:25 +00:00
|
|
|
ui.progressBar->setMaximum(100);
|
2017-09-17 22:04:14 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
|
|
|
// on mac the progress bar doesn't show its text
|
2024-06-08 20:43:04 +00:00
|
|
|
ui.progressText->setText(QString::fromStdString(progress_bar_text));
|
2017-09-17 22:04:14 +00:00
|
|
|
#endif
|
2014-01-27 20:47:40 +00:00
|
|
|
} else {
|
2022-08-30 15:47:31 +00:00
|
|
|
if (nearly_0(progress_bar_fraction)) {
|
2018-09-26 03:34:25 +00:00
|
|
|
// while we are waiting to connect, set the maximum to 0 so we get a busy indication
|
|
|
|
ui.progressBar->setMaximum(0);
|
2017-09-17 22:02:11 +00:00
|
|
|
ui.progressBar->setFormat(tr("Connecting to dive computer"));
|
2017-09-17 22:04:14 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
2018-07-26 01:40:19 +00:00
|
|
|
// on mac the progress bar doesn't show its text
|
|
|
|
ui.progressText->setText(tr("Connecting to dive computer"));
|
2017-09-17 22:04:14 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
2018-09-26 03:34:25 +00:00
|
|
|
// we have some progress - reset the maximum so the user sees actual progress
|
|
|
|
ui.progressBar->setMaximum(100);
|
2017-09-17 22:02:11 +00:00
|
|
|
ui.progressBar->setFormat("%p%");
|
2017-09-17 22:04:14 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
|
|
|
// on mac the progress bar doesn't show its text
|
|
|
|
ui.progressText->setText(QString("%1%").arg(lrint(progress_bar_fraction * 100)));
|
|
|
|
#endif
|
|
|
|
}
|
2014-01-27 20:47:40 +00:00
|
|
|
}
|
2017-03-23 01:13:49 +00:00
|
|
|
ui.progressBar->setValue(lrint(progress_bar_fraction * 100));
|
2024-06-08 20:43:04 +00:00
|
|
|
last_text = progress_bar_text;
|
2013-08-25 22:02:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::updateState(states state)
|
|
|
|
{
|
|
|
|
if (state == currentState)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (state == INITIAL) {
|
2018-08-27 17:32:14 +00:00
|
|
|
fill_device_list(~0);
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.progressBar->hide();
|
2013-08-25 22:02:30 +00:00
|
|
|
markChildrenAsEnabled();
|
|
|
|
timer->stop();
|
2024-06-08 20:43:04 +00:00
|
|
|
progress_bar_text.clear();
|
2017-09-17 22:04:14 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
|
|
|
// on mac we show the text in a label
|
2024-06-08 20:43:04 +00:00
|
|
|
ui.progressText->setText(QString::fromStdString(progress_bar_text));
|
2017-09-17 22:04:14 +00:00
|
|
|
#endif
|
2013-08-25 22:02:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// tries to cancel an on going download
|
|
|
|
else if (currentState == DOWNLOADING && state == CANCELLING) {
|
|
|
|
import_thread_cancelled = true;
|
2015-01-09 23:01:48 +00:00
|
|
|
ui.downloadCancelRetryButton->setEnabled(false);
|
2013-08-25 22:02:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// user pressed cancel but the application isn't doing anything.
|
|
|
|
// means close the window
|
2019-08-28 09:21:24 +00:00
|
|
|
else if ((currentState == INITIAL || currentState == DONE || currentState == ERRORED) && state == CANCELLING) {
|
2013-08-25 22:02:30 +00:00
|
|
|
timer->stop();
|
|
|
|
reject();
|
|
|
|
}
|
|
|
|
|
2013-09-01 14:14:54 +00:00
|
|
|
// the cancelation process is finished
|
2015-01-09 23:01:48 +00:00
|
|
|
else if (currentState == CANCELLING && state == DONE) {
|
2013-08-25 22:02:30 +00:00
|
|
|
timer->stop();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.progressBar->setValue(0);
|
|
|
|
ui.progressBar->hide();
|
2013-08-25 22:02:30 +00:00
|
|
|
markChildrenAsEnabled();
|
2024-06-08 20:43:04 +00:00
|
|
|
progress_bar_text.clear();
|
2017-09-17 22:04:14 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
|
|
|
// on mac we show the text in a label
|
2024-06-08 20:43:04 +00:00
|
|
|
ui.progressText->setText(QString::fromStdString(progress_bar_text));
|
2017-09-17 22:04:14 +00:00
|
|
|
#endif
|
2013-08-25 22:02:30 +00:00
|
|
|
}
|
|
|
|
|
2014-01-27 20:47:40 +00:00
|
|
|
// DOWNLOAD is finally done, but we don't know if there was an error as libdivecomputer doesn't pass
|
2015-01-08 17:29:57 +00:00
|
|
|
// that information on to us.
|
|
|
|
// If we find an error, offer to retry, otherwise continue the interaction to pick the dives the user wants
|
2013-08-25 22:02:30 +00:00
|
|
|
else if (currentState == DOWNLOADING && state == DONE) {
|
|
|
|
timer->stop();
|
2024-06-08 20:43:04 +00:00
|
|
|
if (QString::fromStdString(progress_bar_text).contains("error", Qt::CaseInsensitive)) {
|
2014-01-27 20:47:40 +00:00
|
|
|
updateProgressBar();
|
|
|
|
markChildrenAsEnabled();
|
2024-06-08 20:43:04 +00:00
|
|
|
progress_bar_text.clear();
|
2014-01-27 20:47:40 +00:00
|
|
|
} else {
|
2019-09-22 19:00:15 +00:00
|
|
|
if (diveImportedModel->numDives() != 0)
|
2024-06-08 20:43:04 +00:00
|
|
|
progress_bar_text.clear();
|
2014-01-27 20:47:40 +00:00
|
|
|
ui.progressBar->setValue(100);
|
|
|
|
markChildrenAsEnabled();
|
|
|
|
}
|
2017-09-17 22:04:14 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
|
|
|
// on mac we show the text in a label
|
2024-06-08 20:43:04 +00:00
|
|
|
ui.progressText->setText(QString::fromStdString(progress_bar_text));
|
2017-09-17 22:04:14 +00:00
|
|
|
#endif
|
2013-08-25 22:02:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// DOWNLOAD is started.
|
|
|
|
else if (state == DOWNLOADING) {
|
|
|
|
timer->start();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.progressBar->setValue(0);
|
2017-04-22 20:55:43 +00:00
|
|
|
progress_bar_fraction = 0.0;
|
2014-01-27 20:47:40 +00:00
|
|
|
updateProgressBar();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.progressBar->show();
|
2013-08-25 22:02:30 +00:00
|
|
|
markChildrenAsDisabled();
|
|
|
|
}
|
|
|
|
|
2013-09-01 14:14:54 +00:00
|
|
|
// got an error
|
2019-08-28 09:21:24 +00:00
|
|
|
else if (state == ERRORED) {
|
2017-04-22 20:46:27 +00:00
|
|
|
timer->stop();
|
2017-10-31 20:28:59 +00:00
|
|
|
|
2024-04-29 05:02:54 +00:00
|
|
|
QMessageBox::critical(this, TITLE_OR_TEXT(tr("Error"),
|
|
|
|
QString::fromStdString(diveImportedModel->thread.error)), QMessageBox::Ok);
|
2013-09-01 14:14:54 +00:00
|
|
|
markChildrenAsEnabled();
|
2024-06-08 20:43:04 +00:00
|
|
|
progress_bar_text.clear();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.progressBar->hide();
|
2017-09-17 22:04:14 +00:00
|
|
|
#if defined(Q_OS_MAC)
|
|
|
|
// on mac we show the text in a label
|
2024-06-08 20:43:04 +00:00
|
|
|
ui.progressText->setText(QString::fromStdString(progress_bar_text));
|
2017-09-17 22:04:14 +00:00
|
|
|
#endif
|
2013-09-01 14:14:54 +00:00
|
|
|
}
|
|
|
|
|
2013-08-25 22:02:30 +00:00
|
|
|
// properly updating the widget state
|
|
|
|
currentState = state;
|
2013-05-30 09:21:08 +00:00
|
|
|
}
|
|
|
|
|
2022-02-10 01:25:00 +00:00
|
|
|
void DownloadFromDCWidget::on_vendor_currentTextChanged(const QString &vendor)
|
2013-05-20 20:58:06 +00:00
|
|
|
{
|
2018-08-27 17:32:14 +00:00
|
|
|
unsigned int transport;
|
|
|
|
dc_descriptor_t *descriptor;
|
2017-11-11 18:40:47 +00:00
|
|
|
productModel.setStringList(productList[vendor]);
|
|
|
|
ui.product->setCurrentIndex(0);
|
2013-05-20 20:58:06 +00:00
|
|
|
|
2020-05-14 19:15:24 +00:00
|
|
|
descriptor = descriptorLookup.value(ui.vendor->currentText().toLower() + ui.product->currentText().toLower());
|
2018-08-27 17:32:14 +00:00
|
|
|
transport = dc_descriptor_get_transports(descriptor);
|
|
|
|
fill_device_list(transport);
|
2023-02-27 05:41:46 +00:00
|
|
|
ui.search->setEnabled(is_vendor_searchable(vendor));
|
2013-05-20 20:58:06 +00:00
|
|
|
}
|
|
|
|
|
2022-02-10 01:25:00 +00:00
|
|
|
void DownloadFromDCWidget::on_product_currentTextChanged(const QString &)
|
2013-12-27 10:50:13 +00:00
|
|
|
{
|
2017-11-01 07:01:23 +00:00
|
|
|
updateDeviceEnabled();
|
2013-12-27 10:50:13 +00:00
|
|
|
}
|
|
|
|
|
2018-09-25 00:31:33 +00:00
|
|
|
void DownloadFromDCWidget::on_device_currentTextChanged(const QString &device)
|
|
|
|
{
|
2024-06-24 22:01:12 +00:00
|
|
|
#if defined(BT_SUPPORT) && defined(Q_OS_MACOS)
|
2018-09-25 00:31:33 +00:00
|
|
|
if (isBluetoothAddress(device)) {
|
|
|
|
// ensure we have a discovery running
|
|
|
|
if (btd == nullptr)
|
|
|
|
btd = BTDiscovery::instance();
|
2018-09-26 03:04:02 +00:00
|
|
|
btd->discoverAddress(device);
|
2018-09-25 00:31:33 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
Q_UNUSED(device)
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-02-19 01:20:35 +00:00
|
|
|
void DownloadFromDCWidget::on_search_clicked()
|
|
|
|
{
|
2023-02-27 05:41:46 +00:00
|
|
|
if (is_vendor_searchable(ui.vendor->currentText())) {
|
2024-05-05 05:19:15 +00:00
|
|
|
QString dialogTitle;
|
|
|
|
if (ui.vendor->currentText() == "Uemis")
|
|
|
|
dialogTitle = tr("Find Uemis dive computer");
|
|
|
|
else if (ui.vendor->currentText() == "Garmin")
|
|
|
|
dialogTitle = tr("Find Garmin dive computer");
|
|
|
|
else if (ui.vendor->currentText() == "FIT")
|
|
|
|
dialogTitle = tr("Select diretory to import .fit files from");
|
2014-02-19 01:20:35 +00:00
|
|
|
QString dirName = QFileDialog::getExistingDirectory(this,
|
2018-09-02 00:46:19 +00:00
|
|
|
dialogTitle,
|
2014-02-28 04:09:57 +00:00
|
|
|
QDir::homePath(),
|
|
|
|
QFileDialog::ShowDirsOnly);
|
2014-02-19 01:20:35 +00:00
|
|
|
if (ui.device->findText(dirName) == -1)
|
|
|
|
ui.device->addItem(dirName);
|
|
|
|
ui.device->setEditText(dirName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-09 23:01:48 +00:00
|
|
|
void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
|
2013-05-20 19:43:33 +00:00
|
|
|
{
|
2015-01-09 23:01:48 +00:00
|
|
|
if (currentState == DOWNLOADING) {
|
|
|
|
updateState(CANCELLING);
|
|
|
|
return;
|
|
|
|
}
|
2015-01-11 15:46:21 +00:00
|
|
|
if (currentState == DONE) {
|
|
|
|
// this means we are retrying - so we better clean out the partial
|
|
|
|
// list of downloaded dives from the last attempt
|
|
|
|
diveImportedModel->clearTable();
|
|
|
|
}
|
2013-08-25 22:02:30 +00:00
|
|
|
updateState(DOWNLOADING);
|
2013-05-20 19:43:33 +00:00
|
|
|
|
2015-01-09 23:01:48 +00:00
|
|
|
// you cannot cancel the dialog, just the download
|
|
|
|
ui.cancel->setEnabled(false);
|
2017-04-23 07:51:44 +00:00
|
|
|
ui.downloadCancelRetryButton->setText(tr("Cancel download"));
|
2015-01-09 23:01:48 +00:00
|
|
|
|
2019-09-25 18:49:13 +00:00
|
|
|
auto data = diveImportedModel->thread.data();
|
2017-05-26 14:40:50 +00:00
|
|
|
data->setVendor(ui.vendor->currentText());
|
|
|
|
data->setProduct(ui.product->currentText());
|
2015-07-20 16:35:00 +00:00
|
|
|
#if defined(BT_SUPPORT)
|
2017-05-26 14:40:50 +00:00
|
|
|
data->setBluetoothMode(ui.bluetoothMode->isChecked());
|
2017-12-31 10:44:29 +00:00
|
|
|
if (data->bluetoothMode()) {
|
2018-10-15 10:53:00 +00:00
|
|
|
// Get the selected device address
|
2017-12-31 10:44:29 +00:00
|
|
|
if (btDeviceSelectionDialog != NULL) {
|
|
|
|
data->setDevName(btDeviceSelectionDialog->getSelectedDeviceAddress());
|
|
|
|
data->setDevBluetoothName(btDeviceSelectionDialog->getSelectedDeviceName());
|
|
|
|
} else {
|
2024-05-02 19:26:22 +00:00
|
|
|
auto [address, name] = extractBluetoothNameAddress(ui.device->currentText());
|
2018-09-27 14:08:57 +00:00
|
|
|
data->setDevName(address);
|
|
|
|
data->setDevBluetoothName(name);
|
2017-12-31 10:44:29 +00:00
|
|
|
}
|
2024-06-24 22:01:12 +00:00
|
|
|
if (btd) {
|
|
|
|
// btd should only be active for mac os.
|
|
|
|
// Need to ensure that any scan is shut down BEFORE starting the download
|
|
|
|
// because internally (as of 5.15.13) the QT discovery agent uses a QTimer
|
|
|
|
// that can only be shut off from the same thread it was started from.
|
|
|
|
QString devAddr = data->devName().startsWith("LE:")
|
|
|
|
? data->devName().right(data->devName().size()-3)
|
|
|
|
: data->devName();
|
|
|
|
getBtDeviceInfo(devAddr);
|
|
|
|
}
|
2015-07-20 16:35:00 +00:00
|
|
|
} else
|
|
|
|
// this breaks an "else if" across lines... not happy...
|
|
|
|
#endif
|
2017-05-26 14:40:50 +00:00
|
|
|
if (data->vendor() == "Uemis") {
|
2024-06-08 21:32:17 +00:00
|
|
|
QString devname = ui.device->currentText();
|
|
|
|
auto colon = devname.indexOf(":\\ (UEMISSDA)");
|
|
|
|
if (colon >= 0) {
|
|
|
|
devname.resize(colon + 2);
|
|
|
|
report_info("shortened devname to \"%s\"", qPrintable(devname));
|
2015-04-30 23:35:46 +00:00
|
|
|
}
|
2017-05-26 14:40:50 +00:00
|
|
|
data->setDevName(devname);
|
2015-04-30 23:35:46 +00:00
|
|
|
} else {
|
2017-05-26 14:40:50 +00:00
|
|
|
data->setDevName(ui.device->currentText());
|
2015-04-30 23:35:46 +00:00
|
|
|
}
|
2017-05-26 14:40:50 +00:00
|
|
|
|
|
|
|
data->setForceDownload(ui.forceDownload->isChecked());
|
2017-06-15 09:24:48 +00:00
|
|
|
data->setSaveLog(ui.logToFile->isChecked());
|
|
|
|
data->setSaveDump(ui.dumpToFile->isChecked());
|
2023-04-02 06:28:33 +00:00
|
|
|
data->setSyncTime(ui.syncDiveComputerTime->isChecked());
|
2016-08-10 21:10:15 +00:00
|
|
|
|
2018-08-15 09:56:17 +00:00
|
|
|
qPrefDiveComputer::set_vendor(data->vendor());
|
|
|
|
qPrefDiveComputer::set_product(data->product());
|
|
|
|
qPrefDiveComputer::set_device(data->devName());
|
2017-05-19 09:23:11 +00:00
|
|
|
|
2013-12-08 05:33:46 +00:00
|
|
|
// before we start, remember where the dive_table ended
|
2024-06-07 08:25:09 +00:00
|
|
|
previousLast = static_cast<int>(divelog.dives.size());
|
2019-09-25 18:49:13 +00:00
|
|
|
diveImportedModel->startDownload();
|
2014-12-27 16:31:51 +00:00
|
|
|
|
2017-01-08 13:04:11 +00:00
|
|
|
// FIXME: We should get the _actual_ device info instead of whatever
|
|
|
|
// the user entered in the dropdown.
|
|
|
|
// You can enter "OSTC 3" and download just fine from a "OSTC Sport", but
|
|
|
|
// this check will compair apples and oranges, firmware wise, then.
|
2014-12-28 15:37:11 +00:00
|
|
|
QString product(ui.product->currentText());
|
2017-04-24 16:29:33 +00:00
|
|
|
//
|
|
|
|
// We shouldn't do this for memory dumps.
|
2018-03-03 14:04:49 +00:00
|
|
|
if ((product == "OSTC 3" || product == "OSTC 3+" || product == "OSTC cR" ||
|
2018-08-27 19:09:40 +00:00
|
|
|
product == "OSTC Sport" || product == "OSTC 4" || product == "OSTC Plus") &&
|
2018-07-26 01:40:19 +00:00
|
|
|
!data->saveDump()) {
|
2019-03-18 14:58:07 +00:00
|
|
|
ostcFirmwareCheck.reset(new OstcFirmwareCheck(product));
|
2018-03-03 14:04:49 +00:00
|
|
|
}
|
2013-05-20 19:43:33 +00:00
|
|
|
}
|
|
|
|
|
2013-05-30 08:58:59 +00:00
|
|
|
bool DownloadFromDCWidget::preferDownloaded()
|
|
|
|
{
|
2013-10-03 18:54:25 +00:00
|
|
|
return ui.preferDownloaded->isChecked();
|
2013-05-30 08:58:59 +00:00
|
|
|
}
|
|
|
|
|
2013-12-25 00:26:00 +00:00
|
|
|
void DownloadFromDCWidget::checkLogFile(int state)
|
|
|
|
{
|
|
|
|
ui.chooseLogFile->setEnabled(state == Qt::Checked);
|
2017-05-19 09:23:11 +00:00
|
|
|
// TODO: Verify the Thread.
|
2017-05-19 09:29:03 +00:00
|
|
|
if (state == Qt::Checked) {
|
2013-12-25 00:26:00 +00:00
|
|
|
pickLogFile();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::pickLogFile()
|
|
|
|
{
|
|
|
|
QFileInfo fi(filename);
|
2024-03-16 09:02:54 +00:00
|
|
|
QString logfilename = fi.absolutePath().append(QDir::separator()).append("subsurface.log");
|
2017-05-19 09:29:03 +00:00
|
|
|
QString logFile = QFileDialog::getSaveFileName(this, tr("Choose file for dive computer download logfile"),
|
2024-03-16 09:02:54 +00:00
|
|
|
logfilename, tr("Log files") + " (*.log)");
|
2024-03-16 09:29:05 +00:00
|
|
|
if (!logFile.isEmpty())
|
|
|
|
logfile_name = logFile.toStdString();
|
2013-12-25 00:26:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::checkDumpFile(int state)
|
|
|
|
{
|
|
|
|
ui.chooseDumpFile->setEnabled(state == Qt::Checked);
|
2013-12-26 17:18:57 +00:00
|
|
|
if (state == Qt::Checked) {
|
2017-05-19 09:29:03 +00:00
|
|
|
pickDumpFile();
|
2013-12-26 17:18:57 +00:00
|
|
|
if (!dumpWarningShown) {
|
|
|
|
QMessageBox::warning(this, tr("Warning"),
|
|
|
|
tr("Saving the libdivecomputer dump will NOT download dives to the dive list."));
|
|
|
|
dumpWarningShown = true;
|
|
|
|
}
|
2013-12-25 00:26:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::pickDumpFile()
|
|
|
|
{
|
|
|
|
QFileInfo fi(filename);
|
2024-03-16 09:02:54 +00:00
|
|
|
QString dumpfilename = fi.absolutePath().append(QDir::separator()).append("subsurface.bin");
|
2017-05-19 09:29:03 +00:00
|
|
|
QString dumpFile = QFileDialog::getSaveFileName(this, tr("Choose file for dive computer binary dump file"),
|
2024-03-16 09:02:54 +00:00
|
|
|
dumpfilename, tr("Dump files") + " (*.bin)");
|
2024-03-16 09:29:05 +00:00
|
|
|
if (!dumpFile.isEmpty())
|
|
|
|
dumpfile_name = dumpFile.toStdString();
|
2013-12-25 00:26:00 +00:00
|
|
|
}
|
|
|
|
|
2013-08-25 13:01:59 +00:00
|
|
|
void DownloadFromDCWidget::reject()
|
|
|
|
{
|
|
|
|
// we don't want the download window being able to close
|
|
|
|
// while we're still downloading.
|
2013-08-25 22:02:30 +00:00
|
|
|
if (currentState != DOWNLOADING && currentState != CANCELLING)
|
2013-08-25 13:01:59 +00:00
|
|
|
QDialog::reject();
|
|
|
|
}
|
|
|
|
|
2013-10-15 17:25:53 +00:00
|
|
|
void DownloadFromDCWidget::onDownloadThreadFinished()
|
2013-08-25 22:02:30 +00:00
|
|
|
{
|
2018-09-21 22:41:28 +00:00
|
|
|
// let's update the remembered DCs
|
|
|
|
showRememberedDCs();
|
|
|
|
|
2013-09-01 14:14:54 +00:00
|
|
|
if (currentState == DOWNLOADING) {
|
2024-04-29 05:02:54 +00:00
|
|
|
if (diveImportedModel->thread.error.empty())
|
2013-09-01 14:14:54 +00:00
|
|
|
updateState(DONE);
|
|
|
|
else
|
2019-08-28 09:21:24 +00:00
|
|
|
updateState(ERRORED);
|
2015-01-09 22:44:38 +00:00
|
|
|
} else if (currentState == CANCELLING) {
|
|
|
|
updateState(DONE);
|
|
|
|
}
|
2017-04-23 07:51:44 +00:00
|
|
|
ui.downloadCancelRetryButton->setText(tr("Retry download"));
|
2015-01-09 23:01:48 +00:00
|
|
|
ui.downloadCancelRetryButton->setEnabled(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::on_cancel_clicked()
|
|
|
|
{
|
|
|
|
if (currentState == DOWNLOADING || currentState == CANCELLING)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// now discard all the dives
|
2019-09-22 18:35:38 +00:00
|
|
|
diveImportedModel->clearTable();
|
2015-01-09 23:01:48 +00:00
|
|
|
done(-1);
|
2013-08-25 22:02:30 +00:00
|
|
|
}
|
2015-01-08 13:31:05 +00:00
|
|
|
|
|
|
|
void DownloadFromDCWidget::on_ok_clicked()
|
|
|
|
{
|
2019-08-28 09:21:24 +00:00
|
|
|
if (currentState != DONE && currentState != ERRORED)
|
2015-01-08 13:56:00 +00:00
|
|
|
return;
|
|
|
|
|
2024-06-19 20:45:25 +00:00
|
|
|
int flags = import_flags::is_downloaded;
|
2019-11-16 21:24:06 +00:00
|
|
|
if (preferDownloaded())
|
2024-06-19 20:45:25 +00:00
|
|
|
flags |= import_flags::prefer_imported;
|
2019-11-16 21:24:06 +00:00
|
|
|
if (ui.createNewTrip->isChecked())
|
2024-06-19 20:45:25 +00:00
|
|
|
flags |= import_flags::add_to_new_trip;
|
2019-11-16 21:24:06 +00:00
|
|
|
|
|
|
|
diveImportedModel->recordDives(flags);
|
2015-01-08 13:53:16 +00:00
|
|
|
|
2018-12-23 22:45:12 +00:00
|
|
|
if (ostcFirmwareCheck && currentState == DONE)
|
2024-03-16 09:02:54 +00:00
|
|
|
ostcFirmwareCheck->checkLatest(this, diveImportedModel->thread.data()->internalData(), filename);
|
2015-01-08 17:59:01 +00:00
|
|
|
accept();
|
2015-01-08 13:31:05 +00:00
|
|
|
}
|
2013-08-25 22:02:30 +00:00
|
|
|
|
2017-11-01 07:01:23 +00:00
|
|
|
void DownloadFromDCWidget::updateDeviceEnabled()
|
|
|
|
{
|
|
|
|
// Set up the DC descriptor
|
|
|
|
dc_descriptor_t *descriptor = NULL;
|
2020-05-14 19:15:24 +00:00
|
|
|
descriptor = descriptorLookup.value(ui.vendor->currentText().toLower() + ui.product->currentText().toLower());
|
2017-11-01 07:01:23 +00:00
|
|
|
|
|
|
|
// call dc_descriptor_get_transport to see if the dc_transport_t is DC_TRANSPORT_SERIAL
|
2018-08-27 17:32:14 +00:00
|
|
|
if (dc_descriptor_get_transports(descriptor) & (DC_TRANSPORT_SERIAL | DC_TRANSPORT_USBSTORAGE)) {
|
2017-11-01 07:01:23 +00:00
|
|
|
// if the dc_transport_t is DC_TRANSPORT_SERIAL, then enable the device node box.
|
|
|
|
ui.device->setEnabled(true);
|
|
|
|
} else {
|
|
|
|
// otherwise disable the device node box
|
|
|
|
ui.device->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-25 13:01:59 +00:00
|
|
|
void DownloadFromDCWidget::markChildrenAsDisabled()
|
|
|
|
{
|
2015-01-08 20:56:17 +00:00
|
|
|
ui.device->setEnabled(false);
|
|
|
|
ui.vendor->setEnabled(false);
|
|
|
|
ui.product->setEnabled(false);
|
|
|
|
ui.forceDownload->setEnabled(false);
|
|
|
|
ui.createNewTrip->setEnabled(false);
|
|
|
|
ui.preferDownloaded->setEnabled(false);
|
|
|
|
ui.ok->setEnabled(false);
|
|
|
|
ui.search->setEnabled(false);
|
|
|
|
ui.logToFile->setEnabled(false);
|
|
|
|
ui.dumpToFile->setEnabled(false);
|
|
|
|
ui.chooseLogFile->setEnabled(false);
|
|
|
|
ui.chooseDumpFile->setEnabled(false);
|
|
|
|
ui.selectAllButton->setEnabled(false);
|
|
|
|
ui.unselectAllButton->setEnabled(false);
|
2015-07-06 13:18:06 +00:00
|
|
|
ui.bluetoothMode->setEnabled(false);
|
|
|
|
ui.chooseBluetoothDevice->setEnabled(false);
|
2023-04-02 06:28:33 +00:00
|
|
|
ui.syncDiveComputerTime->setEnabled(false);
|
2013-08-25 13:01:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::markChildrenAsEnabled()
|
|
|
|
{
|
2017-11-01 07:01:23 +00:00
|
|
|
updateDeviceEnabled();
|
2015-01-08 20:56:17 +00:00
|
|
|
ui.vendor->setEnabled(true);
|
|
|
|
ui.product->setEnabled(true);
|
|
|
|
ui.forceDownload->setEnabled(true);
|
|
|
|
ui.createNewTrip->setEnabled(true);
|
|
|
|
ui.preferDownloaded->setEnabled(true);
|
|
|
|
ui.ok->setEnabled(true);
|
|
|
|
ui.cancel->setEnabled(true);
|
|
|
|
ui.search->setEnabled(true);
|
|
|
|
ui.logToFile->setEnabled(true);
|
|
|
|
ui.dumpToFile->setEnabled(true);
|
|
|
|
ui.chooseLogFile->setEnabled(true);
|
|
|
|
ui.chooseDumpFile->setEnabled(true);
|
|
|
|
ui.selectAllButton->setEnabled(true);
|
|
|
|
ui.unselectAllButton->setEnabled(true);
|
2015-07-20 16:35:00 +00:00
|
|
|
#if defined(BT_SUPPORT)
|
2015-07-06 13:18:06 +00:00
|
|
|
ui.bluetoothMode->setEnabled(true);
|
|
|
|
ui.chooseBluetoothDevice->setEnabled(true);
|
2015-07-20 16:35:00 +00:00
|
|
|
#endif
|
2023-04-02 06:28:33 +00:00
|
|
|
ui.syncDiveComputerTime->setEnabled(true);
|
2015-07-06 13:18:06 +00:00
|
|
|
}
|
|
|
|
|
2015-07-20 16:35:00 +00:00
|
|
|
#if defined(BT_SUPPORT)
|
2015-07-06 13:18:06 +00:00
|
|
|
void DownloadFromDCWidget::selectRemoteBluetoothDevice()
|
|
|
|
{
|
2015-07-06 13:35:13 +00:00
|
|
|
if (!btDeviceSelectionDialog) {
|
|
|
|
btDeviceSelectionDialog = new BtDeviceSelectionDialog(this);
|
|
|
|
connect(btDeviceSelectionDialog, SIGNAL(finished(int)),
|
|
|
|
this, SLOT(bluetoothSelectionDialogIsFinished(int)));
|
|
|
|
}
|
|
|
|
|
|
|
|
btDeviceSelectionDialog->show();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::bluetoothSelectionDialogIsFinished(int result)
|
|
|
|
{
|
|
|
|
if (result == QDialog::Accepted) {
|
|
|
|
/* Make the selected Bluetooth device default */
|
2017-11-12 11:33:20 +00:00
|
|
|
ui.device->setEditText(btDeviceSelectionDialog->getSelectedDeviceText());
|
2018-07-26 01:40:19 +00:00
|
|
|
} else if (result == QDialog::Rejected) {
|
2015-07-06 13:35:13 +00:00
|
|
|
/* Disable Bluetooth download mode */
|
|
|
|
ui.bluetoothMode->setChecked(false);
|
|
|
|
}
|
2015-07-06 13:18:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DownloadFromDCWidget::enableBluetoothMode(int state)
|
|
|
|
{
|
|
|
|
ui.chooseBluetoothDevice->setEnabled(state == Qt::Checked);
|
2015-09-06 21:12:00 +00:00
|
|
|
|
2024-04-16 09:38:47 +00:00
|
|
|
/* This is convoluted enough to warrant explanation:
|
2024-04-16 20:45:53 +00:00
|
|
|
1. If Bluetooth is enabled, but no Bluetooth address then scan.
|
|
|
|
2. If Bluetooth is enabled and we have a Bluetooth address, skip scan.
|
|
|
|
3. If Bluetooth is not enabled, but it's a Bluetooth address, clear it. */
|
2024-03-05 09:05:08 +00:00
|
|
|
if (state == Qt::Checked) {
|
2024-03-07 16:33:13 +00:00
|
|
|
if (!isBluetoothAddress(ui.device->currentText()))
|
2024-03-06 06:53:48 +00:00
|
|
|
selectRemoteBluetoothDevice();
|
2024-04-16 09:38:47 +00:00
|
|
|
} else
|
2024-04-16 20:45:53 +00:00
|
|
|
if (isBluetoothAddress(ui.device->currentText()))
|
2024-04-16 09:38:47 +00:00
|
|
|
ui.device->setCurrentIndex(-1);
|
2013-08-25 13:01:59 +00:00
|
|
|
}
|
2015-07-20 16:35:00 +00:00
|
|
|
#endif
|
2013-08-25 13:01:59 +00:00
|
|
|
|
2013-09-16 21:04:42 +00:00
|
|
|
static void fillDeviceList(const char *name, void *data)
|
|
|
|
{
|
|
|
|
QComboBox *comboBox = (QComboBox *)data;
|
|
|
|
comboBox->addItem(name);
|
|
|
|
}
|
|
|
|
|
2018-08-27 17:32:14 +00:00
|
|
|
void DownloadFromDCWidget::fill_device_list(unsigned int transport)
|
2013-09-16 21:04:42 +00:00
|
|
|
{
|
|
|
|
int deviceIndex;
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.device->clear();
|
2018-08-27 17:32:14 +00:00
|
|
|
deviceIndex = enumerate_devices(fillDeviceList, ui.device, transport);
|
2013-09-16 21:04:42 +00:00
|
|
|
if (deviceIndex >= 0)
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.device->setCurrentIndex(deviceIndex);
|
2013-09-16 21:04:42 +00:00
|
|
|
}
|