diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2020-01-10 08:25:37 +0800 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2020-03-10 09:25:57 -0700 |
commit | 57b96490b2c5b81023439046dea225b8caf09946 (patch) | |
tree | 3c5a811d23fbd80720de18331786ab1b56222407 /commands | |
parent | 200932189451d52e277004871004e3b2a0593e58 (diff) | |
download | subsurface-57b96490b2c5b81023439046dea225b8caf09946.tar.gz |
mobile/undo: create EditDive command
Command that just swaps two dives. This is rather complex,
as for example a dive site might be created.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'commands')
-rw-r--r-- | commands/command.cpp | 7 | ||||
-rw-r--r-- | commands/command.h | 5 | ||||
-rw-r--r-- | commands/command_edit.cpp | 133 | ||||
-rw-r--r-- | commands/command_edit.h | 27 |
4 files changed, 172 insertions, 0 deletions
diff --git a/commands/command.cpp b/commands/command.cpp index aa1d18183..47fc45b90 100644 --- a/commands/command.cpp +++ b/commands/command.cpp @@ -304,4 +304,11 @@ void editTripNotes(dive_trip *trip, const QString &s) execute(new EditTripNotes(trip, s)); } +#ifdef SUBSURFACE_MOBILE +void editDive(dive *oldDive, dive *newDive, dive_site *createDs, dive_site *changeDs, location_t dsLocation) +{ + execute(new EditDive(oldDive, newDive, createDs, changeDs, dsLocation)); +} +#endif // SUBSURFACE_MOBILE + } // namespace Command diff --git a/commands/command.h b/commands/command.h index 281c1635c..00de1425a 100644 --- a/commands/command.h +++ b/commands/command.h @@ -89,6 +89,11 @@ void editProfile(dive *d); // dive computer(s) and cylinder(s) will be reset! int addWeight(bool currentDiveOnly); int removeWeight(int index, bool currentDiveOnly); int editWeight(int index, weightsystem_t ws, bool currentDiveOnly); +#ifdef SUBSURFACE_MOBILE +// Edits a dive and creates a divesite (if createDs != NULL) or edits a divesite (if changeDs != NULL). +// Takes ownership of newDive and createDs! +void editDive(dive *oldDive, dive *newDive, dive_site *createDs, dive_site *changeDs, location_t dsLocation); +#endif // 5) Trip editing commands diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index 1a9684e1f..e08f678e7 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -7,6 +7,9 @@ #include "core/subsurface-string.h" #include "core/tag.h" #include "qt-models/weightsysteminfomodel.h" +#ifdef SUBSURFACE_MOBILE +#include "qt-models/divelocationmodel.h" +#endif namespace Command { @@ -1145,4 +1148,134 @@ void EditWeight::undo() redo(); } +#ifdef SUBSURFACE_MOBILE + +EditDive::EditDive(dive *oldDiveIn, dive *newDiveIn, dive_site *createDs, dive_site *editDs, location_t dsLocationIn) + : oldDive(oldDiveIn) + , newDive(newDiveIn) + , changedFields(DiveField::NONE) + , siteToRemove(nullptr) + , siteToAdd(createDs) + , siteToEdit(editDs) + , dsLocation(dsLocationIn) +{ + if (!oldDive || ! newDive) + return; + + setText(tr("Edit dive")); + + // Calculate the fields that changed. + // Note: Probably not needed, as on mobile we don't have that granularity. + // However, for future-proofeness let's just do it. + changedFields = DiveField::NONE; + if (oldDive->number != newDive->number) + changedFields |= DiveField::NR; + if (oldDive->when != newDive->when) + changedFields |= DiveField::DATETIME; + if (oldDive->maxdepth.mm != newDive->maxdepth.mm) + changedFields |= DiveField::DEPTH; + if (oldDive->duration.seconds != newDive->duration.seconds) + changedFields |= DiveField::DURATION; + if (oldDive->airtemp.mkelvin != newDive->airtemp.mkelvin) + changedFields |= DiveField::AIR_TEMP; + if (oldDive->watertemp.mkelvin != newDive->watertemp.mkelvin) + changedFields |= DiveField::WATER_TEMP; + if (oldDive->surface_pressure.mbar != newDive->surface_pressure.mbar) + changedFields |= DiveField::ATM_PRESS; + if (oldDive->dive_site != newDive->dive_site) + changedFields |= DiveField::DIVESITE; + if (!same_string(oldDive->divemaster, newDive->divemaster)) + changedFields |= DiveField::DIVEMASTER; + if (!same_string(oldDive->buddy, newDive->buddy)) + changedFields |= DiveField::BUDDY; + if (oldDive->rating != newDive->rating) + changedFields |= DiveField::RATING; + if (oldDive->visibility != newDive->visibility) + changedFields |= DiveField::VISIBILITY; + if (oldDive->wavesize != newDive->wavesize) + changedFields |= DiveField::WAVESIZE; + if (oldDive->current != newDive->current) + changedFields |= DiveField::CURRENT; + if (oldDive->surge != newDive->surge) + changedFields |= DiveField::SURGE; + if (oldDive->chill != newDive->chill) + changedFields |= DiveField::CHILL; + if (!same_string(oldDive->suit, newDive->suit)) + changedFields |= DiveField::SUIT; + if (get_taglist_string(oldDive->tag_list) != get_taglist_string(newDive->tag_list)) // This is cheating. Do we have a taglist comparison function? + changedFields |= DiveField::TAGS; + if (oldDive->dc.divemode != newDive->dc.divemode) + changedFields |= DiveField::MODE; + if (!same_string(oldDive->notes, newDive->notes)) + changedFields |= DiveField::NOTES; + if (oldDive->salinity != newDive->salinity) + changedFields |= DiveField::SALINITY; +} + +void EditDive::undo() +{ + if (siteToRemove) { + int idx = unregister_dive_site(siteToRemove); + siteToAdd.reset(siteToRemove); + emit diveListNotifier.diveSiteDeleted(siteToRemove, idx); // Inform frontend of removed dive site. + } + + exchangeDives(); + editDs(); +} + +void EditDive::redo() +{ + if (siteToAdd) { + siteToRemove = siteToAdd.get(); + int idx = register_dive_site(siteToAdd.release()); // Return ownership to backend. + emit diveListNotifier.diveSiteAdded(siteToRemove, idx); // Inform frontend of new dive site. + } + + exchangeDives(); + editDs(); +} + +void EditDive::exchangeDives() +{ + // Bluntly exchange dive data by shallow copy + std::swap(*newDive, *oldDive); + invalidate_dive_cache(oldDive); + + // Changing times may have unsorted the dive and trip tables + QVector<dive *> dives = { oldDive }; + timestamp_t delta = oldDive->when - newDive->when; + if (delta != 0) { + sort_dive_table(&dive_table); + sort_trip_table(&trip_table); + if (newDive->divetrip != oldDive->divetrip) + qWarning("Command::EditDive::redo(): This command does not support moving between trips!"); + if (oldDive->divetrip) + sort_dive_table(&newDive->divetrip->dives); // Keep the trip-table in order + emit diveListNotifier.divesTimeChanged(delta, dives); + } + + // Send signals + emit diveListNotifier.divesChanged(dives, changedFields); + + // Select the changed dives + setSelection( { oldDive }, oldDive); +} + +void EditDive::editDs() +{ + if (siteToEdit) { + std::swap(siteToEdit->location, dsLocation); + emit diveListNotifier.diveSiteChanged(siteToEdit, LocationInformationModel::LOCATION); // Inform frontend of changed dive site. + } +} + +bool EditDive::workToBeDone() +{ + // We trust the frontend that an EditDive command is only created if there are changes. + return true; +} + +#endif // SUBSURFACE_MOBILE + } // namespace Command diff --git a/commands/command_edit.h b/commands/command_edit.h index a148550b3..aeecc0bab 100644 --- a/commands/command_edit.h +++ b/commands/command_edit.h @@ -375,6 +375,33 @@ private: void redo() override; }; +#ifdef SUBSURFACE_MOBILE +// Edit a full dive. This is used on mobile where we don't have per-field granularity. +// It may add or edit a dive site. +class EditDive : public Base { +public: + EditDive(dive *oldDive, dive *newDive, dive_site *createDs, dive_site *editDs, location_t dsLocation); // Takes ownership of newDive +private: + dive *oldDive; // Dive that is going to be overwritten + OwningDivePtr newDive; // New data + int changedFields; + + dive_site *siteToRemove; + OwningDiveSitePtr siteToAdd; + + dive_site *siteToEdit; + location_t dsLocation; + + void undo() override; + void redo() override; + bool workToBeDone() override; + + void exchangeDives(); + void editDs(); +}; + +#endif // SUBSURFACE_MOBILE + } // namespace Command #endif |