mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
core: turn event-list of divecomputer into std::vector<>
This is a rather long commit, because it refactors lots of the event code from pointer to value semantics: pointers to entries in an std::vector<> are not stable, so better use indexes. To step through the event-list at diven time stamps, add *_loop classes, which encapsulate state that had to be manually handled before by the caller. I'm not happy about the interface, but it tries to mirror the one we had before. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
8ddc960fa0
commit
27dbdd35c6
36 changed files with 644 additions and 821 deletions
|
@ -352,14 +352,14 @@ 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)
|
||||
void renameEvent(struct dive *d, int dcNr, int idx, const std::string name)
|
||||
{
|
||||
execute(new RenameEvent(d, dcNr, ev, name));
|
||||
execute(new RenameEvent(d, dcNr, idx, std::move(name)));
|
||||
}
|
||||
|
||||
void removeEvent(struct dive *d, int dcNr, struct event *ev)
|
||||
void removeEvent(struct dive *d, int dcNr, int idx)
|
||||
{
|
||||
execute(new RemoveEvent(d, dcNr, ev));
|
||||
execute(new RemoveEvent(d, dcNr, idx));
|
||||
}
|
||||
|
||||
void addGasSwitch(struct dive *d, int dcNr, int seconds, int tank)
|
||||
|
|
|
@ -132,8 +132,8 @@ 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);
|
||||
void removeEvent(struct dive *d, int dcNr, struct event *ev);
|
||||
void renameEvent(struct dive *d, int dcNr, int idx, std::string name);
|
||||
void removeEvent(struct dive *d, int dcNr, int idx);
|
||||
void addGasSwitch(struct dive *d, int dcNr, int seconds, int tank);
|
||||
|
||||
// 7) Picture (media) commands
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "command_edit.h"
|
||||
#include "core/divelist.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/event.h"
|
||||
#include "core/fulltext.h"
|
||||
#include "core/qthelper.h" // for copy_qstring
|
||||
#include "core/sample.h"
|
||||
|
@ -898,7 +899,7 @@ EditProfile::EditProfile(const dive *source, int dcNr, EditProfileType type, int
|
|||
duration = source->duration;
|
||||
|
||||
dc.samples = sdc->samples;
|
||||
copy_events(sdc, &dc);
|
||||
dc.events = sdc->events;
|
||||
|
||||
setText(editProfileTypeToString(type, count) + " " + diveNumberOrDate(d));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "command_event.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/event.h"
|
||||
#include "core/selection.h"
|
||||
#include "core/subsurface-qt/divelistnotifier.h"
|
||||
#include "core/libdivecomputer.h"
|
||||
|
@ -35,8 +34,8 @@ void EventBase::updateDive()
|
|||
setSelection({ d }, d, dcNr);
|
||||
}
|
||||
|
||||
AddEventBase::AddEventBase(struct dive *d, int dcNr, struct event *ev) : EventBase(d, dcNr),
|
||||
eventToAdd(ev)
|
||||
AddEventBase::AddEventBase(struct dive *d, int dcNr, struct event ev) : EventBase(d, dcNr),
|
||||
ev(std::move(ev))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -48,32 +47,29 @@ bool AddEventBase::workToBeDone()
|
|||
void AddEventBase::redoit()
|
||||
{
|
||||
struct divecomputer *dc = get_dive_dc(d, dcNr);
|
||||
eventToRemove = eventToAdd.get();
|
||||
add_event_to_dc(dc, eventToAdd.release()); // return ownership to backend
|
||||
idx = add_event_to_dc(dc, ev); // return ownership to backend
|
||||
}
|
||||
|
||||
void AddEventBase::undoit()
|
||||
{
|
||||
struct divecomputer *dc = get_dive_dc(d, dcNr);
|
||||
remove_event_from_dc(dc, eventToRemove);
|
||||
eventToAdd.reset(eventToRemove); // take ownership of event
|
||||
eventToRemove = nullptr;
|
||||
ev = remove_event_from_dc(dc, idx);
|
||||
}
|
||||
|
||||
AddEventBookmark::AddEventBookmark(struct dive *d, int dcNr, int seconds) :
|
||||
AddEventBase(d, dcNr, create_event(seconds, SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark"))
|
||||
AddEventBase(d, dcNr, event(seconds, SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark"))
|
||||
{
|
||||
setText(Command::Base::tr("Add bookmark"));
|
||||
}
|
||||
|
||||
AddEventDivemodeSwitch::AddEventDivemodeSwitch(struct dive *d, int dcNr, int seconds, int divemode) :
|
||||
AddEventBase(d, dcNr, create_event(seconds, SAMPLE_EVENT_BOOKMARK, 0, divemode, QT_TRANSLATE_NOOP("gettextFromC", "modechange")))
|
||||
AddEventBase(d, dcNr, event(seconds, SAMPLE_EVENT_BOOKMARK, 0, divemode, QT_TRANSLATE_NOOP("gettextFromC", "modechange")))
|
||||
{
|
||||
setText(Command::Base::tr("Add dive mode switch to %1").arg(gettextFromC::tr(divemode_text_ui[divemode])));
|
||||
}
|
||||
|
||||
AddEventSetpointChange::AddEventSetpointChange(struct dive *d, int dcNr, int seconds, pressure_t pO2) :
|
||||
AddEventBase(d, dcNr, create_event(seconds, SAMPLE_EVENT_PO2, 0, pO2.mbar, QT_TRANSLATE_NOOP("gettextFromC", "SP change"))),
|
||||
AddEventBase(d, dcNr, event(seconds, SAMPLE_EVENT_PO2, 0, pO2.mbar, QT_TRANSLATE_NOOP("gettextFromC", "SP change"))),
|
||||
divemode(CCR)
|
||||
{
|
||||
setText(Command::Base::tr("Add set point change")); // TODO: format pO2 value in bar or psi.
|
||||
|
@ -91,11 +87,11 @@ void AddEventSetpointChange::redoit()
|
|||
std::swap(get_dive_dc(d, dcNr)->divemode, divemode);
|
||||
}
|
||||
|
||||
RenameEvent::RenameEvent(struct dive *d, int dcNr, struct event *ev, const char *name) : EventBase(d, dcNr),
|
||||
eventToAdd(clone_event_rename(ev, name)),
|
||||
eventToRemove(ev)
|
||||
RenameEvent::RenameEvent(struct dive *d, int dcNr, int idx, const std::string name) : EventBase(d, dcNr),
|
||||
idx(idx),
|
||||
name(std::move(name))
|
||||
{
|
||||
setText(Command::Base::tr("Rename bookmark to %1").arg(name));
|
||||
setText(Command::Base::tr("Rename bookmark to %1").arg(name.c_str()));
|
||||
}
|
||||
|
||||
bool RenameEvent::workToBeDone()
|
||||
|
@ -106,23 +102,24 @@ bool RenameEvent::workToBeDone()
|
|||
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);
|
||||
event *ev = get_event(dc, idx);
|
||||
if (ev)
|
||||
std::swap(ev->name, name);
|
||||
}
|
||||
|
||||
void RenameEvent::undoit()
|
||||
{
|
||||
// Undo and redo do the same thing - they simply swap events
|
||||
// Undo and redo do the same thing - they simply swap names
|
||||
redoit();
|
||||
}
|
||||
|
||||
RemoveEvent::RemoveEvent(struct dive *d, int dcNr, struct event *ev) : EventBase(d, dcNr),
|
||||
eventToRemove(ev),
|
||||
cylinder(ev->type == SAMPLE_EVENT_GASCHANGE2 || ev->type == SAMPLE_EVENT_GASCHANGE ?
|
||||
ev->gas.index : -1)
|
||||
RemoveEvent::RemoveEvent(struct dive *d, int dcNr, int idx) : EventBase(d, dcNr),
|
||||
idx(idx), cylinder(-1)
|
||||
{
|
||||
struct divecomputer *dc = get_dive_dc(d, dcNr);
|
||||
event *ev = get_event(dc, idx);
|
||||
if (ev && (ev->type == SAMPLE_EVENT_GASCHANGE2 || ev->type == SAMPLE_EVENT_GASCHANGE))
|
||||
cylinder = ev->gas.index;
|
||||
setText(Command::Base::tr("Remove %1 event").arg(ev->name.c_str()));
|
||||
}
|
||||
|
||||
|
@ -134,16 +131,13 @@ bool RemoveEvent::workToBeDone()
|
|||
void RemoveEvent::redoit()
|
||||
{
|
||||
struct divecomputer *dc = get_dive_dc(d, dcNr);
|
||||
remove_event_from_dc(dc, eventToRemove);
|
||||
eventToAdd.reset(eventToRemove); // take ownership of event
|
||||
eventToRemove = nullptr;
|
||||
ev = remove_event_from_dc(dc, idx);
|
||||
}
|
||||
|
||||
void RemoveEvent::undoit()
|
||||
{
|
||||
struct divecomputer *dc = get_dive_dc(d, dcNr);
|
||||
eventToRemove = eventToAdd.get();
|
||||
add_event_to_dc(dc, eventToAdd.release()); // return ownership to backend
|
||||
idx = add_event_to_dc(dc, std::move(ev));
|
||||
}
|
||||
|
||||
void RemoveEvent::post() const
|
||||
|
@ -165,18 +159,18 @@ AddGasSwitch::AddGasSwitch(struct dive *d, int dcNr, int seconds, int tank) : Ev
|
|||
// There shouldn't be more than one gas change per time stamp. Just in case we'll
|
||||
// support that anyway.
|
||||
struct divecomputer *dc = get_dive_dc(d, dcNr);
|
||||
struct event *gasChangeEvent = dc->events;
|
||||
while ((gasChangeEvent = get_next_event(gasChangeEvent, "gaschange")) != NULL) {
|
||||
if (gasChangeEvent->time.seconds == seconds) {
|
||||
eventsToRemove.push_back(gasChangeEvent);
|
||||
int idx = gasChangeEvent->gas.index;
|
||||
if (std::find(cylinders.begin(), cylinders.end(), idx) == cylinders.end())
|
||||
cylinders.push_back(idx); // cylinders might have changed their status
|
||||
}
|
||||
gasChangeEvent = gasChangeEvent->next;
|
||||
|
||||
// Note that we remove events in reverse order so that the indexes don't change
|
||||
// meaning while removing. This should be an extremely rare case anyway.
|
||||
for (int idx = static_cast<int>(dc->events.size()) - 1; idx > 0; --idx) {
|
||||
const event &ev = dc->events[idx];
|
||||
if (ev.time.seconds == seconds && ev.name == "gaschange")
|
||||
eventsToRemove.push_back(idx);
|
||||
if (std::find(cylinders.begin(), cylinders.end(), ev.gas.index) == cylinders.end())
|
||||
cylinders.push_back(ev.gas.index); // cylinders might have changed their status
|
||||
}
|
||||
|
||||
eventsToAdd.emplace_back(create_gas_switch_event(d, dc, seconds, tank));
|
||||
eventsToAdd.push_back(create_gas_switch_event(d, dc, seconds, tank));
|
||||
}
|
||||
|
||||
bool AddGasSwitch::workToBeDone()
|
||||
|
@ -186,20 +180,21 @@ bool AddGasSwitch::workToBeDone()
|
|||
|
||||
void AddGasSwitch::redoit()
|
||||
{
|
||||
std::vector<std::unique_ptr<event>> newEventsToAdd;
|
||||
std::vector<event *> newEventsToRemove;
|
||||
std::vector<event> newEventsToAdd;
|
||||
std::vector<int> newEventsToRemove;
|
||||
newEventsToAdd.reserve(eventsToRemove.size());
|
||||
newEventsToRemove.reserve(eventsToAdd.size());
|
||||
struct divecomputer *dc = get_dive_dc(d, dcNr);
|
||||
|
||||
for (event *ev: eventsToRemove) {
|
||||
remove_event_from_dc(dc, ev);
|
||||
newEventsToAdd.emplace_back(ev); // take ownership of event
|
||||
}
|
||||
for (auto &ev: eventsToAdd) {
|
||||
newEventsToRemove.push_back(ev.get());
|
||||
add_event_to_dc(dc, ev.release()); // return ownership to backend
|
||||
}
|
||||
for (int idx: eventsToRemove)
|
||||
newEventsToAdd.push_back(remove_event_from_dc(dc, idx));
|
||||
|
||||
for (auto &ev: eventsToAdd)
|
||||
newEventsToRemove.push_back(add_event_to_dc(dc, std::move(ev)));
|
||||
|
||||
// Make sure that events are removed in reverse order
|
||||
std::sort(newEventsToRemove.begin(), newEventsToRemove.end(), std::greater<int>());
|
||||
|
||||
eventsToAdd = std::move(newEventsToAdd);
|
||||
eventsToRemove = std::move(newEventsToRemove);
|
||||
|
||||
|
|
|
@ -6,15 +6,12 @@
|
|||
|
||||
#include "command_base.h"
|
||||
#include "core/divemode.h"
|
||||
#include "core/event.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
|
||||
// Pointers to events are not stable, so we always store indexes.
|
||||
|
||||
class EventBase : public Base {
|
||||
protected:
|
||||
|
@ -25,8 +22,7 @@ protected:
|
|||
virtual void undoit() = 0;
|
||||
|
||||
// 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.
|
||||
// Pointers to divecomputers are not stable.
|
||||
struct dive *d;
|
||||
int dcNr;
|
||||
private:
|
||||
|
@ -35,15 +31,15 @@ private:
|
|||
|
||||
class AddEventBase : public EventBase {
|
||||
public:
|
||||
AddEventBase(struct dive *d, int dcNr, struct event *ev); // Takes ownership of event!
|
||||
AddEventBase(struct dive *d, int dcNr, struct event ev); // Takes ownership of event!
|
||||
protected:
|
||||
void undoit() override;
|
||||
void redoit() override;
|
||||
private:
|
||||
bool workToBeDone() override;
|
||||
|
||||
std::unique_ptr<event> eventToAdd; // for redo
|
||||
event *eventToRemove; // for undo
|
||||
struct event ev; // for redo
|
||||
int idx; // for undo
|
||||
};
|
||||
|
||||
class AddEventBookmark : public AddEventBase {
|
||||
|
@ -67,28 +63,28 @@ private:
|
|||
|
||||
class RenameEvent : public EventBase {
|
||||
public:
|
||||
RenameEvent(struct dive *d, int dcNr, struct event *ev, const char *name);
|
||||
RenameEvent(struct dive *d, int dcNr, int idx, const std::string name);
|
||||
private:
|
||||
bool workToBeDone() override;
|
||||
void undoit() override;
|
||||
void redoit() override;
|
||||
|
||||
std::unique_ptr<event> eventToAdd; // for undo and redo
|
||||
event *eventToRemove; // for undo and redo
|
||||
int idx; // for undo and redo
|
||||
std::string name; // for undo and redo
|
||||
};
|
||||
|
||||
class RemoveEvent : public EventBase {
|
||||
public:
|
||||
RemoveEvent(struct dive *d, int dcNr, struct event *ev);
|
||||
RemoveEvent(struct dive *d, int dcNr, int idx);
|
||||
private:
|
||||
bool workToBeDone() override;
|
||||
void undoit() override;
|
||||
void redoit() override;
|
||||
void post() const; // Called to fix up dives should a gas-change have happened.
|
||||
|
||||
std::unique_ptr<event> eventToAdd; // for undo
|
||||
event *eventToRemove; // for redo
|
||||
int cylinder; // affected cylinder (if removing gas switch). <0: not a gas switch.
|
||||
event ev; // for undo
|
||||
int idx; // for redo
|
||||
int cylinder; // affected cylinder (if removing gas switch). <0: not a gas switch.
|
||||
};
|
||||
|
||||
class AddGasSwitch : public EventBase {
|
||||
|
@ -100,8 +96,8 @@ private:
|
|||
void redoit() override;
|
||||
|
||||
std::vector<int> cylinders; // cylinders that are modified
|
||||
std::vector<std::unique_ptr<event>> eventsToAdd;
|
||||
std::vector<event *> eventsToRemove;
|
||||
std::vector<event> eventsToAdd;
|
||||
std::vector<int> eventsToRemove;
|
||||
};
|
||||
|
||||
} // namespace Command
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue