From dec47e11cd3aa1f4c6333a69c72df4c4d5e0628f Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Tue, 18 Apr 2017 19:14:03 +0200 Subject: [PATCH] Separate the download thread from the widget logic This is important to not duplicate code for the Qml view. Now the DownloadFromDiveComputer widget is mostly free from important code (that has been upgraded to the core folder), and I can start coding the QML interface. There are still a few functions on the desktop widget that will die so I can call them via the QML code later. I also touched the location of a few globals (please, let's stop using those) - because it was declared on the desktop code and being used in the core. Signed-off-by: Tomaz Canabrava Signed-off-by: Dirk Hohndel --- core/CMakeLists.txt | 2 + core/dive.h | 2 + core/divelist.c | 3 + core/downloadfromdcthread.cpp | 36 ++++++++++ core/downloadfromdcthread.h | 21 ++++++ core/uemis-downloader.c | 2 + desktop-widgets/downloadfromdivecomputer.cpp | 72 +++++++------------- desktop-widgets/downloadfromdivecomputer.h | 14 +--- desktop-widgets/mainwindow.cpp | 5 +- qt-models/diveimportedmodel.cpp | 10 ++- qt-models/diveimportedmodel.h | 3 + 11 files changed, 106 insertions(+), 64 deletions(-) create mode 100644 core/downloadfromdcthread.cpp create mode 100644 core/downloadfromdcthread.h diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index fc6d20ba8..b2effd519 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -84,11 +84,13 @@ set(SUBSURFACE_CORE_LIB_SRCS isocialnetworkintegration.cpp gpslocation.cpp cloudstorage.cpp + downloadfromdcthread.cpp #Subsurface Qt have the Subsurface structs QObjectified for easy access via QML. subsurface-qt/DiveObjectHelper.cpp subsurface-qt/CylinderObjectHelper.cpp subsurface-qt/SettingsObjectWrapper.cpp + ${SERIAL_FTDI} ${PLATFORM_SRC} ${BT_CORE_SRC_FILES} diff --git a/core/dive.h b/core/dive.h index c2ae1e36d..c65d3ffc5 100644 --- a/core/dive.h +++ b/core/dive.h @@ -971,6 +971,8 @@ extern volume_t string_to_volume(const char *str, pressure_t workp); extern fraction_t string_to_fraction(const char *str); extern void average_max_depth(struct diveplan *dive, int *avg_depth, int *max_depth); +extern struct dive_table downloadTable; + #include "pref.h" #endif // DIVE_H diff --git a/core/divelist.c b/core/divelist.c index fd7fc6790..4f253039b 100644 --- a/core/divelist.c +++ b/core/divelist.c @@ -55,6 +55,9 @@ dive_trip_t *dive_trip_list; unsigned int amount_selected; +// We need to stop using globals, really. +struct dive_table downloadTable; + #if DEBUG_SELECTION_TRACKING void dump_selection(void) { diff --git a/core/downloadfromdcthread.cpp b/core/downloadfromdcthread.cpp new file mode 100644 index 000000000..dc13a23d7 --- /dev/null +++ b/core/downloadfromdcthread.cpp @@ -0,0 +1,36 @@ +#include "downloadfromdcthread.h" +#include "core/libdivecomputer.h" + +static QString str_error(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + const QString str = QString().vsprintf(fmt, args); + va_end(args); + + return str; +} + +DownloadThread::DownloadThread(QObject *parent, device_data_t *data) : QThread(parent), + data(data) +{ + data->download_table = nullptr; +} + +void DownloadThread::setDiveTable(struct dive_table* table) +{ + data->download_table = table; +} + +void DownloadThread::run() +{ + Q_ASSERT(data->download_table != nullptr); + const char *errorText; + import_thread_cancelled = false; + if (!strcmp(data->vendor, "Uemis")) + errorText = do_uemis_import(data); + else + errorText = do_libdivecomputer_import(data); + if (errorText) + error = str_error(errorText, data->devname, data->vendor, data->product); +} diff --git a/core/downloadfromdcthread.h b/core/downloadfromdcthread.h new file mode 100644 index 000000000..ab21db0aa --- /dev/null +++ b/core/downloadfromdcthread.h @@ -0,0 +1,21 @@ +#ifndef DOWNLOADFROMDCTHREAD_H +#define DOWNLOADFROMDCTHREAD_H + +#include +#include "dive.h" +#include "libdivecomputer.h" + +class DownloadThread : public QThread { + Q_OBJECT +public: + DownloadThread(QObject *parent, device_data_t *data); + void setDiveTable(struct dive_table *table); + void run() override; + + QString error; + +private: + device_data_t *data; +}; + +#endif diff --git a/core/uemis-downloader.c b/core/uemis-downloader.c index 79c88d28b..e65c1fd46 100644 --- a/core/uemis-downloader.c +++ b/core/uemis-downloader.c @@ -76,6 +76,8 @@ static int dive_to_read = 0; static int max_deleted_seen = -1; +extern struct dive_table downloadTable; + /* helper function to parse the Uemis data structures */ static void uemis_ts(char *buffer, void *_when) { diff --git a/desktop-widgets/downloadfromdivecomputer.cpp b/desktop-widgets/downloadfromdivecomputer.cpp index 6392a2d1a..c38ffe980 100644 --- a/desktop-widgets/downloadfromdivecomputer.cpp +++ b/desktop-widgets/downloadfromdivecomputer.cpp @@ -37,8 +37,6 @@ namespace DownloadFromDcGlobal { const char *err_string; }; -struct dive_table downloadTable; - // Workaround abuse of old libdc types #define DC_TRANSPORT_BLUETOOTH 1024 @@ -53,37 +51,51 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) : ostcFirmwareCheck(0), currentState(INITIAL) { + fill_computer_list(); + + diveImportedModel = new DiveImportedModel(this); + diveImportedModel->setDiveTable(&downloadTable); + vendorModel = new QStringListModel(vendorList); + QShortcut *close = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this); + QShortcut *quit = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this); + + int startingWidth = defaultModelFont().pointSize(); + clear_table(&downloadTable); ui.setupUi(this); ui.progressBar->hide(); ui.progressBar->setMinimum(0); ui.progressBar->setMaximum(100); - diveImportedModel = new DiveImportedModel(this); ui.downloadedView->setModel(diveImportedModel); ui.downloadedView->setSelectionBehavior(QAbstractItemView::SelectRows); ui.downloadedView->setSelectionMode(QAbstractItemView::SingleSelection); - int startingWidth = defaultModelFont().pointSize(); ui.downloadedView->setColumnWidth(0, startingWidth * 20); ui.downloadedView->setColumnWidth(1, startingWidth * 10); ui.downloadedView->setColumnWidth(2, startingWidth * 10); - connect(ui.downloadedView, SIGNAL(clicked(QModelIndex)), diveImportedModel, SLOT(changeSelected(QModelIndex))); + ui.chooseDumpFile->setEnabled(ui.dumpToFile->isChecked()); + ui.chooseLogFile->setEnabled(ui.logToFile->isChecked()); + ui.selectAllButton->setEnabled(false); + ui.unselectAllButton->setEnabled(false); + ui.vendor->setModel(vendorModel); progress_bar_text = ""; - fill_computer_list(); + timer->setInterval(200); - ui.chooseDumpFile->setEnabled(ui.dumpToFile->isChecked()); + connect(ui.downloadedView, SIGNAL(clicked(QModelIndex)), diveImportedModel, SLOT(changeSelected(QModelIndex))); connect(ui.chooseDumpFile, SIGNAL(clicked()), this, SLOT(pickDumpFile())); connect(ui.dumpToFile, SIGNAL(stateChanged(int)), this, SLOT(checkDumpFile(int))); - ui.chooseLogFile->setEnabled(ui.logToFile->isChecked()); connect(ui.chooseLogFile, SIGNAL(clicked()), this, SLOT(pickLogFile())); connect(ui.logToFile, SIGNAL(stateChanged(int)), this, SLOT(checkLogFile(int))); - ui.selectAllButton->setEnabled(false); - ui.unselectAllButton->setEnabled(false); connect(ui.selectAllButton, SIGNAL(clicked()), diveImportedModel, SLOT(selectAll())); connect(ui.unselectAllButton, SIGNAL(clicked()), diveImportedModel, SLOT(selectNone())); - vendorModel = new QStringListModel(vendorList); - ui.vendor->setModel(vendorModel); + connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar())); + connect(close, SIGNAL(activated()), this, SLOT(close())); + connect(quit, SIGNAL(activated()), parent, SLOT(close())); +#if defined(BT_SUPPORT) && defined(SSRF_CUSTOM_SERIAL) + connect(ui.bluetoothMode, SIGNAL(stateChanged(int)), this, SLOT(enableBluetoothMode(int))); + connect(ui.chooseBluetoothDevice, SIGNAL(clicked()), this, SLOT(selectRemoteBluetoothDevice())); +#endif auto dc = SettingsObjectWrapper::instance()->dive_computer_settings; if (!dc->dc_vendor().isEmpty()) { @@ -96,14 +108,8 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) : if (!dc->dc_device().isEmpty()) ui.device->setEditText(dc->dc_device()); - timer->setInterval(200); - connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar())); updateState(INITIAL); memset(&data, 0, sizeof(data)); - QShortcut *close = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this); - connect(close, SIGNAL(activated()), this, SLOT(close())); - QShortcut *quit = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this); - connect(quit, SIGNAL(activated()), parent, SLOT(close())); ui.ok->setEnabled(false); ui.downloadCancelRetryButton->setEnabled(true); ui.downloadCancelRetryButton->setText(tr("Download")); @@ -113,8 +119,6 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) : ui.bluetoothMode->setChecked(dc->downloadMode() == DC_TRANSPORT_BLUETOOTH); btDeviceSelectionDialog = 0; ui.chooseBluetoothDevice->setEnabled(ui.bluetoothMode->isChecked()); - connect(ui.bluetoothMode, SIGNAL(stateChanged(int)), this, SLOT(enableBluetoothMode(int))); - connect(ui.chooseBluetoothDevice, SIGNAL(clicked()), this, SLOT(selectRemoteBluetoothDevice())); #else ui.bluetoothMode->hide(); ui.chooseBluetoothDevice->hide(); @@ -380,6 +384,7 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked() // before we start, remember where the dive_table ended previousLast = dive_table.nr; + thread->setDiveTable(&downloadTable); thread->start(); // FIXME: We should get the _actual_ device info instead of whatever @@ -624,30 +629,3 @@ void DownloadFromDCWidget::fill_device_list(int dc_type) ui.device->setCurrentIndex(deviceIndex); } -DownloadThread::DownloadThread(QObject *parent, device_data_t *data) : QThread(parent), - data(data) -{ -} - -static QString str_error(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - const QString str = QString().vsprintf(fmt, args); - va_end(args); - - return str; -} - -void DownloadThread::run() -{ - const char *errorText; - import_thread_cancelled = false; - data->download_table = &downloadTable; - if (!strcmp(data->vendor, "Uemis")) - errorText = do_uemis_import(data); - else - errorText = do_libdivecomputer_import(data); - if (errorText) - error = str_error(errorText, data->devname, data->vendor, data->product); -} diff --git a/desktop-widgets/downloadfromdivecomputer.h b/desktop-widgets/downloadfromdivecomputer.h index b1967766a..906cc6eb7 100644 --- a/desktop-widgets/downloadfromdivecomputer.h +++ b/desktop-widgets/downloadfromdivecomputer.h @@ -10,6 +10,8 @@ #include "core/libdivecomputer.h" #include "desktop-widgets/configuredivecomputerdialog.h" +#include "core/downloadfromdcthread.h" + #include "ui_downloadfromdivecomputer.h" #if defined(BT_SUPPORT) @@ -19,18 +21,6 @@ class QStringListModel; class DiveImportedModel; -class DownloadThread : public QThread { - Q_OBJECT -public: - DownloadThread(QObject *parent, device_data_t *data); - virtual void run(); - - QString error; - -private: - device_data_t *data; -}; - class DownloadFromDCWidget : public QDialog { Q_OBJECT public: diff --git a/desktop-widgets/mainwindow.cpp b/desktop-widgets/mainwindow.cpp index 3e0bfa137..824451bfd 100644 --- a/desktop-widgets/mainwindow.cpp +++ b/desktop-widgets/mainwindow.cpp @@ -778,9 +778,8 @@ void MainWindow::on_actionQuit_triggered() void MainWindow::on_actionDownloadDC_triggered() { - DownloadFromDCWidget dlg(this); - - dlg.exec(); + DownloadFromDCWidget dlg(this); + dlg.show(); } void MainWindow::on_actionDownloadWeb_triggered() diff --git a/qt-models/diveimportedmodel.cpp b/qt-models/diveimportedmodel.cpp index b1e5a6174..08c36e7e6 100644 --- a/qt-models/diveimportedmodel.cpp +++ b/qt-models/diveimportedmodel.cpp @@ -4,7 +4,8 @@ DiveImportedModel::DiveImportedModel(QObject *o) : QAbstractTableModel(o), firstIndex(0), lastIndex(-1), - checkStates(0) + checkStates(nullptr), + diveTable(nullptr) { } @@ -37,6 +38,11 @@ QVariant DiveImportedModel::headerData(int section, Qt::Orientation orientation, return QVariant(); } +void DiveImportedModel::setDiveTable(struct dive_table* table) +{ + diveTable = table; +} + QVariant DiveImportedModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) @@ -45,7 +51,7 @@ QVariant DiveImportedModel::data(const QModelIndex &index, int role) const if (index.row() + firstIndex > lastIndex) return QVariant(); - struct dive *d = get_dive_from_table(index.row() + firstIndex, &downloadTable); + struct dive *d = get_dive_from_table(index.row() + firstIndex, diveTable); if (!d) return QVariant(); if (role == Qt::DisplayRole) { diff --git a/qt-models/diveimportedmodel.h b/qt-models/diveimportedmodel.h index 06d73b6b2..1127fc97e 100644 --- a/qt-models/diveimportedmodel.h +++ b/qt-models/diveimportedmodel.h @@ -2,12 +2,14 @@ #define DIVEIMPORTEDMODEL_H #include +#include "core/dive.h" class DiveImportedModel : public QAbstractTableModel { Q_OBJECT public: DiveImportedModel(QObject *o); + void setDiveTable(struct dive_table *table); int columnCount(const QModelIndex& index = QModelIndex()) const; int rowCount(const QModelIndex& index = QModelIndex()) const; QVariant data(const QModelIndex& index, int role) const; @@ -26,6 +28,7 @@ private: int firstIndex; int lastIndex; bool *checkStates; + struct dive_table *diveTable; }; #endif