| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | // SPDX-License-Identifier: GPL-2.0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "command_divesite.h"
 | 
					
						
							|  |  |  | #include "core/divesite.h"
 | 
					
						
							| 
									
										
										
										
											2020-02-03 19:33:06 +01:00
										 |  |  | #include "core/subsurface-qt/divelistnotifier.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-12 23:51:39 +01:00
										 |  |  | #include "core/qthelper.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-14 08:26:50 +01:00
										 |  |  | #include "core/subsurface-string.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-12 23:51:39 +01:00
										 |  |  | #include "qt-models/divelocationmodel.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-22 20:55:05 +01:00
										 |  |  | #include "qt-models/filtermodels.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Command { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Helper functions to add / remove a set of dive sites
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Add a set of dive sites to the core. The dives that were associated with
 | 
					
						
							|  |  |  | // that dive site will be restored to that dive site.
 | 
					
						
							|  |  |  | static std::vector<dive_site *> addDiveSites(std::vector<OwningDiveSitePtr> &sites) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::vector<dive_site *> res; | 
					
						
							| 
									
										
										
										
											2019-06-23 09:22:26 +02:00
										 |  |  | 	QVector<dive *> changedDives; | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | 	res.reserve(sites.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (OwningDiveSitePtr &ds: sites) { | 
					
						
							|  |  |  | 		// Readd the dives that belonged to this site
 | 
					
						
							|  |  |  | 		for (int i = 0; i < ds->dives.nr; ++i) { | 
					
						
							|  |  |  | 			// TODO: send dive site changed signal
 | 
					
						
							| 
									
										
										
										
											2019-03-22 20:55:05 +01:00
										 |  |  | 			struct dive *d = ds->dives.dives[i]; | 
					
						
							|  |  |  | 			d->dive_site = ds.get(); | 
					
						
							|  |  |  | 			changedDives.push_back(d); | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Add dive site to core, but remember a non-owning pointer first.
 | 
					
						
							|  |  |  | 		res.push_back(ds.get()); | 
					
						
							|  |  |  | 		int idx = register_dive_site(ds.release()); // Return ownership to backend.
 | 
					
						
							|  |  |  | 		emit diveListNotifier.diveSiteAdded(res.back(), idx); // Inform frontend of new dive site.
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-23 09:22:26 +02:00
										 |  |  | 	emit diveListNotifier.divesChanged(changedDives, DiveField::DIVESITE); | 
					
						
							| 
									
										
										
										
											2019-03-22 20:55:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | 	// Clear vector of unused owning pointers
 | 
					
						
							|  |  |  | 	sites.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Remove a set of dive sites. Get owning pointers to them. The dives are set to
 | 
					
						
							|  |  |  | // being at no dive site, but the dive site will retain a list of dives, so
 | 
					
						
							|  |  |  | // that the dives can be readded to the site on undo.
 | 
					
						
							|  |  |  | static std::vector<OwningDiveSitePtr> removeDiveSites(std::vector<dive_site *> &sites) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::vector<OwningDiveSitePtr> res; | 
					
						
							| 
									
										
										
										
											2019-06-23 09:22:26 +02:00
										 |  |  | 	QVector<dive *> changedDives; | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | 	res.reserve(sites.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (dive_site *ds: sites) { | 
					
						
							|  |  |  | 		// Reset the dive_site field of the affected dives
 | 
					
						
							|  |  |  | 		for (int i = 0; i < ds->dives.nr; ++i) { | 
					
						
							| 
									
										
										
										
											2019-03-22 20:55:05 +01:00
										 |  |  | 			struct dive *d = ds->dives.dives[i]; | 
					
						
							|  |  |  | 			d->dive_site = nullptr; | 
					
						
							|  |  |  | 			changedDives.push_back(d); | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Remove dive site from core and take ownership.
 | 
					
						
							|  |  |  | 		int idx = unregister_dive_site(ds); | 
					
						
							|  |  |  | 		res.emplace_back(ds); | 
					
						
							|  |  |  | 		emit diveListNotifier.diveSiteDeleted(ds, idx); // Inform frontend of removed dive site.
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-23 09:22:26 +02:00
										 |  |  | 	emit diveListNotifier.divesChanged(changedDives, DiveField::DIVESITE); | 
					
						
							| 
									
										
										
										
											2019-03-22 20:55:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | 	sites.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 20:58:25 +01:00
										 |  |  | AddDiveSite::AddDiveSite(const QString &name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("add dive site")); | 
					
						
							| 
									
										
										
										
											2019-03-13 20:58:25 +01:00
										 |  |  | 	sitesToAdd.emplace_back(alloc_dive_site()); | 
					
						
							|  |  |  | 	sitesToAdd.back()->name = copy_qstring(name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool AddDiveSite::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AddDiveSite::redo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToRemove = addDiveSites(sitesToAdd); | 
					
						
							| 
									
										
										
										
											2019-03-13 20:58:25 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AddDiveSite::undo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToAdd = removeDiveSites(sitesToRemove); | 
					
						
							| 
									
										
										
										
											2019-03-13 20:58:25 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-04 20:40:27 -07:00
										 |  |  | ImportDiveSites::ImportDiveSites(struct dive_site_table *sites, const QString &source) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("import dive sites from %1").arg(source)); | 
					
						
							| 
									
										
										
										
											2019-05-04 20:40:27 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (int i = 0; i < sites->nr; ++i) { | 
					
						
							|  |  |  | 		struct dive_site *new_ds = sites->dive_sites[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Don't import dive sites that already exist. Currently we only check for
 | 
					
						
							|  |  |  | 		// the same name. We might want to be smarter here and merge dive site data, etc.
 | 
					
						
							|  |  |  | 		struct dive_site *old_ds = get_same_dive_site(new_ds); | 
					
						
							|  |  |  | 		if (old_ds) { | 
					
						
							|  |  |  | 			free_dive_site(new_ds); | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		sitesToAdd.emplace_back(new_ds); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// All site have been consumed
 | 
					
						
							|  |  |  | 	sites->nr = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ImportDiveSites::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !sitesToAdd.empty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ImportDiveSites::redo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToRemove = addDiveSites(sitesToAdd); | 
					
						
							| 
									
										
										
										
											2019-05-04 20:40:27 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ImportDiveSites::undo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToAdd = removeDiveSites(sitesToRemove); | 
					
						
							| 
									
										
										
										
											2019-05-04 20:40:27 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-06 12:47:53 -08:00
										 |  |  | DeleteDiveSites::DeleteDiveSites(const QVector<dive_site *> &sites) : sitesToRemove(std::vector<dive_site *>(sites.begin(),sites.end())) | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("delete %n dive site(s)", "", sites.size())); | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool DeleteDiveSites::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !sitesToRemove.empty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DeleteDiveSites::redo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToAdd = removeDiveSites(sitesToRemove); | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DeleteDiveSites::undo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToRemove = addDiveSites(sitesToAdd); | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-19 19:52:54 +01:00
										 |  |  | PurgeUnusedDiveSites::PurgeUnusedDiveSites() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("purge unused dive sites")); | 
					
						
							| 
									
										
										
										
											2019-03-19 19:52:54 +01:00
										 |  |  | 	for (int i = 0; i < dive_site_table.nr; ++i) { | 
					
						
							|  |  |  | 		dive_site *ds = dive_site_table.dive_sites[i]; | 
					
						
							|  |  |  | 		if (ds->dives.nr == 0) | 
					
						
							|  |  |  | 			sitesToRemove.push_back(ds); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool PurgeUnusedDiveSites::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !sitesToRemove.empty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PurgeUnusedDiveSites::redo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToAdd = removeDiveSites(sitesToRemove); | 
					
						
							| 
									
										
										
										
											2019-03-19 19:52:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void PurgeUnusedDiveSites::undo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToRemove = addDiveSites(sitesToAdd); | 
					
						
							| 
									
										
										
										
											2019-03-19 19:52:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 20:10:22 +01:00
										 |  |  | // Helper function: swap C and Qt string
 | 
					
						
							|  |  |  | static void swap(char *&c, QString &q) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	QString s = c; | 
					
						
							|  |  |  | 	free(c); | 
					
						
							|  |  |  | 	c = copy_qstring(q); | 
					
						
							|  |  |  | 	q = s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-12 23:51:39 +01:00
										 |  |  | EditDiveSiteName::EditDiveSiteName(dive_site *dsIn, const QString &name) : ds(dsIn), | 
					
						
							|  |  |  | 	value(name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("Edit dive site name")); | 
					
						
							| 
									
										
										
										
											2019-03-12 23:51:39 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditDiveSiteName::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return value != QString(ds->name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteName::redo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-03-13 20:10:22 +01:00
										 |  |  | 	swap(ds->name, value); | 
					
						
							| 
									
										
										
										
											2019-03-12 23:51:39 +01:00
										 |  |  | 	emit diveListNotifier.diveSiteChanged(ds, LocationInformationModel::NAME); // Inform frontend of changed dive site.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteName::undo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Undo and redo do the same
 | 
					
						
							|  |  |  | 	redo(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-13 20:10:22 +01:00
										 |  |  | EditDiveSiteDescription::EditDiveSiteDescription(dive_site *dsIn, const QString &description) : ds(dsIn), | 
					
						
							|  |  |  | 	value(description) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("Edit dive site description")); | 
					
						
							| 
									
										
										
										
											2019-03-13 20:10:22 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditDiveSiteDescription::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return value != QString(ds->description); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteDescription::redo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	swap(ds->description, value); | 
					
						
							|  |  |  | 	emit diveListNotifier.diveSiteChanged(ds, LocationInformationModel::DESCRIPTION); // Inform frontend of changed dive site.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteDescription::undo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Undo and redo do the same
 | 
					
						
							|  |  |  | 	redo(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 00:00:54 +01:00
										 |  |  | EditDiveSiteNotes::EditDiveSiteNotes(dive_site *dsIn, const QString ¬es) : ds(dsIn), | 
					
						
							|  |  |  | 	value(notes) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("Edit dive site notes")); | 
					
						
							| 
									
										
										
										
											2019-03-14 00:00:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditDiveSiteNotes::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return value != QString(ds->notes); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteNotes::redo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	swap(ds->notes, value); | 
					
						
							|  |  |  | 	emit diveListNotifier.diveSiteChanged(ds, LocationInformationModel::NOTES); // Inform frontend of changed dive site.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteNotes::undo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Undo and redo do the same
 | 
					
						
							|  |  |  | 	redo(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 08:26:50 +01:00
										 |  |  | EditDiveSiteCountry::EditDiveSiteCountry(dive_site *dsIn, const QString &country) : ds(dsIn), | 
					
						
							|  |  |  | 	value(country) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("Edit dive site country")); | 
					
						
							| 
									
										
										
										
											2019-03-14 08:26:50 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditDiveSiteCountry::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !same_string(qPrintable(value), taxonomy_get_country(&ds->taxonomy)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteCountry::redo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	QString old = taxonomy_get_country(&ds->taxonomy); | 
					
						
							|  |  |  | 	taxonomy_set_country(&ds->taxonomy, copy_qstring(value), taxonomy_origin::GEOMANUAL); | 
					
						
							|  |  |  | 	value = old; | 
					
						
							|  |  |  | 	emit diveListNotifier.diveSiteChanged(ds, LocationInformationModel::TAXONOMY); // Inform frontend of changed dive site.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteCountry::undo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Undo and redo do the same
 | 
					
						
							|  |  |  | 	redo(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 23:28:45 +01:00
										 |  |  | EditDiveSiteLocation::EditDiveSiteLocation(dive_site *dsIn, const location_t location) : ds(dsIn), | 
					
						
							|  |  |  | 	value(location) | 
					
						
							| 
									
										
										
										
											2019-03-14 22:07:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("Edit dive site location")); | 
					
						
							| 
									
										
										
										
											2019-03-14 22:07:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditDiveSiteLocation::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	bool ok = has_location(&value); | 
					
						
							|  |  |  | 	bool old_ok = has_location(&ds->location); | 
					
						
							|  |  |  | 	if (ok != old_ok) | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	return ok && !same_location(&value, &ds->location); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteLocation::redo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::swap(value, ds->location); | 
					
						
							|  |  |  | 	emit diveListNotifier.diveSiteChanged(ds, LocationInformationModel::LOCATION); // Inform frontend of changed dive site.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteLocation::undo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Undo and redo do the same
 | 
					
						
							|  |  |  | 	redo(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 14:32:55 +01:00
										 |  |  | EditDiveSiteTaxonomy::EditDiveSiteTaxonomy(dive_site *dsIn, taxonomy_data &taxonomy) : ds(dsIn), | 
					
						
							|  |  |  | 	value(taxonomy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// We did a dumb copy. Erase the source to remove double references to strings.
 | 
					
						
							|  |  |  | 	memset(&taxonomy, 0, sizeof(taxonomy)); | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("Edit dive site taxonomy")); | 
					
						
							| 
									
										
										
										
											2019-03-15 14:32:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | EditDiveSiteTaxonomy::~EditDiveSiteTaxonomy() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	free_taxonomy(&value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool EditDiveSiteTaxonomy::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// TODO: Apparently we have no way of comparing taxonomies?
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteTaxonomy::redo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::swap(value, ds->taxonomy); | 
					
						
							|  |  |  | 	emit diveListNotifier.diveSiteChanged(ds, LocationInformationModel::TAXONOMY); // Inform frontend of changed dive site.
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void EditDiveSiteTaxonomy::undo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// Undo and redo do the same
 | 
					
						
							|  |  |  | 	redo(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | MergeDiveSites::MergeDiveSites(dive_site *dsIn, const QVector<dive_site *> &sites) : ds(dsIn) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("merge dive sites")); | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | 	sitesToRemove.reserve(sites.size()); | 
					
						
							|  |  |  | 	for (dive_site *site: sites) { | 
					
						
							|  |  |  | 		if (site != ds) | 
					
						
							|  |  |  | 			sitesToRemove.push_back(site); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool MergeDiveSites::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !sitesToRemove.empty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MergeDiveSites::redo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// First, remove all dive sites
 | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToAdd = removeDiveSites(sitesToRemove); | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 22:02:10 +01:00
										 |  |  | 	// Remember which dives changed so that we can send a single dives-edited signal
 | 
					
						
							| 
									
										
										
										
											2019-06-23 09:22:26 +02:00
										 |  |  | 	QVector<dive *> divesChanged; | 
					
						
							| 
									
										
										
										
											2019-03-20 22:02:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | 	// The dives of the above dive sites were reset to no dive sites.
 | 
					
						
							|  |  |  | 	// Add them to the merged-into dive site. Thankfully, we remember
 | 
					
						
							|  |  |  | 	// the dives in the sitesToAdd vector.
 | 
					
						
							|  |  |  | 	for (const OwningDiveSitePtr &site: sitesToAdd) { | 
					
						
							| 
									
										
										
										
											2019-03-20 22:02:10 +01:00
										 |  |  | 		for (int i = 0; i < site->dives.nr; ++i) { | 
					
						
							|  |  |  | 			add_dive_to_dive_site(site->dives.dives[i], ds); | 
					
						
							| 
									
										
										
										
											2019-02-11 15:34:43 +01:00
										 |  |  | 			divesChanged.push_back(site->dives.dives[i]); | 
					
						
							| 
									
										
										
										
											2019-03-20 22:02:10 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-06-23 09:22:26 +02:00
										 |  |  | 	emit diveListNotifier.divesChanged(divesChanged, DiveField::DIVESITE); | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MergeDiveSites::undo() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-03-20 22:02:10 +01:00
										 |  |  | 	// Remember which dives changed so that we can send a single dives-edited signal
 | 
					
						
							| 
									
										
										
										
											2019-06-23 09:22:26 +02:00
										 |  |  | 	QVector<dive *> divesChanged; | 
					
						
							| 
									
										
										
										
											2019-03-20 22:02:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | 	// Before readding the dive sites, unregister the corresponding dives so that they can be
 | 
					
						
							|  |  |  | 	// readded to their old dive sites.
 | 
					
						
							|  |  |  | 	for (const OwningDiveSitePtr &site: sitesToAdd) { | 
					
						
							| 
									
										
										
										
											2019-03-20 22:02:10 +01:00
										 |  |  | 		for (int i = 0; i < site->dives.nr; ++i) { | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | 			unregister_dive_from_dive_site(site->dives.dives[i]); | 
					
						
							| 
									
										
										
										
											2019-02-11 15:34:43 +01:00
										 |  |  | 			divesChanged.push_back(site->dives.dives[i]); | 
					
						
							| 
									
										
										
										
											2019-03-20 22:02:10 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-13 21:34:22 +01:00
										 |  |  | 	sitesToRemove = addDiveSites(sitesToAdd); | 
					
						
							| 
									
										
										
										
											2019-03-22 20:55:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-23 09:22:26 +02:00
										 |  |  | 	emit diveListNotifier.divesChanged(divesChanged, DiveField::DIVESITE); | 
					
						
							| 
									
										
										
										
											2019-03-15 17:41:31 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-16 21:35:26 +01:00
										 |  |  | ApplyGPSFixes::ApplyGPSFixes(const std::vector<DiveAndLocation> &fixes) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-21 16:46:36 -07:00
										 |  |  | 	setText(Command::Base::tr("apply GPS fixes")); | 
					
						
							| 
									
										
										
										
											2019-11-16 21:35:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (const DiveAndLocation &dl: fixes) { | 
					
						
							|  |  |  | 		struct dive_site *ds = dl.d->dive_site; | 
					
						
							|  |  |  | 		if (ds) { | 
					
						
							|  |  |  | 			// Arbitrary choice: if we find multiple fixes for the same dive, we use the first one.
 | 
					
						
							|  |  |  | 			if (std::find_if(siteLocations.begin(), siteLocations.end(), | 
					
						
							|  |  |  | 					 [ds] (const SiteAndLocation &sl) { return sl.ds == ds; }) == siteLocations.end()) { | 
					
						
							|  |  |  | 				siteLocations.push_back({ ds, dl.location }); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			ds = create_dive_site(qPrintable(dl.name), &dive_site_table); | 
					
						
							|  |  |  | 			ds->location = dl.location; | 
					
						
							|  |  |  | 			add_dive_to_dive_site(dl.d, ds); | 
					
						
							|  |  |  | 			dl.d->dive_site = nullptr; // This will be set on redo()
 | 
					
						
							|  |  |  | 			sitesToAdd.emplace_back(ds); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ApplyGPSFixes::workToBeDone() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !sitesToAdd.empty() || !siteLocations.empty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplyGPSFixes::editDiveSites() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	for (SiteAndLocation &sl: siteLocations) { | 
					
						
							|  |  |  | 		std::swap(sl.location, sl.ds->location); | 
					
						
							|  |  |  | 		emit diveListNotifier.diveSiteChanged(sl.ds, LocationInformationModel::LOCATION); // Inform frontend of changed dive site.
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplyGPSFixes::redo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	sitesToRemove = addDiveSites(sitesToAdd); | 
					
						
							|  |  |  | 	editDiveSites(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ApplyGPSFixes::undo() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	sitesToAdd = removeDiveSites(sitesToRemove); | 
					
						
							|  |  |  | 	editDiveSites(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-12 22:35:43 +01:00
										 |  |  | } // namespace Command
 |