Merge branch 'downloaddialog' of github.com:danilocesar/subsurface

This commit is contained in:
Dirk Hohndel 2013-09-10 12:07:34 -07:00
commit 636477becc
2 changed files with 143 additions and 67 deletions

View file

@ -10,6 +10,8 @@
#include <QThread>
#include <QDebug>
#include <QStringListModel>
#include <QTimer>
#include <QMessageBox>
struct product {
const char *product;
@ -42,7 +44,8 @@ DownloadFromDCWidget *DownloadFromDCWidget::instance()
}
DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) :
QDialog(parent, f), ui(new Ui::DownloadFromDiveComputer), thread(0), downloading(false)
QDialog(parent, f), ui(new Ui::DownloadFromDiveComputer), thread(0), timer(new QTimer(this)),
currentState(INITIAL)
{
ui->setupUi(this);
ui->progressBar->hide();
@ -61,21 +64,86 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) :
}
if (default_dive_computer_device)
ui->device->setText(default_dive_computer_device);
timer->setInterval(200);
connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
updateState(INITIAL);
}
void DownloadFromDCWidget::runDialog()
{
// Since the DownloadDialog is only
// created once, we need to do put some starting code here
ui->progressBar->hide();
markChildrenAsEnabled();
updateState(INITIAL);
exec();
}
void DownloadFromDCWidget::stoppedDownloading()
void DownloadFromDCWidget::updateProgressBar()
{
downloading = false;
ui->progressBar->setValue(progress_bar_fraction *100);
}
void DownloadFromDCWidget::updateState(states state)
{
if (state == currentState)
return;
if (state == INITIAL) {
ui->progressBar->hide();
markChildrenAsEnabled();
timer->stop();
}
// tries to cancel an on going download
else if (currentState == DOWNLOADING && state == CANCELLING) {
import_thread_cancelled = true;
ui->cancel->setEnabled(false);
}
// user pressed cancel but the application isn't doing anything.
// means close the window
else if ((currentState == INITIAL || currentState == CANCELLED || currentState == DONE || currentState == ERROR)
&& state == CANCELLING) {
timer->stop();
reject();
}
// the cancelation process is finished
else if (currentState == CANCELLING && (state == DONE || state == CANCELLED)) {
timer->stop();
state = CANCELLED;
ui->progressBar->setValue(0);
ui->progressBar->hide();
markChildrenAsEnabled();
}
// DOWNLOAD is finally done, close the dialog and go back to the main window
else if (currentState == DOWNLOADING && state == DONE) {
timer->stop();
ui->progressBar->setValue(100);
markChildrenAsEnabled();
accept();
}
// DOWNLOAD is started.
else if (state == DOWNLOADING) {
timer->start();
ui->progressBar->setValue(0);
ui->progressBar->show();
markChildrenAsDisabled();
}
// got an error
else if (state == ERROR) {
QMessageBox::critical(this, tr("Error"), this->thread->error, QMessageBox::Ok);
markChildrenAsEnabled();
ui->progressBar->hide();
ui->ok->setText(tr("retry"));
}
// properly updating the widget state
currentState = state;
}
void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString& vendor)
@ -136,28 +204,15 @@ void DownloadFromDCWidget::fill_computer_list()
void DownloadFromDCWidget::on_cancel_clicked()
{
import_thread_cancelled = true;
if (thread) {
thread->wait();
thread->deleteLater();
thread = 0;
}
// Confusing, but if the user press cancel during a download
// he probably want to cancel the download, not to close the window.
if (!downloading)
close();
updateState(CANCELLING);
}
void DownloadFromDCWidget::on_ok_clicked()
{
if (downloading)
return;
markChildrenAsDisabled();
ui->progressBar->setValue(0);
ui->progressBar->show();
updateState(DOWNLOADING);
// I don't really think that create/destroy the thread
// is really necessary.
if (thread) {
thread->deleteLater();
}
@ -172,14 +227,15 @@ void DownloadFromDCWidget::on_ok_clicked()
set_default_dive_computer(data.vendor, data.product);
set_default_dive_computer_device(data.devname);
thread = new InterfaceThread(this, &data);
connect(thread, SIGNAL(updateInterface(int)),
ui->progressBar, SLOT(setValue(int)), Qt::QueuedConnection); // Qt::QueuedConnection == threadsafe.
thread = new DownloadThread(this, &data);
connect(thread, SIGNAL(finished()), this, SLOT(close()));
connect(thread, SIGNAL(finished()),
this, SLOT(onDownloadThreadFinished()), Qt::QueuedConnection);
MainWindow *w = mainWindow();
connect(thread, SIGNAL(finished()), w, SLOT(refreshDisplay()));
thread->start();
downloading = true;
}
bool DownloadFromDCWidget::preferDownloaded()
@ -191,10 +247,21 @@ void DownloadFromDCWidget::reject()
{
// we don't want the download window being able to close
// while we're still downloading.
if (!downloading)
if (currentState != DOWNLOADING && currentState != CANCELLING)
QDialog::reject();
}
void DownloadFromDCWidget::onDownloadThreadFinished()
{
if (currentState == DOWNLOADING) {
if (thread->error.isEmpty())
updateState(DONE);
else
updateState(ERROR);
} else
updateState(CANCELLED);
}
void DownloadFromDCWidget::markChildrenAsDisabled()
{
ui->device->setDisabled(true);
@ -214,37 +281,40 @@ void DownloadFromDCWidget::markChildrenAsEnabled()
ui->forceDownload->setDisabled(false);
ui->preferDownloaded->setDisabled(false);
ui->ok->setDisabled(false);
ui->cancel->setDisabled(false);
ui->search->setDisabled(false);
}
DownloadThread::DownloadThread(device_data_t* data): data(data)
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()
{
DownloadFromDCWidget *dfdcw = DownloadFromDCWidget::instance();
const char *error;
if (!strcmp(data->vendor, "Uemis"))
do_uemis_import(data->devname, data->force_download);
error = do_uemis_import(data->devname, data->force_download);
else
do_libdivecomputer_import(data);
process_dives(TRUE, dfdcw->preferDownloaded());
dfdcw->stoppedDownloading();
}
error = do_libdivecomputer_import(data);
InterfaceThread::InterfaceThread(QObject* parent, device_data_t* data): QThread(parent), data(data)
{
}
void InterfaceThread::run()
{
DownloadThread *download = new DownloadThread(data);
MainWindow *w = mainWindow();
connect(download, SIGNAL(finished()), w, SLOT(refreshDisplay()));
download->start();
while (download->isRunning()) {
msleep(200);
updateInterface(progress_bar_fraction *100);
if (error) {
this->error = str_error(error, data->devname, data->vendor, data->product);
}
updateInterface(100);
// I'm not sure if we should really call process_dives even
// if there's an error or a cancelation
process_dives(TRUE, dfdcw->preferDownloaded());
}

View file

@ -15,20 +15,10 @@ struct device_data_t;
class DownloadThread : public QThread{
Q_OBJECT
public:
explicit DownloadThread(device_data_t* data);
virtual void run();
private:
device_data_t *data;
};
class InterfaceThread : public QThread{
Q_OBJECT
public:
InterfaceThread(QObject *parent, device_data_t *data);
DownloadThread(QObject* parent, device_data_t* data);
virtual void run();
signals:
void updateInterface(int value);
QString error;
private:
device_data_t *data;
};
@ -41,19 +31,30 @@ public:
static DownloadFromDCWidget *instance();
void reject();
enum states {
INITIAL,
DOWNLOADING,
CANCELLING,
CANCELLED,
ERROR,
DONE,
};
public slots:
void on_ok_clicked();
void on_cancel_clicked();
void runDialog();
void stoppedDownloading();
void on_vendor_currentIndexChanged(const QString& vendor);
void onDownloadThreadFinished();
void updateProgressBar();
void runDialog();
private:
void markChildrenAsDisabled();
void markChildrenAsEnabled();
void markChildrenAsDisabled();
void markChildrenAsEnabled();
Ui::DownloadFromDiveComputer *ui;
InterfaceThread *thread;
DownloadThread *thread;
bool downloading;
QStringList vendorList;
@ -65,8 +66,13 @@ private:
QStringListModel *productModel;
void fill_computer_list();
QTimer *timer;
public:
bool preferDownloaded();
void updateState(states state);
states currentState;
};
#endif