Subject: [PATCH] [PATCH] Separate downloadfromdivecomputer code to separate
class
This code has been cleaned up.
1) Code from downloadfromdivecomputer.cpp is moved to a new class
downloadmanager.cpp. Encapsulation of diveloadmanager is
maximised. As development proceeds more code will be
moved to downloadmanager.
2) Getter functions (to downloadmanager variables) are used outside
of downloadmanager.
3) Downloadmanager.cpp is placed in the subsurface-core directory.
4) This code focuses purely on the desktop code. Code for the
mobile app needs to be added.
Signed-off-by: Willem Ferguson <[email protected]>
Responses to previous comments in-line below.
Kind regards,
willem
---
On 04/02/2016 19:11, Dirk Hohndel wrote:
On Thu, Feb 04, 2016 at 08:37:57AM +0200, Willem Ferguson wrote:
At the moment, downloadmanager is in the Desktop-widgets. This is
for development purposes only because it is handy to have
downloadfromdivecomputer.cpp close to downloadmanager.cpp
I don't know what that means. "have [it] close to"... you mean in the file
system? That makes no sense to me...
Downloadmanager is now in the subsurface-core directory
diff --git a/desktop-widgets/downloadfromdivecomputer.cpp
b/desktop-widgets/downloadfromdivecomputer.cpp
index 4c8fa6b..78a7714 100644
--- a/desktop-widgets/downloadfromdivecomputer.cpp
+++ b/desktop-widgets/downloadfromdivecomputer.cpp
@@ -76,12 +77,10 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent,
Qt::WindowFlags f) :
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);
+ ui.vendor->setModel(downloadHelper->vendorModel);
Usually the preferred way of doing things like this is to have a "getter"
function instead of exposing the variable as a public. This may seem silly
but there are a number of good reasons to do so (starting with "this
separates the API of your object from the internal implementation" and
"you can handle validation and filtering in that getter function").
So please use DownloadHelper::vendorModel() and turn the vendorModel
member into a private m_vendorModel
This was implemented. Also in the other cases pointed out.
@@ -380,7 +332,7 @@ void DownloadFromDCWidget::pickLogFile()
QFileInfo fi(filename);
filename =
fi.absolutePath().append(QDir::separator()).append("subsurface.log");
logFile = QFileDialog::getSaveFileName(this, tr("Choose file for
divecomputer download logfile"),
- filename, tr("Log files
(*.log)"));
+ filename, tr("Log files
(*.log)"));
Another small whitespace thing. You have this a few times. Continuation
lines should be indented with tab and space to align. This should be set
up correctly in QtCreator if you use the settings in CodingStyle. If this
isn't working correctly for you, please let us know.
I use the subsurface style sheet in Qtcreator. I still see that some
text that I am sure I did not touch
has been moved horizontally, causing differences in whitespace compared
to original. The above is one
of these cases.
diff --git a/desktop-widgets/downloadfromdivecomputer.h
b/desktop-widgets/downloadfromdivecomputer.h
index 7acd49e..15e90f2 100644
--- a/desktop-widgets/downloadfromdivecomputer.h
+++ b/desktop-widgets/downloadfromdivecomputer.h
@@ -10,11 +10,13 @@
#include "libdivecomputer.h"
#include "configuredivecomputerdialog.h"
#include "ui_downloadfromdivecomputer.h"
+#include "downloadmanager.h"
#if defined(BT_SUPPORT)
#include "btdeviceselectiondialog.h"
#endif
+
Adding empty lines like this isn't harmful, but it's usually a sign that
you didn't carefully read the patch before sending. :-)
In general we rarely ever have two consecutive empty lines
Corrected
@@ -96,15 +98,15 @@ private:
DownloadThread *thread;
bool downloading;
- QStringList vendorList;
- QHash<QString, QStringList> productList;
- QMap<QString, dc_descriptor_t *> descriptorLookup;
+// QStringList vendorList;
+// QHash<QString, QStringList> productList;
+// QMap<QString, dc_descriptor_t *> descriptorLookup;
device_data_t data;
int previousLast;
- QStringListModel *vendorModel;
- QStringListModel *productModel;
- void fill_computer_list();
+// QStringListModel *vendorModel;
+// QStringListModel *productModel;
+// void fill_computer_list();
void fill_device_list(int dc_type);
QString logFile;
QString dumpFile;
That's ok while you work on the code, but once you submit it, just remove
those members, don't comment them out.
My glitch. Corrected.
diff --git a/desktop-widgets/downloadmanager.cpp
b/desktop-widgets/downloadmanager.cpp
new file mode 100644
index 0000000..1100014
--- /dev/null
+++ b/desktop-widgets/downloadmanager.cpp
@@ -0,0 +1,89 @@
+#include <QStringListModel>
+#include <QStringList>
+#include <QString>
+#include <QHash>
+#include <QMap>
+#include "downloadmanager.h"
+#include "libdivecomputer.h"
+#include "divecomputer.h"
+#include "display.h"
+
+DownloadManager::DownloadManager(QObject *parent) : QObject(parent) {
+}
That's a function, so opening '{' at the beginning of the new line
+DownloadManager::~DownloadManager() {}
Normally I prefer
DownloadManager::~DownloadManager()
{
}
Implemented everywhere (I hope)
Yes, that wastes vertical space but it's easier to find functions that
way. I know we have code that breaks this... still.
+
+/* ------------------------ Fill_computer_list --------------------------
+1) Fill the QstringList structures containing the vendor names as well as the
+ products of all the supported dive computers.
+2) Set up the hash table that points to the descriptor structure for each
+ dive computer.
+This method is used by both the desktop and the mobile software.
+ ----------------------------------------------------------------------- */
That comment style is very different from anything we use elsewhere in the
code. Not saying it's bad, just that it's inconsistent.
I cannot find a definition of preferred comment style in Subsurface.
Many styles are used currently. The above comes from my days of writing
Pascal (later Delphi) when I enforced strict rules for commenting
at the headings of functions. I would be happy to change it to any specific
format.
+void DownloadManager::fill_computer_list()
+{
+ struct mydescriptor {
+ const char *vendor;
+ const char *product;
+ dc_family_t type;
+ unsigned int model;
+ };
Why is this a private structure inside the function?
It appears diveloadfromdivecomputer is the only class that uses it.
Therefore
why should it have global scope? Also part of my Pascal background. The
structure
now lies at the global level, where it was before.
/D
>From b14b7fb5d85427059648b5c87830261d84cd445f Mon Sep 17 00:00:00 2001
From: Willem Ferguson <[email protected]>
Date: Thu, 11 Feb 2016 13:38:15 +0200
Subject: [PATCH] [PATCH] Separate downloadfromdivecomputer code to separate
class
This code has been cleaned up.
1) Code from downloadfromdivecomputer.cpp is moved to a new class
downloadmanager.cpp. Encapsulation of diveloadmanager is
maximised. As development proceeds more code will be
moved to downloadmanager.
2) Getter functions (to downloadmanager variables) are used outside
of downloadmanager.
3) Downloadmanager.cpp is placed in the subsurface-core directory.
4) This code focuses purely on the desktop code. Code for the
mobile app needs to be added.
Signed-off-by: Willem Ferguson <[email protected]>
---
desktop-widgets/downloadfromdivecomputer.cpp | 79 +++------------
desktop-widgets/downloadfromdivecomputer.h | 9 +-
subsurface-core/CMakeLists.txt | 1 +
subsurface-core/downloadmanager.cpp | 146 +++++++++++++++++++++++++++
subsurface-core/downloadmanager.h | 53 ++++++++++
5 files changed, 218 insertions(+), 70 deletions(-)
create mode 100644 subsurface-core/downloadmanager.cpp
create mode 100644 subsurface-core/downloadmanager.h
diff --git a/desktop-widgets/downloadfromdivecomputer.cpp b/desktop-widgets/downloadfromdivecomputer.cpp
index 4c8fa6b..f5774cd 100644
--- a/desktop-widgets/downloadfromdivecomputer.cpp
+++ b/desktop-widgets/downloadfromdivecomputer.cpp
@@ -5,6 +5,7 @@
#include "display.h"
#include "uemis.h"
#include "models.h"
+#include "subsurface-core/downloadmanager.h"
#include <QTimer>
#include <QFileDialog>
@@ -40,13 +41,12 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) :
thread(0),
downloading(false),
previousLast(0),
- vendorModel(0),
- productModel(0),
timer(new QTimer(this)),
dumpWarningShown(false),
ostcFirmwareCheck(0),
currentState(INITIAL)
{
+ downloadHelper = DownloadManager::instance();
clear_table(&downloadTable);
ui.setupUi(this);
ui.progressBar->hide();
@@ -61,10 +61,9 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) :
ui.downloadedView->setColumnWidth(1, startingWidth * 10);
ui.downloadedView->setColumnWidth(2, startingWidth * 10);
connect(ui.downloadedView, SIGNAL(clicked(QModelIndex)), diveImportedModel, SLOT(changeSelected(QModelIndex)));
-
progress_bar_text = "";
- fill_computer_list();
+ downloadHelper->fill_computer_list();
ui.chooseDumpFile->setEnabled(ui.dumpToFile->isChecked());
connect(ui.chooseDumpFile, SIGNAL(clicked()), this, SLOT(pickDumpFile()));
@@ -76,12 +75,10 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) :
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);
+ ui.vendor->setModel(downloadHelper->VendorModel());
if (default_dive_computer_vendor) {
ui.vendor->setCurrentIndex(ui.vendor->findText(default_dive_computer_vendor));
- productModel = new QStringListModel(productList[default_dive_computer_vendor]);
- ui.product->setModel(productModel);
+ ui.product->setModel(downloadHelper->ProductModel());
if (default_dive_computer_product)
ui.product->setCurrentIndex(ui.product->findText(default_dive_computer_product));
}
@@ -199,8 +196,9 @@ void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString &vendor)
if (!currentModel)
return;
- productModel = new QStringListModel(productList[vendor]);
- ui.product->setModel(productModel);
+ downloadHelper->onVendorChangedSlot(vendor);
+ ui.product->setModel(downloadHelper->ProductModel());
+ ui.product->setCurrentIndex(0);
if (vendor == QString("Uemis"))
dcType = DC_TYPE_UEMIS;
@@ -214,7 +212,7 @@ void DownloadFromDCWidget::on_product_currentIndexChanged(const QString &product
{
// Set up the DC descriptor
dc_descriptor_t *descriptor = NULL;
- descriptor = descriptorLookup[ui.vendor->currentText() + product];
+ descriptor = downloadHelper->getDescriptor(ui.vendor->currentText(),product);
// call dc_descriptor_get_transport to see if the dc_transport_t is DC_TRANSPORT_SERIAL
if (dc_descriptor_get_transport(descriptor) == DC_TRANSPORT_SERIAL) {
@@ -226,60 +224,13 @@ void DownloadFromDCWidget::on_product_currentIndexChanged(const QString &product
}
}
-void DownloadFromDCWidget::fill_computer_list()
-{
- dc_iterator_t *iterator = NULL;
- dc_descriptor_t *descriptor = NULL;
- struct mydescriptor *mydescriptor;
-
- QStringList computer;
- dc_descriptor_iterator(&iterator);
- while (dc_iterator_next(iterator, &descriptor) == DC_STATUS_SUCCESS) {
- const char *vendor = dc_descriptor_get_vendor(descriptor);
- const char *product = dc_descriptor_get_product(descriptor);
-
- if (!vendorList.contains(vendor))
- vendorList.append(vendor);
-
- if (!productList[vendor].contains(product))
- productList[vendor].push_back(product);
-
- descriptorLookup[QString(vendor) + QString(product)] = descriptor;
- }
- dc_iterator_free(iterator);
- Q_FOREACH (QString vendor, vendorList)
- qSort(productList[vendor]);
-
- /* and add the Uemis Zurich which we are handling internally
- THIS IS A HACK as we magically have a data structure here that
- happens to match a data structure that is internal to libdivecomputer;
- this WILL BREAK if libdivecomputer changes the dc_descriptor struct...
- eventually the UEMIS code needs to move into libdivecomputer, I guess */
-
- mydescriptor = (struct mydescriptor *)malloc(sizeof(struct mydescriptor));
- mydescriptor->vendor = "Uemis";
- mydescriptor->product = "Zurich";
- mydescriptor->type = DC_FAMILY_NULL;
- mydescriptor->model = 0;
-
- if (!vendorList.contains("Uemis"))
- vendorList.append("Uemis");
-
- if (!productList["Uemis"].contains("Zurich"))
- productList["Uemis"].push_back("Zurich");
-
- descriptorLookup["UemisZurich"] = (dc_descriptor_t *)mydescriptor;
-
- qSort(vendorList);
-}
-
void DownloadFromDCWidget::on_search_clicked()
{
if (ui.vendor->currentText() == "Uemis") {
QString dirName = QFileDialog::getExistingDirectory(this,
- tr("Find Uemis dive computer"),
- QDir::homePath(),
- QFileDialog::ShowDirsOnly);
+ tr("Find Uemis dive computer"),
+ QDir::homePath(),
+ QFileDialog::ShowDirsOnly);
if (ui.device->findText(dirName) == -1)
ui.device->addItem(dirName);
ui.device->setEditText(dirName);
@@ -332,7 +283,7 @@ void DownloadFromDCWidget::on_downloadCancelRetryButton_clicked()
} else {
data.devname = strdup(ui.device->currentText().toUtf8().data());
}
- data.descriptor = descriptorLookup[ui.vendor->currentText() + ui.product->currentText()];
+ data.descriptor = downloadHelper->getDescriptor(ui.vendor->currentText(),ui.product->currentText());
data.force_download = ui.forceDownload->isChecked();
data.create_new_trip = ui.createNewTrip->isChecked();
data.trip = NULL;
@@ -380,7 +331,7 @@ void DownloadFromDCWidget::pickLogFile()
QFileInfo fi(filename);
filename = fi.absolutePath().append(QDir::separator()).append("subsurface.log");
logFile = QFileDialog::getSaveFileName(this, tr("Choose file for divecomputer download logfile"),
- filename, tr("Log files (*.log)"));
+ filename, tr("Log files (*.log)"));
if (!logFile.isEmpty()) {
free(logfile_name);
logfile_name = strdup(logFile.toUtf8().data());
@@ -396,7 +347,7 @@ void DownloadFromDCWidget::checkDumpFile(int state)
pickDumpFile();
if (!dumpWarningShown) {
QMessageBox::warning(this, tr("Warning"),
- tr("Saving the libdivecomputer dump will NOT download dives to the dive list."));
+ tr("Saving the libdivecomputer dump will NOT download dives to the dive list."));
dumpWarningShown = true;
}
}
diff --git a/desktop-widgets/downloadfromdivecomputer.h b/desktop-widgets/downloadfromdivecomputer.h
index 7acd49e..e122c73 100644
--- a/desktop-widgets/downloadfromdivecomputer.h
+++ b/desktop-widgets/downloadfromdivecomputer.h
@@ -10,6 +10,7 @@
#include "libdivecomputer.h"
#include "configuredivecomputerdialog.h"
#include "ui_downloadfromdivecomputer.h"
+#include "subsurface-core/downloadmanager.h"
#if defined(BT_SUPPORT)
#include "btdeviceselectiondialog.h"
@@ -96,15 +97,9 @@ private:
DownloadThread *thread;
bool downloading;
- QStringList vendorList;
- QHash<QString, QStringList> productList;
- QMap<QString, dc_descriptor_t *> descriptorLookup;
device_data_t data;
int previousLast;
- QStringListModel *vendorModel;
- QStringListModel *productModel;
- void fill_computer_list();
void fill_device_list(int dc_type);
QString logFile;
QString dumpFile;
@@ -112,6 +107,8 @@ private:
bool dumpWarningShown;
OstcFirmwareCheck *ostcFirmwareCheck;
DiveImportedModel *diveImportedModel;
+ DownloadManager *downloadHelper;
+
#if defined(BT_SUPPORT)
BtDeviceSelectionDialog *btDeviceSelectionDialog;
#endif
diff --git a/subsurface-core/CMakeLists.txt b/subsurface-core/CMakeLists.txt
index 703864a..0f29e97 100644
--- a/subsurface-core/CMakeLists.txt
+++ b/subsurface-core/CMakeLists.txt
@@ -82,6 +82,7 @@ set(SUBSURFACE_CORE_LIB_SRCS
isocialnetworkintegration.cpp
gpslocation.cpp
cloudstorage.cpp
+ downloadmanager.cpp
#Subsurface Qt have the Subsurface structs QObjectified for easy access via QML.
subsurface-qt/DiveObjectHelper.cpp
diff --git a/subsurface-core/downloadmanager.cpp b/subsurface-core/downloadmanager.cpp
new file mode 100644
index 0000000..17fe30c
--- /dev/null
+++ b/subsurface-core/downloadmanager.cpp
@@ -0,0 +1,146 @@
+#include <QStringListModel>
+#include <QStringList>
+#include <QString>
+#include <QHash>
+#include <QMap>
+#include "downloadmanager.h"
+#include "libdivecomputer.h"
+#include "divecomputer.h"
+#include "display.h"
+
+struct mydescriptor {
+ const char *vendor;
+ const char *product;
+ dc_family_t type;
+ unsigned int model;
+};
+
+DownloadManager *DownloadManager::m_instance = NULL;
+
+DownloadManager::DownloadManager()
+{
+ m_instance = this;
+}
+
+DownloadManager::~DownloadManager()
+{
+ m_instance = NULL;
+}
+
+DownloadManager *DownloadManager::instance()
+{
+ if(!m_instance)
+ m_instance = new DownloadManager();
+ return m_instance;
+}
+
+/* ------------------------ fill_computer_list --------------------------
+ 1) Fill the QstringList structures containing the vendor names as well as the
+ products of all the supported dive computers.
+ 2) Set up the hash table that points to the descriptor structure for each
+ dive computer.
+ This method is used by both the desktop and the mobile software. */
+void DownloadManager::fill_computer_list()
+{
+ struct mydescriptor *mydescriptor;
+
+ dc_iterator_t *iterator = NULL;
+ dc_descriptor_t *descriptor = NULL;
+
+ dc_descriptor_iterator(&iterator);
+ while (dc_iterator_next(iterator, &descriptor) == DC_STATUS_SUCCESS) {
+ const char *vendor = dc_descriptor_get_vendor(descriptor);
+ const char *product = dc_descriptor_get_product(descriptor);
+
+ if (!vendorList.contains(vendor))
+ vendorList.append(vendor);
+
+ if (!productList[vendor].contains(product))
+ productList[vendor].push_back(product);
+
+ descriptorLookup[QString(vendor) + QString(product)] = descriptor;
+ }
+ dc_iterator_free(iterator);
+ Q_FOREACH (QString vendor, vendorList)
+ qSort(productList[vendor]);
+
+ /* and add the Uemis Zurich which we are handling internally
+ THIS IS A HACK as we magically have a data structure here that
+ happens to match a data structure that is internal to libdivecomputer;
+ this WILL BREAK if libdivecomputer changes the dc_descriptor struct...
+ eventually the UEMIS code needs to move into libdivecomputer, I guess */
+
+ mydescriptor = (struct mydescriptor *)malloc(sizeof(struct mydescriptor));
+ mydescriptor->vendor = "Uemis";
+ mydescriptor->product = "Zurich";
+ mydescriptor->type = DC_FAMILY_NULL;
+ mydescriptor->model = 0;
+
+ if (!vendorList.contains("Uemis"))
+ vendorList.append("Uemis");
+
+ if (!productList["Uemis"].contains("Zurich"))
+ productList["Uemis"].push_back("Zurich");
+
+ descriptorLookup["UemisZurich"] = (dc_descriptor_t *)mydescriptor;
+
+ qSort(vendorList);
+
+ vendorModel=new QStringListModel(vendorList);
+ m_vendorModel = vendorModel;
+
+ if (default_dive_computer_vendor) {
+ productModel=new QStringListModel(productList[default_dive_computer_vendor]);
+ m_productModel = productModel;
+ } else {
+ productModel=new QStringListModel(productList[vendorModel->stringList().at(0)]);
+ m_productModel = productModel;
+ }
+
+}
+
+/* These following methods follow from these properties defined in the header downloadmanager.h:
+Q_PROPERTY(QStringListModel *productModel READ productModel WRITE setProductModel)
+Q_PROPERTY(QStringListModel *vendorModel READ vendorModel WRITE setVendorModel NOTIFY vendorChanged) */
+
+void DownloadManager::setProductModel(QStringListModel *ProductModel)
+{ // This method triggers QML UI update
+ m_productModel = ProductModel;
+}
+
+void DownloadManager::onVendorChangedSlot(const QString vendorText) // Load productModel with product mame
+{ // stringlist determined by vendorText. This method
+ productModel->setStringList(productList[vendorText]); // is called by the mobile and the desktop versions
+ setProductModel(productModel); //.when the product combobox needs appropriate update.
+}
+
+void DownloadManager::setVendorModel(QStringListModel *VendorModel)
+{
+ VendorModel->setStringList(this->vendorList); // This method uses vendorList
+ m_vendorModel = VendorModel; // as an external data source.
+}
+
+QStringListModel *DownloadManager::VendorModel()
+{
+ return(m_vendorModel);
+}
+
+QStringListModel *DownloadManager::ProductModel()
+{
+ return(m_productModel);
+}
+
+dc_descriptor_t *DownloadManager::getDescriptor(QString vendorName, QString productName)
+{
+ m_descriptor = descriptorLookup[vendorName + productName];
+ return m_descriptor;
+}
+
+void DownloadManager::printList(QStringList M) // Print a QStringList M
+{
+ for (int i = 0; i < M.size(); ++i) {
+ QByteArray ba = M.at(i).toLatin1();
+ printf("(%d) %s\n",i,ba.data());
+ }
+}
+
diff --git a/subsurface-core/downloadmanager.h b/subsurface-core/downloadmanager.h
new file mode 100644
index 0000000..32ef10a
--- /dev/null
+++ b/subsurface-core/downloadmanager.h
@@ -0,0 +1,53 @@
+#ifndef DOWNLOADMANAGER_H
+#define DOWNLOADMANAGER_H
+
+#include <QStringList>
+#include <QStringListModel>
+#include <QAbstractListModel>
+#include <QString>
+#include <QHash>
+#include <QMap>
+#include <QDebug>
+#include "libdivecomputer.h"
+
+// ================================ DownloadManager =============================================================
+class DownloadManager : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QStringListModel *productModel READ ProductModel WRITE setProductModel)
+ Q_PROPERTY(QStringListModel *vendorModel READ VendorModel WRITE setVendorModel NOTIFY vendorModelChanged)
+ Q_PROPERTY(DownloadManager *DownloadManager READ instance)
+public:
+ static DownloadManager *instance();
+ void fill_computer_list();
+ void setProductModel(QStringListModel *ProductModel);
+ void setVendorModel(QStringListModel *VendorModel);
+ void newProductModel(QString vendorName);
+ dc_descriptor_t *getDescriptor(QString vendorName, QString productName);
+ QStringListModel *ProductModel();
+ QStringListModel *VendorModel();
+
+private:
+ DownloadManager();
+ ~DownloadManager();
+ static DownloadManager *m_instance;
+ QStringListModel *m_vendorModel;
+ QStringListModel *m_productModel;
+ dc_descriptor_t *m_descriptor;
+ QStringListModel *vendorModel;
+ QStringListModel *productModel;
+ QMap<QString, dc_descriptor_t *> descriptorLookup;
+ QString vendorName;
+ QStringList vendorList;
+ QHash<QString, QStringList> productList;
+ void printList(QStringList M);
+
+signals:
+ void vendorModelChanged();
+
+public slots:
+ void onVendorChangedSlot(const QString vendorText);
+
+};
+
+#endif // DOWNLOADMANAGER_H
--
2.5.0
_______________________________________________
subsurface mailing list
[email protected]
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface