diff options
author | Tomaz Canabrava <tcanabrava@kde.org> | 2013-05-20 16:43:33 -0300 |
---|---|---|
committer | Tomaz Canabrava <tcanabrava@kde.org> | 2013-05-20 16:43:33 -0300 |
commit | c7a5d0490fa5f4e8579e6a8e0fbdc7baf7c34145 (patch) | |
tree | 615ec1dbf0887d0e1ffeecf4ed7b1600ca0c0d6a | |
parent | 15bb4fccbb14c0e69637ca5920a1e68071700b8e (diff) | |
download | subsurface-c7a5d0490fa5f4e8579e6a8e0fbdc7baf7c34145.tar.gz |
Skeleton code for a non-blocking UI thread for downloading dives from the DC
This is the skeleton code for a non-blocking ui-thread
It already creates the first-thread ( 'do not block the ui' )
and the second thread ('download from the dive computer')
We can in the future merge both in the same place - I didn't
want to do that now because the download function is written
in the libdivecomputer.c code, and I cant just transform that
to a QThread and use signals, so I used two threads for that.
Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | download-dialog.c | 12 | ||||
-rw-r--r-- | libdivecomputer.c | 75 | ||||
-rw-r--r-- | libdivecomputer.h | 15 | ||||
-rw-r--r-- | qt-ui/downloadfromdivecomputer.cpp | 73 | ||||
-rw-r--r-- | qt-ui/downloadfromdivecomputer.h | 46 | ||||
-rw-r--r-- | qt-ui/downloadfromdivecomputer.ui | 110 | ||||
-rw-r--r-- | qt-ui/mainwindow.cpp | 4 |
8 files changed, 249 insertions, 89 deletions
@@ -45,6 +45,7 @@ HEADERS = \ qt-ui/profilegraphics.h \ qt-ui/globe.h \ qt-ui/kmessagewidget.h \ + qt-ui/downloadfromdivecomputer.h \ SOURCES = \ @@ -64,6 +65,7 @@ SOURCES = \ sha1.c \ statistics.c \ time.c \ + libdivecomputer.c \ qt-gui.cpp \ qt-ui/addcylinderdialog.cpp \ qt-ui/addweightsystemdialog.cpp \ @@ -77,6 +79,7 @@ SOURCES = \ qt-ui/profilegraphics.cpp \ qt-ui/globe.cpp \ qt-ui/kmessagewidget.cpp \ + qt-ui/downloadfromdivecomputer.cpp \ $(RESFILE) diff --git a/download-dialog.c b/download-dialog.c index 8f6220e31..bbd499aaf 100644 --- a/download-dialog.c +++ b/download-dialog.c @@ -3,24 +3,12 @@ #include "dive.h" #include "divelist.h" #include "display.h" -#if USE_GTK_UI -#include "display-gtk.h" -#include "callbacks-gtk.h" -#endif #include "libdivecomputer.h" const char *default_dive_computer_vendor; const char *default_dive_computer_product; const char *default_dive_computer_device; -#if USE_GTK_UI -static gboolean force_download; -static gboolean prefer_downloaded; - -OPTIONCALLBACK(force_toggle, force_download) -OPTIONCALLBACK(prefer_dl_toggle, prefer_downloaded) -#endif - struct product { const char *product; dc_descriptor_t *descriptor; diff --git a/libdivecomputer.c b/libdivecomputer.c index cc1c0be28..ecc90accc 100644 --- a/libdivecomputer.c +++ b/libdivecomputer.c @@ -1,5 +1,4 @@ #include <stdio.h> -#include <pthread.h> #include <unistd.h> #include <inttypes.h> #include <glib/gi18n.h> @@ -21,8 +20,9 @@ #define NOT_FROG #endif -static const char *progress_bar_text = ""; -static double progress_bar_fraction = 0.0; +const char *progress_bar_text = ""; +double progress_bar_fraction = 0.0; + static int stoptime, stopdepth, ndl, po2, cns; static gboolean in_deco, first_temp_is_air; @@ -686,7 +686,7 @@ static const char *do_device_import(device_data_t *data) return NULL; } -static const char *do_libdivecomputer_import(device_data_t *data) +const char *do_libdivecomputer_import(device_data_t *data) { dc_status_t rc; const char *err; @@ -709,70 +709,3 @@ static const char *do_libdivecomputer_import(device_data_t *data) dc_context_free(data->context); return err; } - -#if USE_GTK_UI -static void *pthread_wrapper(void *_data) -{ - device_data_t *data = _data; - const char *err_string = do_libdivecomputer_import(data); - import_thread_done = 1; - return (void *)err_string; -} - -/* this simply ends the dialog without a response and asks not to be fired again - * as we set this function up in every loop while uemis_download is waiting for - * the download to finish */ -static gboolean timeout_func(gpointer _data) -{ - GtkDialog *dialog = _data; - if (!import_thread_cancelled) - gtk_dialog_response(dialog, GTK_RESPONSE_NONE); - return FALSE; -} - -GError *do_import(device_data_t *data) -{ - pthread_t pthread; - void *retval; - GtkDialog *dialog = data->dialog; - - /* I'm sure there is some better interface for waiting on a thread in a UI main loop */ - import_thread_done = 0; - progress_bar_text = ""; - progress_bar_fraction = 0.0; - pthread_create(&pthread, NULL, pthread_wrapper, data); - /* loop here until the import is done or was cancelled by the user; - * in order to get control back from gtk we register a timeout function - * that ends the dialog with no response every 100ms; we then update the - * progressbar and setup the timeout again - unless of course the user - * pressed cancel, in which case we just wait for the download thread - * to react to that and exit */ - while (!import_thread_done) { - if (!import_thread_cancelled) { - int result; - g_timeout_add(100, timeout_func, dialog); - update_progressbar(&data->progress, progress_bar_fraction); - update_progressbar_text(&data->progress, progress_bar_text); - result = gtk_dialog_run(dialog); - switch (result) { - case GTK_RESPONSE_CANCEL: - import_thread_cancelled = TRUE; - progress_bar_text = _("Cancelled..."); - break; - default: - /* nothing */ - break; - } - } else { - update_progressbar(&data->progress, progress_bar_fraction); - update_progressbar_text(&data->progress, progress_bar_text); - usleep(100000); - } - } - if (pthread_join(pthread, &retval) < 0) - retval = _("Odd pthread error return"); - if (retval) - return error(retval, data->vendor, data->product, data->devname); - return NULL; -} -#endif diff --git a/libdivecomputer.h b/libdivecomputer.h index 639a69c73..996037c8c 100644 --- a/libdivecomputer.h +++ b/libdivecomputer.h @@ -1,6 +1,11 @@ #ifndef LIBDIVECOMPUTER_H #define LIBDIVECOMPUTER_H + +#ifdef __cplusplus +extern "C" { +#endif + /* libdivecomputer */ #include <libdivecomputer/version.h> #include <libdivecomputer/device.h> @@ -20,12 +25,12 @@ typedef struct device_data_t { dc_context_t *context; int preexisting; gboolean force_download; -#if USE_GTK_UI - progressbar_t progress; - GtkDialog *dialog; -#endif } device_data_t; -extern GError *do_import(device_data_t *data); +const char *do_libdivecomputer_import(device_data_t *data); +#ifdef __cplusplus +} #endif + +#endif
\ No newline at end of file diff --git a/qt-ui/downloadfromdivecomputer.cpp b/qt-ui/downloadfromdivecomputer.cpp new file mode 100644 index 000000000..8be4e6cbb --- /dev/null +++ b/qt-ui/downloadfromdivecomputer.cpp @@ -0,0 +1,73 @@ +#include "downloadfromdivecomputer.h" +#include "ui_downloadfromdivecomputer.h" + +#include "../libdivecomputer.h" + +#include <QThread> +#include <QDebug> + +namespace DownloadFromDcGlobal{ + const char *err_string; +}; + +extern const char *progress_bar_text; +extern double progress_bar_fraction; + +DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) : + QDialog(parent, f), ui(new Ui::DownloadFromDiveComputer), thread(0) +{ + ui->setupUi(this); + ui->progressBar->hide(); + ui->progressBar->setMinimum(0); + ui->progressBar->setMaximum(100); +} + +void DownloadFromDCWidget::on_cancel_clicked() +{ + close(); +} + +void DownloadFromDCWidget::on_ok_clicked() +{ + + ui->progressBar->setValue(0); + ui->progressBar->show(); + + if(thread){ + thread->deleteLater(); + } + + device_data_t data; + // still need to fill the data info here. + thread = new InterfaceThread(this, &data); + connect(thread, SIGNAL(updateInterface(int)), ui->progressBar, SLOT(setValue(int)), Qt::QueuedConnection); // Qt::QueuedConnection == threadsafe. + connect(thread, SIGNAL(updateInterface(int)), this, SLOT(setValue(int)), Qt::QueuedConnection); // Qt::QueuedConnection == threadsafe. + thread->start(); +} + +DownloadThread::DownloadThread(device_data_t* data): data(data) +{ +} + +void DownloadThread::run() +{ + do_libdivecomputer_import(data); + qDebug() << "Download thread started"; +} + +InterfaceThread::InterfaceThread(QObject* parent, device_data_t* data): QThread(parent), data(data) +{ + +} + +void InterfaceThread::run() +{ + DownloadThread *download = new DownloadThread(data); + + download->start(); + while(download->isRunning()){ + msleep(200); + updateInterface(progress_bar_fraction *100); + } + updateInterface(100); +} diff --git a/qt-ui/downloadfromdivecomputer.h b/qt-ui/downloadfromdivecomputer.h new file mode 100644 index 000000000..433d43779 --- /dev/null +++ b/qt-ui/downloadfromdivecomputer.h @@ -0,0 +1,46 @@ +#ifndef DOWNLOADFROMDIVECOMPUTER_H +#define DOWNLOADFROMDIVECOMPUTER_H +#include <QDialog> +#include <QThread> + +namespace Ui{ + class DownloadFromDiveComputer; +} +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) ; + virtual void run(); + +Q_SIGNALS: + void updateInterface(int value); +private: + device_data_t *data; +}; + +class DownloadFromDCWidget : public QDialog{ + Q_OBJECT +public: + explicit DownloadFromDCWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); + +public slots: + void on_ok_clicked(); + void on_cancel_clicked(); +private: + Ui::DownloadFromDiveComputer *ui; + InterfaceThread *thread; +}; + + +#endif
\ No newline at end of file diff --git a/qt-ui/downloadfromdivecomputer.ui b/qt-ui/downloadfromdivecomputer.ui new file mode 100644 index 000000000..924b886aa --- /dev/null +++ b/qt-ui/downloadfromdivecomputer.ui @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DownloadFromDiveComputer</class> + <widget class="QDialog" name="DownloadFromDiveComputer"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>331</width> + <height>199</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Vendor</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Dive Computer</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QComboBox" name="vendor"/> + </item> + <item row="1" column="1" colspan="2"> + <widget class="QComboBox" name="diveComputerName"/> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Device or Mount Point</string> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2"> + <widget class="QLineEdit" name="mountPoint"/> + </item> + <item row="3" column="2"> + <widget class="QToolButton" name="search"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + <item row="4" column="0" colspan="3"> + <widget class="QCheckBox" name="forceDownload"> + <property name="text"> + <string>Force download of all dives</string> + </property> + </widget> + </item> + <item row="5" column="0" colspan="3"> + <widget class="QCheckBox" name="preferDownloaded"> + <property name="text"> + <string>Always prefer downloaded dives</string> + </property> + </widget> + </item> + <item row="6" column="0" colspan="3"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="ok"> + <property name="text"> + <string>OK</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancel"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="7" column="0" colspan="3"> + <widget class="QProgressBar" name="progressBar"> + <property name="value"> + <number>24</number> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index d7320ceeb..30629ce95 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -25,6 +25,7 @@ #include "../pref.h" #include "modeldelegates.h" #include "models.h" +#include "downloadfromdivecomputer.h" static MainWindow* instance = 0; @@ -160,7 +161,8 @@ void MainWindow::on_actionQuit_triggered() void MainWindow::on_actionDownloadDC_triggered() { - qDebug("actionDownloadDC"); + DownloadFromDCWidget* downloadWidget = new DownloadFromDCWidget(); + downloadWidget->show(); } void MainWindow::on_actionDownloadWeb_triggered() |