| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | #include "diveimportedmodel.h"
 | 
					
						
							| 
									
										
										
										
											2018-06-03 22:15:19 +02:00
										 |  |  | #include "core/qthelper.h"
 | 
					
						
							| 
									
										
										
										
											2019-07-15 23:44:39 +02:00
										 |  |  | #include "core/divelist.h"
 | 
					
						
							| 
									
										
										
										
											2019-11-16 22:24:06 +01:00
										 |  |  | #include "commands/command.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | DiveImportedModel::DiveImportedModel(QObject *o) : QAbstractTableModel(o), | 
					
						
							| 
									
										
										
										
											2020-01-08 21:25:02 -08:00
										 |  |  | 	diveTable(empty_dive_table), | 
					
						
							|  |  |  | 	sitesTable(empty_dive_site_table) | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-25 20:49:13 +02:00
										 |  |  | 	connect(&thread, &QThread::finished, this, &DiveImportedModel::downloadThreadFinished); | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-21 17:53:42 +02:00
										 |  |  | int DiveImportedModel::columnCount(const QModelIndex&) const | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	return 3; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-21 17:53:42 +02:00
										 |  |  | int DiveImportedModel::rowCount(const QModelIndex&) const | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-22 22:07:13 +02:00
										 |  |  | 	return diveTable.nr; | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QVariant DiveImportedModel::headerData(int section, Qt::Orientation orientation, int role) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (orientation == Qt::Vertical) | 
					
						
							|  |  |  | 		return QVariant(); | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// widgets access the model via index.column(), qml via role.
 | 
					
						
							|  |  |  | 	int column = section; | 
					
						
							|  |  |  | 	if (role == DateTime || role == Duration || role == Depth) { | 
					
						
							|  |  |  | 		column = role - DateTime; | 
					
						
							|  |  |  | 		role = Qt::DisplayRole; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 	if (role == Qt::DisplayRole) { | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | 		switch (column) { | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 		case 0: | 
					
						
							|  |  |  | 			return QVariant(tr("Date/time")); | 
					
						
							|  |  |  | 		case 1: | 
					
						
							|  |  |  | 			return QVariant(tr("Duration")); | 
					
						
							|  |  |  | 		case 2: | 
					
						
							|  |  |  | 			return QVariant(tr("Depth")); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return QVariant(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QVariant DiveImportedModel::data(const QModelIndex &index, int role) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!index.isValid()) | 
					
						
							|  |  |  | 		return QVariant(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-22 22:07:13 +02:00
										 |  |  | 	if (index.row() >= diveTable.nr) | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 		return QVariant(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-22 22:03:49 +02:00
										 |  |  | 	struct dive *d = get_dive_from_table(index.row(), &diveTable); | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 	if (!d) | 
					
						
							|  |  |  | 		return QVariant(); | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// widgets access the model via index.column(), qml via role.
 | 
					
						
							|  |  |  | 	int column = index.column(); | 
					
						
							| 
									
										
										
										
											2017-06-04 14:40:25 +02:00
										 |  |  | 	if (role >= DateTime) { | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | 		column = role - DateTime; | 
					
						
							|  |  |  | 		role = Qt::DisplayRole; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 	if (role == Qt::DisplayRole) { | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | 		switch (column) { | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 		case 0: | 
					
						
							|  |  |  | 			return QVariant(get_short_dive_date_string(d->when)); | 
					
						
							|  |  |  | 		case 1: | 
					
						
							| 
									
										
										
										
											2017-06-12 18:08:34 +08:00
										 |  |  | 			return QVariant(get_dive_duration_string(d->duration.seconds, tr("h"), tr("min"))); | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 		case 2: | 
					
						
							|  |  |  | 			return QVariant(get_depth_string(d->maxdepth.mm, true, false)); | 
					
						
							| 
									
										
										
										
											2017-06-04 14:40:25 +02:00
										 |  |  | 		case 3: | 
					
						
							|  |  |  | 			return checkStates[index.row()]; | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (role == Qt::CheckStateRole) { | 
					
						
							|  |  |  | 		if (index.column() == 0) | 
					
						
							|  |  |  | 			return checkStates[index.row()] ? Qt::Checked : Qt::Unchecked; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return QVariant(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DiveImportedModel::changeSelected(QModelIndex clickedIndex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	checkStates[clickedIndex.row()] = !checkStates[clickedIndex.row()]; | 
					
						
							| 
									
										
										
										
											2017-06-04 14:40:25 +02:00
										 |  |  | 	dataChanged(index(clickedIndex.row(), 0), index(clickedIndex.row(), 0), QVector<int>() << Qt::CheckStateRole << Selected); | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DiveImportedModel::selectAll() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-09 19:10:55 +01:00
										 |  |  | 	std::fill(checkStates.begin(), checkStates.end(), true); | 
					
						
							| 
									
										
										
										
											2019-09-22 22:07:13 +02:00
										 |  |  | 	dataChanged(index(0, 0), index(diveTable.nr - 1, 0), QVector<int>() << Qt::CheckStateRole << Selected); | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-29 20:36:00 +02:00
										 |  |  | void DiveImportedModel::selectRow(int row) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	checkStates[row] = !checkStates[row]; | 
					
						
							| 
									
										
										
										
											2017-06-04 14:40:25 +02:00
										 |  |  | 	dataChanged(index(row, 0), index(row, 0), QVector<int>() << Qt::CheckStateRole << Selected); | 
					
						
							| 
									
										
										
										
											2017-05-29 20:36:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | void DiveImportedModel::selectNone() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-09 19:10:55 +01:00
										 |  |  | 	std::fill(checkStates.begin(), checkStates.end(), false); | 
					
						
							| 
									
										
										
										
											2019-09-22 22:07:13 +02:00
										 |  |  | 	dataChanged(index(0, 0), index(diveTable.nr - 1, 0 ), QVector<int>() << Qt::CheckStateRole << Selected); | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Qt::ItemFlags DiveImportedModel::flags(const QModelIndex &index) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (index.column() != 0) | 
					
						
							|  |  |  | 		return QAbstractTableModel::flags(index); | 
					
						
							|  |  |  | 	return QAbstractTableModel::flags(index) | Qt::ItemIsUserCheckable; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DiveImportedModel::clearTable() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-22 22:07:13 +02:00
										 |  |  | 	beginResetModel(); | 
					
						
							|  |  |  | 	clear_dive_table(&diveTable); | 
					
						
							|  |  |  | 	clear_dive_site_table(&sitesTable); | 
					
						
							|  |  |  | 	endResetModel(); | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-25 20:49:13 +02:00
										 |  |  | void DiveImportedModel::downloadThreadFinished() | 
					
						
							| 
									
										
										
										
											2017-04-18 17:32:10 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-09 18:56:51 +01:00
										 |  |  | 	beginResetModel(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-22 21:48:46 +02:00
										 |  |  | 	// Move the table data from thread to model
 | 
					
						
							|  |  |  | 	move_dive_table(&thread.downloadTable, &diveTable); | 
					
						
							|  |  |  | 	move_dive_site_table(&thread.diveSiteTable, &sitesTable); | 
					
						
							| 
									
										
										
										
											2020-10-19 19:19:32 +02:00
										 |  |  | 	deviceTable = std::move(thread.deviceTable); | 
					
						
							| 
									
										
										
										
											2019-09-22 21:48:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	checkStates.resize(diveTable.nr); | 
					
						
							| 
									
										
										
										
											2018-12-09 19:10:55 +01:00
										 |  |  | 	std::fill(checkStates.begin(), checkStates.end(), true); | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-09 18:56:51 +01:00
										 |  |  | 	endResetModel(); | 
					
						
							| 
									
										
										
										
											2019-09-22 21:48:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	emit downloadFinished(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DiveImportedModel::startDownload() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	thread.start(); | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 17:17:17 +01:00
										 |  |  | void DiveImportedModel::waitForDownload() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	thread.wait(); | 
					
						
							| 
									
										
										
										
											2020-11-27 21:32:40 +01:00
										 |  |  | 	downloadThreadFinished(); | 
					
						
							| 
									
										
										
										
											2020-11-23 17:17:17 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 16:07:39 +02:00
										 |  |  | std::tuple<struct dive_table, struct dive_site_table, struct device_table> DiveImportedModel::consumeTables() | 
					
						
							| 
									
										
										
										
											2019-09-22 20:23:37 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	beginResetModel(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Move tables to result
 | 
					
						
							| 
									
										
										
										
											2020-01-08 21:25:02 -08:00
										 |  |  | 	struct dive_table dives = empty_dive_table; | 
					
						
							|  |  |  | 	struct dive_site_table sites = empty_dive_site_table; | 
					
						
							| 
									
										
										
										
											2020-10-17 16:07:39 +02:00
										 |  |  | 	struct device_table devices; | 
					
						
							| 
									
										
										
										
											2019-09-22 21:48:46 +02:00
										 |  |  | 	move_dive_table(&diveTable, &dives); | 
					
						
							|  |  |  | 	move_dive_site_table(&sitesTable, &sites); | 
					
						
							| 
									
										
										
										
											2020-10-17 16:07:39 +02:00
										 |  |  | 	devices = std::move(deviceTable); | 
					
						
							| 
									
										
										
										
											2019-09-22 20:23:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-11 11:30:51 +01:00
										 |  |  | 	// Reset indices
 | 
					
						
							| 
									
										
										
										
											2019-09-22 20:23:37 +02:00
										 |  |  | 	checkStates.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	endResetModel(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-17 16:07:39 +02:00
										 |  |  | 	return std::make_tuple(dives, sites, devices); | 
					
						
							| 
									
										
										
										
											2019-09-22 20:23:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-22 21:00:15 +02:00
										 |  |  | int DiveImportedModel::numDives() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-22 21:48:46 +02:00
										 |  |  | 	return diveTable.nr; | 
					
						
							| 
									
										
										
										
											2019-09-22 21:00:15 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-22 18:50:10 +02:00
										 |  |  | // Delete non-selected dives
 | 
					
						
							|  |  |  | void DiveImportedModel::deleteDeselected() | 
					
						
							| 
									
										
										
										
											2017-05-28 11:48:30 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-22 21:48:46 +02:00
										 |  |  | 	int total = diveTable.nr; | 
					
						
							| 
									
										
										
										
											2018-09-28 10:21:23 +02:00
										 |  |  | 	int j = 0; | 
					
						
							|  |  |  | 	for (int i = 0; i < total; i++) { | 
					
						
							| 
									
										
										
										
											2019-09-22 18:50:10 +02:00
										 |  |  | 		if (checkStates[i]) { | 
					
						
							| 
									
										
										
										
											2018-09-28 10:21:23 +02:00
										 |  |  | 			j++; | 
					
						
							| 
									
										
										
										
											2019-09-22 18:50:10 +02:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			beginRemoveRows(QModelIndex(), j, j); | 
					
						
							| 
									
										
										
										
											2019-09-22 21:48:46 +02:00
										 |  |  | 			delete_dive_from_table(&diveTable, j); | 
					
						
							| 
									
										
										
										
											2019-09-22 18:50:10 +02:00
										 |  |  | 			endRemoveRows(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-05-28 11:48:30 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-22 21:48:46 +02:00
										 |  |  | 	checkStates.resize(diveTable.nr); | 
					
						
							| 
									
										
										
										
											2019-09-22 18:50:10 +02:00
										 |  |  | 	std::fill(checkStates.begin(), checkStates.end(), true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Note: this function is only used from mobile - perhaps move it there or unify.
 | 
					
						
							| 
									
										
										
										
											2019-11-16 22:24:06 +01:00
										 |  |  | void DiveImportedModel::recordDives(int flags) | 
					
						
							| 
									
										
										
										
											2019-09-22 18:50:10 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-16 22:24:06 +01:00
										 |  |  | 	// delete non-selected dives
 | 
					
						
							| 
									
										
										
										
											2019-09-22 22:00:29 +02:00
										 |  |  | 	deleteDeselected(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-16 22:24:06 +01:00
										 |  |  | 	// TODO: use structured bindings once we go C++17
 | 
					
						
							| 
									
										
										
										
											2020-10-17 16:07:39 +02:00
										 |  |  | 	std::tuple<struct dive_table, struct dive_site_table, struct device_table> tables = consumeTables(); | 
					
						
							|  |  |  | 	if (std::get<0>(tables).nr > 0) { | 
					
						
							| 
									
										
										
										
											2019-11-16 22:24:06 +01:00
										 |  |  | 		auto data = thread.data(); | 
					
						
							| 
									
										
										
										
											2020-10-17 16:07:39 +02:00
										 |  |  | 		Command::importDives(&std::get<0>(tables), nullptr, &std::get<1>(tables), | 
					
						
							|  |  |  | 				     &std::get<2>(tables), nullptr, flags, data->devName()); | 
					
						
							| 
									
										
										
										
											2019-11-16 22:24:06 +01:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2020-10-17 16:07:39 +02:00
										 |  |  | 		clear_dive_site_table(&std::get<1>(tables)); | 
					
						
							| 
									
										
										
										
											2019-11-16 22:24:06 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// The dives and dive sites have been consumed, but the arrays of the tables
 | 
					
						
							|  |  |  | 	// still exist. Free them.
 | 
					
						
							| 
									
										
										
										
											2020-10-17 16:07:39 +02:00
										 |  |  | 	free(std::get<0>(tables).dives); | 
					
						
							|  |  |  | 	free(std::get<1>(tables).dive_sites); | 
					
						
							| 
									
										
										
										
											2017-05-28 11:48:30 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | QHash<int, QByteArray> DiveImportedModel::roleNames() const { | 
					
						
							|  |  |  | 	static QHash<int, QByteArray> roles = { | 
					
						
							|  |  |  | 		{ DateTime, "datetime"}, | 
					
						
							|  |  |  | 		{ Depth, "depth"}, | 
					
						
							| 
									
										
										
										
											2017-05-29 20:36:00 +02:00
										 |  |  | 		{ Duration, "duration"}, | 
					
						
							| 
									
										
										
										
											2017-06-04 14:40:25 +02:00
										 |  |  | 		{ Selected, "selected"} | 
					
						
							| 
									
										
										
										
											2017-05-29 20:36:00 +02:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2017-05-26 17:53:25 +02:00
										 |  |  | 	return roles; | 
					
						
							|  |  |  | } |