undo: implement addBookmark undo command

Create a new translation unit for event-related undo commands.
Create a base class of commands that add events and one subclass
that adds a bookmark event.
Use this command in the profile-widget.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2020-03-03 22:34:50 +01:00
parent 3aa1bb5bfa
commit 30c7499a3c
7 changed files with 108 additions and 7 deletions

View file

@ -14,6 +14,8 @@ set(SUBSURFACE_GENERIC_COMMANDS_SRCS
command_edit.h
command_edit_trip.cpp
command_edit_trip.h
command_event.cpp
command_event.h
)
add_library(subsurface_commands STATIC ${SUBSURFACE_GENERIC_COMMANDS_SRCS})
target_link_libraries(subsurface_commands ${QT_LIBRARIES})

View file

@ -5,6 +5,7 @@
#include "command_divesite.h"
#include "command_edit.h"
#include "command_edit_trip.h"
#include "command_event.h"
namespace Command {
@ -326,4 +327,11 @@ void editDive(dive *oldDive, dive *newDive, dive_site *createDs, dive_site *chan
}
#endif // SUBSURFACE_MOBILE
// Event commands
void addEventBookmark(struct dive *d, int dcNr, int seconds)
{
execute(new AddEventBookmark(d, dcNr, seconds));
}
} // namespace Command

View file

@ -104,6 +104,10 @@ void editDive(dive *oldDive, dive *newDive, dive_site *createDs, dive_site *chan
void editTripLocation(dive_trip *trip, const QString &s);
void editTripNotes(dive_trip *trip, const QString &s);
// 6) Event commands
void addEventBookmark(struct dive *d, int dcNr, int seconds);
} // namespace Command
#endif // COMMAND_H

View file

@ -141,7 +141,7 @@
// We put everything in a namespace, so that we can shorten names without polluting the global namespace
namespace Command {
// Classes used to automatically call free_dive()/free_trip for owning pointers that go out of scope.
// Classes used to automatically call the appropriate free_*() function for owning pointers that go out of scope.
struct DiveDeleter {
void operator()(dive *d) { free_dive(d); }
};
@ -151,11 +151,15 @@ struct TripDeleter {
struct DiveSiteDeleter {
void operator()(dive_site *ds) { free_dive_site(ds); }
};
struct EventDeleter {
void operator()(event *ev) { free(ev); }
};
// Owning pointers to dive and dive_trip objects.
// Owning pointers to dive, dive_trip, dive_site and event objects.
typedef std::unique_ptr<dive, DiveDeleter> OwningDivePtr;
typedef std::unique_ptr<dive_trip, TripDeleter> OwningTripPtr;
typedef std::unique_ptr<dive_site, DiveSiteDeleter> OwningDiveSitePtr;
typedef std::unique_ptr<event, EventDeleter> OwningEventPtr;
// This is the base class of all commands.
// It defines the Qt-translation functions
@ -182,4 +186,3 @@ QString getListOfDives(QVector<struct dive *> dives);
} // namespace Command
#endif // COMMAND_BASE_H

View file

@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-2.0
#include "command_event.h"
#include "core/dive.h"
#include "core/subsurface-qt/divelistnotifier.h"
#include "core/libdivecomputer.h"
namespace Command {
AddEventBase::AddEventBase(struct dive *dIn, int dcNrIn, struct event *ev) :
d(dIn), dcNr(dcNrIn), eventToAdd(ev)
{
}
bool AddEventBase::workToBeDone()
{
return true;
}
void AddEventBase::redo()
{
struct divecomputer *dc = get_dive_dc(d, dcNr);
eventToRemove = eventToAdd.get();
add_event_to_dc(dc, eventToAdd.release()); // return ownership to backend
invalidate_dive_cache(d);
}
void AddEventBase::undo()
{
struct divecomputer *dc = get_dive_dc(d, dcNr);
remove_event_from_dc(dc, eventToRemove);
eventToAdd.reset(eventToRemove); // take ownership of event
eventToRemove = nullptr;
invalidate_dive_cache(d);
}
AddEventBookmark::AddEventBookmark(struct dive *d, int dcNr, int seconds) :
AddEventBase(d, dcNr, create_event(seconds, SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark"))
{
setText(tr("Add bookmark"));
}
} // namespace Command

44
commands/command_event.h Normal file
View file

@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-2.0
// Note: this header file is used by the undo-machinery and should not be included elsewhere.
#ifndef COMMAND_EVENT_H
#define COMMAND_EVENT_H
#include "command_base.h"
// We put everything in a namespace, so that we can shorten names without polluting the global namespace
namespace Command {
// Events are a strange thing: they contain there own description which means
// that on changing the description a new object must be allocated. Moreover,
// it means that these objects can't be collected in a table.
// Therefore, the undo commands work on events as they do with dives: using
// owning pointers. See comments in command_base.h
class AddEventBase : public Base {
public:
AddEventBase(struct dive *d, int dcNr, struct event *ev); // Takes ownership of event!
private:
bool workToBeDone() override;
void undo() override;
void redo() override;
// Note: we store dive and the divecomputer-number instead of a pointer to the divecomputer.
// Since one divecomputer is integrated into the dive structure, pointers to divecomputers
// are probably not stable.
struct dive *d;
int dcNr;
OwningEventPtr eventToAdd; // for redo
event *eventToRemove; // for undo
};
class AddEventBookmark : public AddEventBase {
public:
AddEventBookmark(struct dive *d, int dcNr, int seconds);
};
} // namespace Command
#endif // COMMAND_EVENT_H

View file

@ -1600,10 +1600,7 @@ void ProfileWidget2::removeEvent(DiveEventItem *item)
void ProfileWidget2::addBookmark(int seconds)
{
add_event(current_dc, seconds, SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark");
invalidate_dive_cache(current_dive);
mark_divelist_changed(true);
replot();
Command::addEventBookmark(current_dive, dc_number, seconds);
}
void ProfileWidget2::addDivemodeSwitch(int seconds, int divemode)