From 6f574c53a38ad848bfd364acb0ae16680c3f6c8a Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Wed, 20 Mar 2019 21:46:58 +0100 Subject: Undo: implement undo of dive site editing This one is a bit more tricky. There are two modes: set dive site and set newly created dive site. This is realized using an OO model with derived classed. Quite convoluted - but it seems to work. Moreover, editing a dive site is not simply setting a value, but the list of dives in a dive site has to be kept up to date. Finally, we have to inform the dive site list of the changed number of dives. Therefore add a new signal diveSiteDivesChanged. To send only one signal per dive site, hook into the undo() and redo() functions and call the functions of the base class there. Signed-off-by: Berthold Stoeger --- desktop-widgets/command_edit.cpp | 80 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) (limited to 'desktop-widgets/command_edit.cpp') diff --git a/desktop-widgets/command_edit.cpp b/desktop-widgets/command_edit.cpp index dc90ccd5e..c1e00bdf1 100644 --- a/desktop-widgets/command_edit.cpp +++ b/desktop-widgets/command_edit.cpp @@ -2,6 +2,7 @@ #include "command_edit.h" #include "core/divelist.h" +#include "core/qthelper.h" // for copy_qstring namespace Command { @@ -70,12 +71,17 @@ template EditBase::EditBase(const QVector &dives, QString oldValue, QString newValue); template EditBase::EditBase(const QVector &dives, int oldValue, int newValue); +template +EditBase::EditBase(const QVector &dives, struct dive_site *oldValue, struct dive_site *newValue); // Undo and redo do the same as just the stored value is exchanged template void EditBase::redo() { - undo(); + // Note: here, we explicitly call the undo function of EditBase and don't do + // virtual dispatch. Thus, derived classes can call this redo function without + // having their own undo() function called. + EditBase::undo(); } // Implementation of virtual functions @@ -208,6 +214,78 @@ DiveField EditWaterTemp::fieldId() const return DiveField::WATER_TEMP; } +// ***** DiveSite ***** +void EditDiveSite::set(struct dive *d, struct dive_site *dive_site) const +{ + unregister_dive_from_dive_site(d); + add_dive_to_dive_site(d, dive_site); +} + +struct dive_site *EditDiveSite::data(struct dive *d) const +{ + return d->dive_site; +} + +QString EditDiveSite::fieldName() const +{ + return tr("dive site"); +} + +DiveField EditDiveSite::fieldId() const +{ + return DiveField::DIVESITE; +} + +void EditDiveSite::undo() +{ + // Do the normal undo thing, then send dive site changed signals + EditBase::undo(); + if (value) + emit diveListNotifier.diveSiteDivesChanged(value); + if (old) + emit diveListNotifier.diveSiteDivesChanged(old); +} + +void EditDiveSite::redo() +{ + EditDiveSite::undo(); // Undo and redo do the same +} + +static struct dive_site *createDiveSite(const QString &name, struct dive_site *old) +{ + struct dive_site *ds = alloc_dive_site(); + if (old) { + copy_dive_site(old, ds); + free(ds->name); // Free name, as we will overwrite it with our own version + } + ds->name = copy_qstring(name); + return ds; +} + +EditDiveSiteNew::EditDiveSiteNew(const QVector &dives, const QString &newName, struct dive_site *oldValue) : + EditDiveSite(dives, createDiveSite(newName, oldValue), oldValue), + diveSiteToAdd(value), + diveSiteToRemove(nullptr) +{ +} + +void EditDiveSiteNew::undo() +{ + EditDiveSite::undo(); + int idx = unregister_dive_site(diveSiteToRemove); + diveSiteToAdd.reset(diveSiteToRemove); + emit diveListNotifier.diveSiteDeleted(diveSiteToRemove, idx); // Inform frontend of removed dive site. + diveSiteToRemove = nullptr; +} + +void EditDiveSiteNew::redo() +{ + diveSiteToRemove = diveSiteToAdd.get(); + int idx = register_dive_site(diveSiteToAdd.release()); // Return ownership to backend. + emit diveListNotifier.diveSiteAdded(diveSiteToRemove, idx); // Inform frontend of new dive site. + EditDiveSite::redo(); +} + // ***** Mode ***** // Editing the dive mode has very peculiar semantics for historic reasons: // Since the dive-mode depends on the dive computer, the i-th dive computer -- cgit v1.2.3-70-g09d2