diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2020-03-04 18:13:02 +0100 |
---|---|---|
committer | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2020-04-07 00:13:35 +0200 |
commit | ab8e317b28672cc19fd04e994b9adf9b63f0c603 (patch) | |
tree | 3e360e47ad55232fd85be094ef4b19bef7d2f976 | |
parent | f9fe6d759f33c36f1c0c0d20a591f6517fc9071f (diff) | |
download | subsurface-ab8e317b28672cc19fd04e994b9adf9b63f0c603.tar.gz |
undo: implement renaming of events
There is a slight complexity here owing to the fact that the profile
works on a copy of the current dive: We get a copy of the event and
have to search for the original event in the current dive. This
could be done in the undo command. Nevertheless, here we do it in
the profile so that when in the future the profile can work on a
non-copied dive we can simply remove this function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
-rw-r--r-- | commands/command.cpp | 5 | ||||
-rw-r--r-- | commands/command.h | 1 | ||||
-rw-r--r-- | commands/command_event.cpp | 27 | ||||
-rw-r--r-- | commands/command_event.h | 12 | ||||
-rw-r--r-- | core/dive.c | 20 | ||||
-rw-r--r-- | core/dive.h | 3 | ||||
-rw-r--r-- | profile-widget/profilewidget2.cpp | 29 |
7 files changed, 87 insertions, 10 deletions
diff --git a/commands/command.cpp b/commands/command.cpp index 44eb4b8f0..09e85f3b2 100644 --- a/commands/command.cpp +++ b/commands/command.cpp @@ -344,4 +344,9 @@ void addEventSetpointChange(struct dive *d, int dcNr, int seconds, pressure_t pO execute(new AddEventSetpointChange(d, dcNr, seconds, pO2)); } +void renameEvent(struct dive *d, int dcNr, struct event *ev, const char *name) +{ + execute(new RenameEvent(d, dcNr, ev, name)); +} + } // namespace Command diff --git a/commands/command.h b/commands/command.h index aa7c75ab3..eeb400bc4 100644 --- a/commands/command.h +++ b/commands/command.h @@ -109,6 +109,7 @@ void editTripNotes(dive_trip *trip, const QString &s); void addEventBookmark(struct dive *d, int dcNr, int seconds); void addEventDivemodeSwitch(struct dive *d, int dcNr, int seconds, int divemode); void addEventSetpointChange(struct dive *d, int dcNr, int seconds, pressure_t pO2); +void renameEvent(struct dive *d, int dcNr, struct event *ev, const char *name); } // namespace Command diff --git a/commands/command_event.cpp b/commands/command_event.cpp index 7ecd4f070..1114182aa 100644 --- a/commands/command_event.cpp +++ b/commands/command_event.cpp @@ -70,4 +70,31 @@ AddEventSetpointChange::AddEventSetpointChange(struct dive *d, int dcNr, int sec setText(tr("Add set point change")); // TODO: format pO2 value in bar or psi. } +RenameEvent::RenameEvent(struct dive *d, int dcNr, struct event *ev, const char *name) : EventBase(d, dcNr), + eventToAdd(clone_event_rename(ev, name)), + eventToRemove(ev) +{ + setText(tr("Rename bookmark to %1").arg(name)); +} + +bool RenameEvent::workToBeDone() +{ + return true; +} + +void RenameEvent::redoit() +{ + struct divecomputer *dc = get_dive_dc(d, dcNr); + swap_event(dc, eventToRemove, eventToAdd.get()); + event *tmp = eventToRemove; + eventToRemove = eventToAdd.release(); + eventToAdd.reset(tmp); +} + +void RenameEvent::undoit() +{ + // Undo and redo do the same thing - they simply swap events + redoit(); +} + } // namespace Command diff --git a/commands/command_event.h b/commands/command_event.h index a674e258b..ddfe6f7d4 100644 --- a/commands/command_event.h +++ b/commands/command_event.h @@ -58,6 +58,18 @@ public: AddEventSetpointChange(struct dive *d, int dcNr, int seconds, pressure_t pO2); }; +class RenameEvent : public EventBase { +public: + RenameEvent(struct dive *d, int dcNr, struct event *ev, const char *name); +private: + bool workToBeDone() override; + void undoit() override; + void redoit() override; + + OwningEventPtr eventToAdd; // for undo and redo + event *eventToRemove; // for undo and redo +}; + } // namespace Command #endif // COMMAND_EVENT_H diff --git a/core/dive.c b/core/dive.c index 3ec9b1a82..6d2645cef 100644 --- a/core/dive.c +++ b/core/dive.c @@ -166,6 +166,11 @@ struct event *create_event(unsigned int time, int type, int flags, int value, co return ev; } +struct event *clone_event_rename(const struct event *ev, const char *name) +{ + return create_event(ev->time.seconds, ev->type, ev->flags, ev->value, name); +} + void add_event_to_dc(struct divecomputer *dc, struct event *ev) { struct event **p; @@ -192,7 +197,20 @@ struct event *add_event(struct divecomputer *dc, unsigned int time, int type, in return ev; } -static int same_event(const struct event *a, const struct event *b) +/* Substitutes an event in a divecomputer for another. No reordering is performed! */ +void swap_event(struct divecomputer *dc, struct event *from, struct event *to) +{ + for (struct event **ep = &dc->events; *ep; ep = &(*ep)->next) { + if (*ep == from) { + to->next = from->next; + *ep = to; + from->next = NULL; // For good measure. + break; + } + } +} + +bool same_event(const struct event *a, const struct event *b) { if (a->time.seconds != b->time.seconds) return 0; diff --git a/core/dive.h b/core/dive.h index 1de68f4ff..727d4bbff 100644 --- a/core/dive.h +++ b/core/dive.h @@ -378,7 +378,10 @@ extern bool is_cylinder_used(const struct dive *dive, int idx); extern bool is_cylinder_prot(const struct dive *dive, int idx); extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx); extern struct event *create_event(unsigned int time, int type, int flags, int value, const char *name); +extern struct event *clone_event_rename(const struct event *ev, const char *name); extern void add_event_to_dc(struct divecomputer *dc, struct event *ev); +extern void swap_event(struct divecomputer *dc, struct event *from, struct event *to); +extern bool same_event(const struct event *a, const struct event *b); extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name); extern void remove_event_from_dc(struct divecomputer *dc, struct event *event); extern void remove_event(const struct event *event); diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index 76b3c9afb..824c4ccb6 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -1584,6 +1584,22 @@ void ProfileWidget2::unhideEvents() item->show(); } +// The profile displays a copy of the current_dive, namely displayed_dive. +// Therefore, the events we get are likewise copies. This function finds +// the original event. TODO: Remove function once the profile can display +// arbitrary dives. +static event *find_event(const struct event *ev) +{ + struct divecomputer *dc = current_dc; + if (!dc) + return nullptr; + for (struct event *act = current_dc->events; act; act = act->next) { + if (same_event(act, ev)) + return act; + } + return nullptr; +} + void ProfileWidget2::removeEvent(DiveEventItem *item) { struct event *event = item->getEvent(); @@ -1698,7 +1714,9 @@ double ProfileWidget2::getFontPrintScale() #ifndef SUBSURFACE_MOBILE void ProfileWidget2::editName(DiveEventItem *item) { - struct event *event = item->getEvent(); + struct event *event = find_event(item->getEvent()); + if (!event) + return; bool ok; QString newName = QInputDialog::getText(this, tr("Edit name of bookmark"), tr("Custom name:"), QLineEdit::Normal, @@ -1710,14 +1728,7 @@ void ProfileWidget2::editName(DiveEventItem *item) lengthWarning.exec(); return; } - // order is important! first update the current dive (by matching the unchanged event), - // then update the displayed dive (as event is part of the events on displayed dive - // and will be freed as part of changing the name! - update_event_name(current_dive, event, qPrintable(newName)); - update_event_name(&displayed_dive, event, qPrintable(newName)); - invalidate_dive_cache(current_dive); - mark_divelist_changed(true); - replot(); + Command::renameEvent(current_dive, dc_number, event, qPrintable(newName)); } } #endif |