Import: Make DownloadThread a subobject of DiveImportedModel

Currently, desktop and mobile are accessing the DownloadThread
and the DiveImportedModel concurrently. This makes a big data
flow mess. To achieve a more hierarchical data flow, start
by making the DownloadThread a subobject of DiveImportedModel.

Start the download by calling a function in DiveImportedModel.

Route the finished signal through DiveImportedModel. Thus,
the model can reload itself with the new data.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2019-09-25 20:49:13 +02:00 committed by Dirk Hohndel
parent 6e343c734a
commit ad7ffa0af0
5 changed files with 45 additions and 33 deletions

View file

@ -7,6 +7,7 @@
#include "core/settings/qPrefDiveComputer.h" #include "core/settings/qPrefDiveComputer.h"
#include "core/subsurface-string.h" #include "core/subsurface-string.h"
#include "core/uemis.h" #include "core/uemis.h"
#include "core/downloadfromdcthread.h"
#include "desktop-widgets/divelistview.h" #include "desktop-widgets/divelistview.h"
#include "desktop-widgets/mainwindow.h" #include "desktop-widgets/mainwindow.h"
#include "qt-models/diveimportedmodel.h" #include "qt-models/diveimportedmodel.h"
@ -67,8 +68,7 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) :
connect(close, SIGNAL(activated()), this, SLOT(close())); connect(close, SIGNAL(activated()), this, SLOT(close()));
connect(quit, SIGNAL(activated()), parent, SLOT(close())); connect(quit, SIGNAL(activated()), parent, SLOT(close()));
connect(&thread, SIGNAL(finished()), connect(diveImportedModel, &DiveImportedModel::downloadFinished, this, &DownloadFromDCWidget::onDownloadThreadFinished);
this, SLOT(onDownloadThreadFinished()), Qt::QueuedConnection);
if (!qPrefDiveComputer::vendor().isEmpty()) { if (!qPrefDiveComputer::vendor().isEmpty()) {
ui.vendor->setCurrentIndex(ui.vendor->findText(qPrefDiveComputer::vendor())); ui.vendor->setCurrentIndex(ui.vendor->findText(qPrefDiveComputer::vendor()));
@ -272,7 +272,7 @@ void DownloadFromDCWidget::updateState(states state)
markChildrenAsEnabled(); markChildrenAsEnabled();
progress_bar_text = ""; progress_bar_text = "";
} else { } else {
if (thread.table()->nr != 0) if (diveImportedModel->thread.table()->nr != 0)
progress_bar_text = ""; progress_bar_text = "";
ui.progressBar->setValue(100); ui.progressBar->setValue(100);
markChildrenAsEnabled(); markChildrenAsEnabled();
@ -297,7 +297,7 @@ void DownloadFromDCWidget::updateState(states state)
else if (state == ERRORED) { else if (state == ERRORED) {
timer->stop(); timer->stop();
QMessageBox::critical(this, TITLE_OR_TEXT(tr("Error"), thread.error), QMessageBox::Ok); QMessageBox::critical(this, TITLE_OR_TEXT(tr("Error"), diveImportedModel->thread.error), QMessageBox::Ok);
markChildrenAsEnabled(); markChildrenAsEnabled();
progress_bar_text = ""; progress_bar_text = "";
ui.progressBar->hide(); ui.progressBar->hide();
@ -367,7 +367,7 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
// this means we are retrying - so we better clean out the partial // this means we are retrying - so we better clean out the partial
// list of downloaded dives from the last attempt // list of downloaded dives from the last attempt
diveImportedModel->clearTable(); diveImportedModel->clearTable();
clear_dive_table(thread.table()); clear_dive_table(diveImportedModel->thread.table());
} }
updateState(DOWNLOADING); updateState(DOWNLOADING);
@ -375,7 +375,7 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
ui.cancel->setEnabled(false); ui.cancel->setEnabled(false);
ui.downloadCancelRetryButton->setText(tr("Cancel download")); ui.downloadCancelRetryButton->setText(tr("Cancel download"));
auto data = thread.data(); auto data = diveImportedModel->thread.data();
data->setVendor(ui.vendor->currentText()); data->setVendor(ui.vendor->currentText());
data->setProduct(ui.product->currentText()); data->setProduct(ui.product->currentText());
#if defined(BT_SUPPORT) #if defined(BT_SUPPORT)
@ -417,7 +417,7 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
// before we start, remember where the dive_table ended // before we start, remember where the dive_table ended
previousLast = dive_table.nr; previousLast = dive_table.nr;
thread.start(); diveImportedModel->startDownload();
// FIXME: We should get the _actual_ device info instead of whatever // FIXME: We should get the _actual_ device info instead of whatever
// the user entered in the dropdown. // the user entered in the dropdown.
@ -500,7 +500,7 @@ void DownloadFromDCWidget::onDownloadThreadFinished()
showRememberedDCs(); showRememberedDCs();
if (currentState == DOWNLOADING) { if (currentState == DOWNLOADING) {
if (thread.error.isEmpty()) if (diveImportedModel->thread.error.isEmpty())
updateState(DONE); updateState(DONE);
else else
updateState(ERRORED); updateState(ERRORED);
@ -509,7 +509,6 @@ void DownloadFromDCWidget::onDownloadThreadFinished()
} }
ui.downloadCancelRetryButton->setText(tr("Retry download")); ui.downloadCancelRetryButton->setText(tr("Retry download"));
ui.downloadCancelRetryButton->setEnabled(true); ui.downloadCancelRetryButton->setEnabled(true);
diveImportedModel->repopulate(thread.table(), thread.sites());
} }
void DownloadFromDCWidget::on_cancel_clicked() void DownloadFromDCWidget::on_cancel_clicked()
@ -518,7 +517,7 @@ void DownloadFromDCWidget::on_cancel_clicked()
return; return;
// now discard all the dives // now discard all the dives
clear_dive_table(thread.table()); clear_dive_table(diveImportedModel->thread.table());
done(-1); done(-1);
} }
@ -526,8 +525,8 @@ void DownloadFromDCWidget::on_ok_clicked()
{ {
if (currentState != DONE && currentState != ERRORED) if (currentState != DONE && currentState != ERRORED)
return; return;
struct dive_table *table = thread.table(); struct dive_table *table = diveImportedModel->thread.table();
struct dive_site_table *sites = thread.sites(); struct dive_site_table *sites = diveImportedModel->thread.sites();
// delete non-selected dives // delete non-selected dives
int total = table->nr; int total = table->nr;
@ -536,11 +535,11 @@ void DownloadFromDCWidget::on_ok_clicked()
if (diveImportedModel->data(diveImportedModel->index(i, 0), Qt::CheckStateRole) == Qt::Checked) if (diveImportedModel->data(diveImportedModel->index(i, 0), Qt::CheckStateRole) == Qt::Checked)
j++; j++;
else else
delete_dive_from_table(thread.table(), j); delete_dive_from_table(diveImportedModel->thread.table(), j);
} }
if (table->nr > 0) { if (table->nr > 0) {
auto data = thread.data(); auto data = diveImportedModel->thread.data();
int flags = IMPORT_IS_DOWNLOADED; int flags = IMPORT_IS_DOWNLOADED;
if (preferDownloaded()) if (preferDownloaded())
flags |= IMPORT_PREFER_IMPORTED; flags |= IMPORT_PREFER_IMPORTED;
@ -550,7 +549,7 @@ void DownloadFromDCWidget::on_ok_clicked()
} }
if (ostcFirmwareCheck && currentState == DONE) if (ostcFirmwareCheck && currentState == DONE)
ostcFirmwareCheck->checkLatest(this, thread.data()->internalData()); ostcFirmwareCheck->checkLatest(this, diveImportedModel->thread.data()->internalData());
accept(); accept();
} }

View file

@ -11,7 +11,6 @@
#include "core/libdivecomputer.h" #include "core/libdivecomputer.h"
#include "desktop-widgets/configuredivecomputerdialog.h" #include "desktop-widgets/configuredivecomputerdialog.h"
#include "core/downloadfromdcthread.h"
#include "ui_downloadfromdivecomputer.h" #include "ui_downloadfromdivecomputer.h"
@ -21,6 +20,7 @@
class QStringListModel; class QStringListModel;
class DiveImportedModel; class DiveImportedModel;
class BTDiscovery;
class DownloadFromDCWidget : public QDialog { class DownloadFromDCWidget : public QDialog {
Q_OBJECT Q_OBJECT
@ -72,7 +72,6 @@ private:
QStringListModel vendorModel; QStringListModel vendorModel;
QStringListModel productModel; QStringListModel productModel;
Ui::DownloadFromDiveComputer ui; Ui::DownloadFromDiveComputer ui;
DownloadThread thread;
bool downloading; bool downloading;
int previousLast; int previousLast;

View file

@ -24,18 +24,13 @@ Kirigami.Page {
property alias product: comboProduct.currentIndex property alias product: comboProduct.currentIndex
property alias connection: comboConnection.currentIndex property alias connection: comboConnection.currentIndex
DCDownloadThread { DCImportModel {
id: downloadThread id: importModel
onFinished : { onDownloadFinished : {
if (!table || !sites) {
console.warn("DCDownloadThread::onFinished(): table or sites is null!")
return
}
importModel.repopulate(table, sites)
progressBar.visible = false progressBar.visible = false
if (dcImportModel.rowCount() > 0) { if (rowCount() > 0) {
console.log(dcImportModel.rowCount() + " dive downloaded") console.log(rowCount() + " dive downloaded")
divesDownloaded = true divesDownloaded = true
} else { } else {
console.log("no new dives downloaded") console.log("no new dives downloaded")
@ -45,10 +40,6 @@ Kirigami.Page {
} }
} }
DCImportModel {
id: importModel
}
ColumnLayout { ColumnLayout {
anchors.top: parent.top anchors.top: parent.top
height: parent.height height: parent.height
@ -295,7 +286,7 @@ Kirigami.Page {
message += " downloading " + (manager.DC_forceDownload ? "all" : "only new" ) + " dives"; message += " downloading " + (manager.DC_forceDownload ? "all" : "only new" ) + " dives";
manager.appendTextToLog(message) manager.appendTextToLog(message)
progressBar.visible = true progressBar.visible = true
downloadThread.start() importModel.startDownload()
} }
} }
SsrfButton { SsrfButton {

View file

@ -8,6 +8,7 @@ DiveImportedModel::DiveImportedModel(QObject *o) : QAbstractTableModel(o),
diveTable(nullptr), diveTable(nullptr),
sitesTable(nullptr) sitesTable(nullptr)
{ {
connect(&thread, &QThread::finished, this, &DiveImportedModel::downloadThreadFinished);
} }
int DiveImportedModel::columnCount(const QModelIndex&) const int DiveImportedModel::columnCount(const QModelIndex&) const
@ -129,6 +130,17 @@ void DiveImportedModel::clearTable()
endRemoveRows(); endRemoveRows();
} }
void DiveImportedModel::downloadThreadFinished()
{
repopulate(thread.table(), thread.sites());
emit downloadFinished();
}
void DiveImportedModel::startDownload()
{
thread.start();
}
void DiveImportedModel::repopulate(dive_table_t *table, struct dive_site_table *sites) void DiveImportedModel::repopulate(dive_table_t *table, struct dive_site_table *sites)
{ {
beginResetModel(); beginResetModel();

View file

@ -4,6 +4,7 @@
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <vector> #include <vector>
#include "core/divesite.h" #include "core/divesite.h"
#include "core/downloadfromdcthread.h"
class DiveImportedModel : public QAbstractTableModel class DiveImportedModel : public QAbstractTableModel
{ {
@ -20,8 +21,10 @@ public:
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex &index) const;
Q_INVOKABLE void clearTable(); Q_INVOKABLE void clearTable();
QHash<int, QByteArray> roleNames() const; QHash<int, QByteArray> roleNames() const;
Q_INVOKABLE void repopulate(dive_table_t *table, dive_site_table_t *sites);
Q_INVOKABLE void recordDives(); Q_INVOKABLE void recordDives();
Q_INVOKABLE void startDownload();
DownloadThread thread;
public public
slots: slots:
void changeSelected(QModelIndex clickedIndex); void changeSelected(QModelIndex clickedIndex);
@ -29,7 +32,15 @@ slots:
void selectAll(); void selectAll();
void selectNone(); void selectNone();
private
slots:
void downloadThreadFinished();
signals:
void downloadFinished();
private: private:
void repopulate(dive_table_t *table, dive_site_table_t *sites);
int firstIndex; int firstIndex;
int lastIndex; int lastIndex;
std::vector<char> checkStates; // char instead of bool to avoid silly pessimization of std::vector. std::vector<char> checkStates; // char instead of bool to avoid silly pessimization of std::vector.