DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) :
    QDialog(parent, f), thread(0), timer(new QTimer(this)),
	currentState(INITIAL)
{
	ui.setupUi(this);
	ui.progressBar->hide();
	ui.progressBar->setMinimum(0);
	ui.progressBar->setMaximum(100);

	fill_device_list();
	fill_computer_list();

	vendorModel = new QStringListModel(vendorList);
	ui.vendor->setModel(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);
		if (default_dive_computer_product)
			ui.product->setCurrentIndex(ui.product->findText(default_dive_computer_product));
	}
	if (default_dive_computer_device)
		ui.device->setEditText(default_dive_computer_device);

	timer->setInterval(200);
	connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
	updateState(INITIAL);
}
void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString &vendor)
{
	unsigned int transport;
	dc_descriptor_t *descriptor;
	productModel.setStringList(productList[vendor]);
	ui.product->setCurrentIndex(0);

	descriptor = descriptorLookup.value(ui.vendor->currentText() + ui.product->currentText());
	transport = dc_descriptor_get_transports(descriptor);
	fill_device_list(transport);
}
void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString &vendor)
{
	int dcType = DC_TYPE_SERIAL;
	QAbstractItemModel *currentModel = ui.product->model();
	if (!currentModel)
		return;

	productModel = new QStringListModel(productList[vendor]);
	ui.product->setModel(productModel);

	if (vendor == QString("Uemis"))
		dcType = DC_TYPE_UEMIS;
	fill_device_list(dcType);

	// Memleak - but deleting gives me a crash.
	//currentModel->deleteLater();
}
DownloadFromDCWidget::DownloadFromDCWidget(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f),
	thread(0),
	downloading(false),
	previousLast(0),
	vendorModel(0),
	productModel(0),
	timer(new QTimer(this)),
	dumpWarningShown(false),
	currentState(INITIAL)
{
	ui.setupUi(this);
	ui.progressBar->hide();
	ui.progressBar->setMinimum(0);
	ui.progressBar->setMaximum(100);

	progress_bar_text = "";

	fill_device_list();
	fill_computer_list();

	ui.chooseDumpFile->setEnabled(ui.dumpToFile->isChecked());
	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)));
	vendorModel = new QStringListModel(vendorList);
	ui.vendor->setModel(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);
		if (default_dive_computer_product)
			ui.product->setCurrentIndex(ui.product->findText(default_dive_computer_product));
	}
	connect(ui.product, SIGNAL(currentIndexChanged(int)), this, SLOT(on_product_currentIndexChanged()), Qt::UniqueConnection);
	if (default_dive_computer_device)
		ui.device->setEditText(default_dive_computer_device);

	timer->setInterval(200);
	connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
	updateState(INITIAL);
	memset(&data, 0, sizeof(data));
}
void DownloadFromDCWidget::updateState(states state)
{
	if (state == currentState)
		return;

	if (state == INITIAL) {
		fill_device_list(DC_TYPE_OTHER);
		ui.progressBar->hide();
		markChildrenAsEnabled();
		timer->stop();
	}

	// tries to cancel an on going download
	else if (currentState == DOWNLOADING && state == CANCELLING) {
		import_thread_cancelled = true;
		ui.downloadCancelRetryButton->setEnabled(false);
	}

	// user pressed cancel but the application isn't doing anything.
	// means close the window
	else if ((currentState == INITIAL || currentState == DONE || currentState == ERROR) && state == CANCELLING) {
		timer->stop();
		reject();
	}

	// the cancelation process is finished
	else if (currentState == CANCELLING && state == DONE) {
		timer->stop();
		ui.progressBar->setValue(0);
		ui.progressBar->hide();
		markChildrenAsEnabled();
	}

	// DOWNLOAD is finally done, but we don't know if there was an error as libdivecomputer doesn't pass
	// that information on to us.
	// If we find an error, offer to retry, otherwise continue the interaction to pick the dives the user wants
	else if (currentState == DOWNLOADING && state == DONE) {
		timer->stop();
		if (QString(progress_bar_text).contains("error", Qt::CaseInsensitive)) {
			updateProgressBar();
			markChildrenAsEnabled();
			progress_bar_text = "";
		} else {
			ui.progressBar->setValue(100);
			markChildrenAsEnabled();
		}
	}

	// DOWNLOAD is started.
	else if (state == DOWNLOADING) {
		timer->start();
		ui.progressBar->setValue(0);
		updateProgressBar();
		ui.progressBar->show();
		markChildrenAsDisabled();
	}

	// got an error
	else if (state == ERROR) {
		QMessageBox::critical(this, TITLE_OR_TEXT(tr("Error"), this->thread->error), QMessageBox::Ok);

		markChildrenAsEnabled();
		ui.progressBar->hide();
	}

	// properly updating the widget state
	currentState = state;
}
void DownloadFromDCWidget::updateState(states state)
{
	if (state == currentState)
		return;

	if (state == INITIAL) {
		fill_device_list();
		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();
		ui.ok->setText(tr("OK"));
	}

	// 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, but we don't know if there was an error as libdivecomputer doesn't pass
	// that information on to us
	// so check the progressBar text and if no error was reported, close the dialog and go back to the main window
	// otherwise treat this as if the download was cancelled
	else if (currentState == DOWNLOADING && state == DONE) {
		timer->stop();
		if (QString(progress_bar_text).contains("error", Qt::CaseInsensitive)) {
			updateProgressBar();
			markChildrenAsEnabled();
			progress_bar_text = "";
			ui.ok->setText(tr("Retry"));
		} else {
			ui.progressBar->setValue(100);
			markChildrenAsEnabled();
			ui.ok->setText(tr("OK"));
			accept();
		}
	}

	// DOWNLOAD is started.
	else if (state == DOWNLOADING) {
		timer->start();
		ui.progressBar->setValue(0);
		updateProgressBar();
		ui.progressBar->show();
		markChildrenAsDisabled();
	}

	// got an error
	else if (state == ERROR) {
		QMessageBox::critical(this, TITLE_OR_TEXT(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::updateState(states state)
{
	if (state == currentState)
		return;

	if (state == INITIAL) {
		fill_device_list();
		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;
}