undo: implement ApplyGPSFixes undo command

This gets a list of dives with GPS fixes and
1) Adds new dive sites if the dive hasn't a dive site set
2) Edits the location of the dive site

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2019-11-16 21:35:26 +01:00 committed by Dirk Hohndel
parent 89047b3541
commit 93bdaa9bb5
4 changed files with 81 additions and 1 deletions

View file

@ -145,6 +145,11 @@ void purgeUnusedDiveSites()
execute(new PurgeUnusedDiveSites);
}
void applyGPSFixes(const std::vector<DiveAndLocation> &fixes)
{
execute(new ApplyGPSFixes(fixes));
}
// Execute an edit-command and return number of edited dives
static int execute_edit(EditDivesBase *cmd)
{

View file

@ -5,6 +5,9 @@
#include "core/dive.h"
#include <QVector>
#include <QAction>
#include <vector>
struct DiveAndLocation;
// We put everything in a namespace, so that we can shorten names without polluting the global namespace
namespace Command {
@ -41,6 +44,7 @@ void splitDiveComputer(dive *d, int dc_num);
void moveDiveComputerToFront(dive *d, int dc_num);
void deleteDiveComputer(dive *d, int dc_num);
void mergeDives(const QVector <dive *> &dives);
void applyGPSFixes(const std::vector<DiveAndLocation> &fixes);
// 3) Dive-site related commands

View file

@ -391,4 +391,51 @@ void MergeDiveSites::undo()
emit diveListNotifier.divesChanged(divesChanged, DiveField::DIVESITE);
}
ApplyGPSFixes::ApplyGPSFixes(const std::vector<DiveAndLocation> &fixes)
{
setText(tr("apply GPS fixes"));
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();
}
} // namespace Command

View file

@ -5,6 +5,7 @@
#define COMMAND_DIVESITE_H
#include "command_base.h"
#include "core/gpslocation.h"
#include <QVector>
@ -110,7 +111,6 @@ private:
QString value; // Value to be set
};
class EditDiveSiteCountry : public Base {
public:
EditDiveSiteCountry(dive_site *ds, const QString &country);
@ -165,6 +165,30 @@ private:
std::vector<OwningDiveSitePtr> sitesToAdd;
};
class ApplyGPSFixes : public Base {
public:
// Note: the dive site table is consumed after the call it will be empty.
ApplyGPSFixes(const std::vector<DiveAndLocation> &fixes);
private:
bool workToBeDone() override;
void undo() override;
void redo() override;
// For undo
std::vector<dive_site *> sitesToRemove;
// For redo
std::vector<OwningDiveSitePtr> sitesToAdd;
// For redo and undo
struct SiteAndLocation {
dive_site *ds;
location_t location;
};
std::vector<SiteAndLocation> siteLocations;
void editDiveSites();
};
} // namespace Command
#endif // COMMAND_DIVESITE_H