diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2019-03-20 21:46:58 +0100 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2019-04-12 18:19:07 +0300 |
commit | 6f574c53a38ad848bfd364acb0ae16680c3f6c8a (patch) | |
tree | f62f5d8c24dc7787d60d161e63640393add7bad8 /desktop-widgets/command_edit.cpp | |
parent | 4cb1ceefff96121331f63e1455d233b32b3d7680 (diff) | |
download | subsurface-6f574c53a38ad848bfd364acb0ae16680c3f6c8a.tar.gz |
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 <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'desktop-widgets/command_edit.cpp')
-rw-r--r-- | desktop-widgets/command_edit.cpp | 80 |
1 files changed, 79 insertions, 1 deletions
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<QString>::EditBase(const QVector<dive *> &dives, QString oldValue, QString newValue); template EditBase<int>::EditBase(const QVector<dive *> &dives, int oldValue, int newValue); +template +EditBase<struct dive_site *>::EditBase(const QVector<dive *> &dives, struct dive_site *oldValue, struct dive_site *newValue); // Undo and redo do the same as just the stored value is exchanged template<typename T> void EditBase<T>::redo() { - undo(); + // Note: here, we explicitly call the undo function of EditBase<T> and don't do + // virtual dispatch. Thus, derived classes can call this redo function without + // having their own undo() function called. + EditBase<T>::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<dive_site *>::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<dive *> &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 |