From 2453d4fc1fa6c6109645853483839f1e3c87d4a8 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 23 Feb 2020 11:05:19 +0100 Subject: core: introduce clone_cylinder() function We have a clone_weightsystem function. For symmetry, introduce a clone_cylinder() function so that we can more-or-less copy&paste the weightsystem undo code for cylinder undo. Signed-off-by: Berthold Stoeger --- core/equipment.c | 10 ++++++++-- core/equipment.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/equipment.c b/core/equipment.c index c9c0539c3..e96ce0d6a 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -137,12 +137,18 @@ void add_cloned_weightsystem_at(struct weightsystem_table *t, weightsystem_t ws) add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws)); } +cylinder_t clone_cylinder(cylinder_t cyl) +{ + cylinder_t res = cyl; + res.type.description = copy_string(res.type.description); + return res; +} + /* Add a clone of a cylinder to the end of a cylinder table. * Cloned in means that the description-string is copied. */ void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl) { - cyl.type.description = copy_string(cyl.type.description); - add_to_cylinder_table(t, t->nr, cyl); + add_to_cylinder_table(t, t->nr, clone_cylinder(cyl)); } bool same_weightsystem(weightsystem_t w1, weightsystem_t w2) diff --git a/core/equipment.h b/core/equipment.h index b62587447..74f04dfdf 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -75,6 +75,7 @@ extern weightsystem_t clone_weightsystem(weightsystem_t ws); extern void free_weightsystem(weightsystem_t ws); extern void copy_cylinder_types(const struct dive *s, struct dive *d); extern void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws); +extern cylinder_t clone_cylinder(cylinder_t cyl); extern cylinder_t *add_empty_cylinder(struct cylinder_table *t); extern void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl); extern cylinder_t *get_cylinder(const struct dive *d, int idx); -- cgit v1.2.3-70-g09d2 From 1ca25ec03950cea052fd151c41e7d6535cfb1381 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 23 Feb 2020 11:07:51 +0100 Subject: core: make free_cylinder() global The cylinder undo commands will keep a copy of a cylinder and therefore need the ability to free a cylinder object. Signed-off-by: Berthold Stoeger --- core/equipment.c | 2 +- core/equipment.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/equipment.c b/core/equipment.c index e96ce0d6a..4672cbe00 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -29,7 +29,7 @@ void free_weightsystem(weightsystem_t ws) ws.description = NULL; } -static void free_cylinder(cylinder_t c) +void free_cylinder(cylinder_t c) { free((void *)c.type.description); c.type.description = NULL; diff --git a/core/equipment.h b/core/equipment.h index 74f04dfdf..8bc752022 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -76,6 +76,7 @@ extern void free_weightsystem(weightsystem_t ws); extern void copy_cylinder_types(const struct dive *s, struct dive *d); extern void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws); extern cylinder_t clone_cylinder(cylinder_t cyl); +extern void free_cylinder(cylinder_t cyl); extern cylinder_t *add_empty_cylinder(struct cylinder_table *t); extern void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl); extern cylinder_t *get_cylinder(const struct dive *d, int idx); -- cgit v1.2.3-70-g09d2 From f1e08fd470502e5703a7338d6b5a5130a5f41c14 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 23 Feb 2020 11:38:53 +0100 Subject: core: introduce set_cylinder() function We have a set_weightsystem() function. For symmetry, introduce a set_cylinder() function so that we can more-or-less copy&paste the weightsystem undo code for cylinder undo. Signed-off-by: Berthold Stoeger --- core/equipment.c | 9 +++++++++ core/equipment.h | 1 + 2 files changed, 10 insertions(+) (limited to 'core') diff --git a/core/equipment.c b/core/equipment.c index 4672cbe00..3d169a338 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -291,6 +291,15 @@ void remove_cylinder(struct dive *dive, int idx) remove_from_cylinder_table(&dive->cylinders, idx); } +// cyl is cloned. +void set_cylinder(struct dive *dive, int idx, cylinder_t cyl) +{ + if (idx < 0 || idx >= dive->cylinders.nr) + return; + free_cylinder(dive->cylinders.cylinders[idx]); + dive->cylinders.cylinders[idx] = clone_cylinder(cyl); +} + void remove_weightsystem(struct dive *dive, int idx) { remove_from_weightsystem_table(&dive->weightsystems, idx); diff --git a/core/equipment.h b/core/equipment.h index 8bc752022..4ed809eff 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -86,6 +86,7 @@ extern void add_weightsystem_description(const weightsystem_t *); extern bool same_weightsystem(weightsystem_t w1, weightsystem_t w2); extern bool same_cylinder(cylinder_t cyl1, cylinder_t cyl2); extern void remove_cylinder(struct dive *dive, int idx); +extern void set_cylinder(struct dive *dive, int idx, cylinder_t ws); extern void remove_weightsystem(struct dive *dive, int idx); extern void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws); extern void reset_cylinders(struct dive *dive, bool track_gas); -- cgit v1.2.3-70-g09d2 From e008b42a591b83eb1304a552fdd950287ddbc375 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 1 Mar 2020 16:26:47 +0100 Subject: core: add create_new_cylinder() function Turn the code in CylindersModel that creates a new cylinder for addition into its own function to avoid code duplication. This will be used from the undo commands. Signed-off-by: Berthold Stoeger --- core/equipment.c | 10 ++++++++++ core/equipment.h | 1 + qt-models/cylindermodel.cpp | 6 +----- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'core') diff --git a/core/equipment.c b/core/equipment.c index 3d169a338..c3b9fa494 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -392,6 +392,16 @@ cylinder_t *get_or_create_cylinder(struct dive *d, int idx) return &d->cylinders.cylinders[idx]; } +cylinder_t create_new_cylinder(const struct dive *d) +{ + cylinder_t cyl = empty_cylinder; + fill_default_cylinder(d, &cyl); + cyl.start = cyl.type.workingpressure; + cyl.manually_added = true; + cyl.cylinder_use = OC_GAS; + return cyl; +} + #ifdef DEBUG_CYL void dump_cylinders(struct dive *dive, bool verbose) { diff --git a/core/equipment.h b/core/equipment.h index 4ed809eff..289eb75a1 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -92,6 +92,7 @@ extern void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws); extern void reset_cylinders(struct dive *dive, bool track_gas); extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */ extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders); +extern cylinder_t create_new_cylinder(const struct dive *dive); /* dive is needed to fill out MOD, which depends on salinity. */ #ifdef DEBUG_CYL extern void dump_cylinders(struct dive *dive, bool verbose); #endif diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp index da8b2eb1e..428d3c868 100644 --- a/qt-models/cylindermodel.cpp +++ b/qt-models/cylindermodel.cpp @@ -448,11 +448,7 @@ int CylindersModel::rowCount(const QModelIndex&) const void CylindersModel::add() { int row = rows; - cylinder_t cyl = empty_cylinder; - fill_default_cylinder(&displayed_dive, &cyl); - cyl.start = cyl.type.workingpressure; - cyl.manually_added = true; - cyl.cylinder_use = OC_GAS; + cylinder_t cyl = create_new_cylinder(&displayed_dive); beginInsertRows(QModelIndex(), row, row); add_to_cylinder_table(&displayed_dive.cylinders, row, cyl); rows++; -- cgit v1.2.3-70-g09d2 From 36754d3399dab9155fac50e9451dcd325c7c73c0 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Mon, 2 Mar 2020 15:34:56 +0100 Subject: cleanup: move fill_default_cylinder from planner.c to equipment.c Moreover, move the declaration from dive.h to equipment.h. The result is a) more consistent and b) more logical. Signed-off-by: Berthold Stoeger --- core/dive.h | 1 - core/equipment.c | 30 ++++++++++++++++++++++++++++++ core/equipment.h | 1 + core/planner.c | 31 ------------------------------- 4 files changed, 31 insertions(+), 32 deletions(-) (limited to 'core') diff --git a/core/dive.h b/core/dive.h index 1e5ca873d..76eccb5e8 100644 --- a/core/dive.h +++ b/core/dive.h @@ -376,7 +376,6 @@ extern void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_ extern void copy_samples(const struct divecomputer *s, struct divecomputer *d); extern bool is_cylinder_used(const struct dive *dive, int idx); extern bool is_cylinder_prot(const struct dive *dive, int idx); -extern void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl); extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int time, int idx); extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name); extern void remove_event(struct event *event); diff --git a/core/equipment.c b/core/equipment.c index c3b9fa494..24d1d826b 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -392,6 +392,36 @@ cylinder_t *get_or_create_cylinder(struct dive *d, int idx) return &d->cylinders.cylinders[idx]; } +/* if a default cylinder is set, use that */ +void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl) +{ + const char *cyl_name = prefs.default_cylinder; + struct tank_info_t *ti = tank_info; + pressure_t pO2 = {.mbar = 1600}; + + if (!cyl_name) + return; + while (ti->name != NULL && ti < tank_info + MAX_TANK_INFO) { + if (strcmp(ti->name, cyl_name) == 0) + break; + ti++; + } + if (ti->name == NULL) + /* didn't find it */ + return; + cyl->type.description = strdup(ti->name); + if (ti->ml) { + cyl->type.size.mliter = ti->ml; + cyl->type.workingpressure.mbar = ti->bar * 1000; + } else { + cyl->type.workingpressure.mbar = psi_to_mbar(ti->psi); + if (ti->psi) + cyl->type.size.mliter = lrint(cuft_to_l(ti->cuft) * 1000 / bar_to_atm(psi_to_bar(ti->psi))); + } + // MOD of air + cyl->depth = gas_mod(cyl->gasmix, pO2, dive, 1); +} + cylinder_t create_new_cylinder(const struct dive *d) { cylinder_t cyl = empty_cylinder; diff --git a/core/equipment.h b/core/equipment.h index 289eb75a1..494f8dc2b 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -92,6 +92,7 @@ extern void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws); extern void reset_cylinders(struct dive *dive, bool track_gas); extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */ extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders); +extern void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl); /* dive is needed to fill out MOD, which depends on salinity. */ extern cylinder_t create_new_cylinder(const struct dive *dive); /* dive is needed to fill out MOD, which depends on salinity. */ #ifdef DEBUG_CYL extern void dump_cylinders(struct dive *dive, bool verbose); diff --git a/core/planner.c b/core/planner.c index 0e26a9a57..204958a7e 100644 --- a/core/planner.c +++ b/core/planner.c @@ -175,37 +175,6 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, struct deco_s return surface_interval; } - -/* if a default cylinder is set, use that */ -void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl) -{ - const char *cyl_name = prefs.default_cylinder; - struct tank_info_t *ti = tank_info; - pressure_t pO2 = {.mbar = 1600}; - - if (!cyl_name) - return; - while (ti->name != NULL && ti < tank_info + MAX_TANK_INFO) { - if (strcmp(ti->name, cyl_name) == 0) - break; - ti++; - } - if (ti->name == NULL) - /* didn't find it */ - return; - cyl->type.description = strdup(ti->name); - if (ti->ml) { - cyl->type.size.mliter = ti->ml; - cyl->type.workingpressure.mbar = ti->bar * 1000; - } else { - cyl->type.workingpressure.mbar = psi_to_mbar(ti->psi); - if (ti->psi) - cyl->type.size.mliter = lrint(cuft_to_l(ti->cuft) * 1000 / bar_to_atm(psi_to_bar(ti->psi))); - } - // MOD of air - cyl->depth = gas_mod(cyl->gasmix, pO2, dive, 1); -} - /* calculate the new end pressure of the cylinder, based on its current end pressure and the * latest segment. */ static void update_cylinder_pressure(struct dive *d, int old_depth, int new_depth, int duration, int sac, cylinder_t *cyl, bool in_deco, enum divemode_t divemode) -- cgit v1.2.3-70-g09d2 From aa7b0cadb2f737e65d490f4ad026f5df09a394f0 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 23 Feb 2020 11:43:50 +0100 Subject: undo: add cylinder undo commands by copy & paste Do a simple copy & paste followed by a simple search & replace to generate cylinder undo commands from weight undo commands. Obviously, this is still missing the necessary code to keep the dive-data consistent after cylinder editing. Signed-off-by: Berthold Stoeger --- commands/command.cpp | 15 +++ commands/command.h | 3 + commands/command_edit.cpp | 180 ++++++++++++++++++++++++++++++++++ commands/command_edit.h | 40 +++++++- core/subsurface-qt/divelistnotifier.h | 3 + 5 files changed, 240 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/commands/command.cpp b/commands/command.cpp index 1fb968778..5d71e6725 100644 --- a/commands/command.cpp +++ b/commands/command.cpp @@ -293,6 +293,21 @@ int editWeight(int index, weightsystem_t ws, bool currentDiveOnly) return execute_edit(new EditWeight(index, ws, currentDiveOnly)); } +int addCylinder(bool currentDiveOnly) +{ + return execute_edit(new AddCylinder(currentDiveOnly)); +} + +int removeCylinder(int index, bool currentDiveOnly) +{ + return execute_edit(new RemoveCylinder(index, currentDiveOnly)); +} + +int editCylinder(int index, cylinder_t cyl, bool currentDiveOnly) +{ + return execute_edit(new EditCylinder(index, cyl, currentDiveOnly)); +} + // Trip editing related commands void editTripLocation(dive_trip *trip, const QString &s) { diff --git a/commands/command.h b/commands/command.h index e19d093cb..b8024c03d 100644 --- a/commands/command.h +++ b/commands/command.h @@ -90,6 +90,9 @@ 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); +int addCylinder(bool currentDiveOnly); +int removeCylinder(int index, bool currentDiveOnly); +int editCylinder(int index, cylinder_t cyl, 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! diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index 46c206c98..c06ef1ffa 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -8,6 +8,7 @@ #include "core/subsurface-string.h" #include "core/tag.h" #include "qt-models/weightsysteminfomodel.h" +#include "qt-models/tankinfomodel.h" #ifdef SUBSURFACE_MOBILE #include "qt-models/divelocationmodel.h" #endif @@ -917,6 +918,7 @@ bool EditWeightBase::workToBeDone() return !dives.empty(); } +// ***** Remove Weight ***** RemoveWeight::RemoveWeight(int index, bool currentDiveOnly) : EditWeightBase(index, currentDiveOnly) { @@ -943,6 +945,7 @@ void RemoveWeight::redo() } } +// ***** Edit Weight ***** EditWeight::EditWeight(int index, weightsystem_t wsIn, bool currentDiveOnly) : EditWeightBase(index, currentDiveOnly), new_ws(empty_weightsystem) @@ -999,6 +1002,183 @@ void EditWeight::undo() redo(); } +// ***** Add Cylinder ***** +AddCylinder::AddCylinder(bool currentDiveOnly) : + EditDivesBase(currentDiveOnly), + cyl(empty_cylinder) +{ + if (dives.empty()) + return; + else if (dives.size() == 1) + setText(tr("Add cylinder")); + else + setText(tr("Add cylinder (%n dive(s))", "", dives.size())); + cyl = create_new_cylinder(dives[0]); +} + +AddCylinder::~AddCylinder() +{ + free_cylinder(cyl); +} + +bool AddCylinder::workToBeDone() +{ + return true; +} + +void AddCylinder::undo() +{ + for (dive *d: dives) { + if (d->cylinders.nr <= 0) + continue; + remove_cylinder(d, d->cylinders.nr - 1); + emit diveListNotifier.cylinderRemoved(d, d->cylinders.nr); + } +} + +void AddCylinder::redo() +{ + for (dive *d: dives) { + add_cloned_cylinder(&d->cylinders, cyl); + emit diveListNotifier.cylinderAdded(d, d->cylinders.nr - 1); + } +} + +static int find_cylinder_index(const struct dive *d, const cylinder_t &cyl) +{ + for (int idx = 0; idx < d->cylinders.nr; ++idx) { + if (same_cylinder(d->cylinders.cylinders[idx], cyl)) + return idx; + } + return -1; +} + +EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly) : + EditDivesBase(currentDiveOnly), + cyl(empty_cylinder) +{ + // Get the old cylinder, bail if index is invalid + if (!current || index < 0 || index >= current->cylinders.nr) { + dives.clear(); + return; + } + cyl = clone_cylinder(current->cylinders.cylinders[index]); + + std::vector divesNew; + divesNew.reserve(dives.size()); + indexes.reserve(dives.size()); + + for (dive *d: dives) { + if (d == current) { + divesNew.push_back(d); + indexes.push_back(index); + continue; + } + int idx = find_cylinder_index(d, cyl); + if (idx >= 0) { + divesNew.push_back(d); + indexes.push_back(idx); + } + } + dives = std::move(divesNew); +} + +EditCylinderBase::~EditCylinderBase() +{ + free_cylinder(cyl); +} + +bool EditCylinderBase::workToBeDone() +{ + return !dives.empty(); +} + +// ***** Remove Cylinder ***** +RemoveCylinder::RemoveCylinder(int index, bool currentDiveOnly) : + EditCylinderBase(index, currentDiveOnly) +{ + if (dives.size() == 1) + setText(tr("Remove cylinder")); + else + setText(tr("Remove cylinder (%n dive(s))", "", dives.size())); +} + +void RemoveCylinder::undo() +{ + for (size_t i = 0; i < dives.size(); ++i) { + add_to_cylinder_table(&dives[i]->cylinders, indexes[i], clone_cylinder(cyl)); + emit diveListNotifier.cylinderAdded(dives[i], indexes[i]); + } +} + +void RemoveCylinder::redo() +{ + for (size_t i = 0; i < dives.size(); ++i) { + remove_cylinder(dives[i], indexes[i]); + emit diveListNotifier.cylinderRemoved(dives[i], indexes[i]); + } +} + +// ***** Edit Cylinder ***** +EditCylinder::EditCylinder(int index, cylinder_t cylIn, bool currentDiveOnly) : + EditCylinderBase(index, currentDiveOnly), + new_cyl(empty_cylinder) +{ + if (dives.empty()) + return; + + if (dives.size() == 1) + setText(tr("Edit cylinder")); + else + setText(tr("Edit cylinder (%n dive(s))", "", dives.size())); + + // Try to untranslate the cylinder type + new_cyl = clone_cylinder(cylIn); + QString vString(new_cyl.type.description); + for (int i = 0; i < MAX_TANK_INFO && tank_info[i].name; ++i) { + if (gettextFromC::tr(tank_info[i].name) == vString) { + free_cylinder(new_cyl); + new_cyl.type.description = copy_string(tank_info[i].name); + break; + } + } + + // If that doesn't change anything, do nothing + if (same_cylinder(cyl, new_cyl)) { + dives.clear(); + return; + } + + TankInfoModel *tim = TankInfoModel::instance(); + QModelIndexList matches = tim->match(tim->index(0, 0), Qt::DisplayRole, gettextFromC::tr(new_cyl.type.description)); + if (!matches.isEmpty()) { + if (new_cyl.type.size.mliter != cyl.type.size.mliter) + tim->setData(tim->index(matches.first().row(), TankInfoModel::ML), new_cyl.type.size.mliter); + if (new_cyl.type.workingpressure.mbar != cyl.type.workingpressure.mbar) + tim->setData(tim->index(matches.first().row(), TankInfoModel::BAR), new_cyl.type.workingpressure.mbar / 1000.0); + } +} + +EditCylinder::~EditCylinder() +{ + free_cylinder(new_cyl); +} + +void EditCylinder::redo() +{ + for (size_t i = 0; i < dives.size(); ++i) { + set_cylinder(dives[i], indexes[i], new_cyl); + emit diveListNotifier.cylinderEdited(dives[i], indexes[i]); + } + std::swap(cyl, new_cyl); +} + +// Undo and redo do the same as just the stored value is exchanged +void EditCylinder::undo() +{ + redo(); +} + #ifdef SUBSURFACE_MOBILE EditDive::EditDive(dive *oldDiveIn, dive *newDiveIn, dive_site *createDs, dive_site *editDs, location_t dsLocationIn) diff --git a/commands/command_edit.h b/commands/command_edit.h index e99ce2407..88f359fba 100644 --- a/commands/command_edit.h +++ b/commands/command_edit.h @@ -377,6 +377,45 @@ private: void redo() override; }; +class AddCylinder : public EditDivesBase { +public: + AddCylinder(bool currentDiveOnly); + ~AddCylinder(); +private: + cylinder_t cyl; + void undo() override; + void redo() override; + bool workToBeDone() override; +}; + +class EditCylinderBase : public EditDivesBase { +protected: + EditCylinderBase(int index, bool currentDiveOnly); + ~EditCylinderBase(); + + cylinder_t cyl; + std::vector indexes; // An index for each dive in the dives vector. + bool workToBeDone() override; +}; + +class RemoveCylinder : public EditCylinderBase { +public: + RemoveCylinder(int index, bool currentDiveOnly); +private: + void undo() override; + void redo() override; +}; + +class EditCylinder : public EditCylinderBase { +public: + EditCylinder(int index, cylinder_t cyl, bool currentDiveOnly); // Clones cylinder + ~EditCylinder(); +private: + cylinder_t new_cyl; + void undo() override; + 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. @@ -406,5 +445,4 @@ private: #endif // SUBSURFACE_MOBILE } // namespace Command - #endif diff --git a/core/subsurface-qt/divelistnotifier.h b/core/subsurface-qt/divelistnotifier.h index aafe29c0c..2a72cdf49 100644 --- a/core/subsurface-qt/divelistnotifier.h +++ b/core/subsurface-qt/divelistnotifier.h @@ -87,6 +87,9 @@ signals: void divesTimeChanged(timestamp_t delta, const QVector &dives); void cylindersReset(const QVector &dives); + void cylinderAdded(dive *d, int pos); + void cylinderRemoved(dive *d, int pos); + void cylinderEdited(dive *d, int pos); void weightsystemsReset(const QVector &dives); void weightAdded(dive *d, int pos); void weightRemoved(dive *d, int pos); -- cgit v1.2.3-70-g09d2 From 5b7a3165932d9b3fced80fec17de01eb1ad89bf7 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 23 Feb 2020 19:24:06 +0100 Subject: undo: reorder cylinders on remove-cylinder undo/redo The cylinders in the events must be reordered if we remove a cylinder. To avoid duplication of code, move the reordering function into qthelper.cpp, though it might not be ideal there. Signed-off-by: Berthold Stoeger --- commands/command_edit.cpp | 3 +++ core/qthelper.cpp | 33 +++++++++++++++++++++++++++++++++ core/qthelper.h | 2 ++ qt-models/cylindermodel.cpp | 10 +--------- 4 files changed, 39 insertions(+), 9 deletions(-) (limited to 'core') diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index c06ef1ffa..3ba7a2823 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -1106,6 +1106,7 @@ RemoveCylinder::RemoveCylinder(int index, bool currentDiveOnly) : void RemoveCylinder::undo() { for (size_t i = 0; i < dives.size(); ++i) { + std::vector mapping = get_cylinder_map_for_add(dives[i]->cylinders.nr, indexes[i]); add_to_cylinder_table(&dives[i]->cylinders, indexes[i], clone_cylinder(cyl)); emit diveListNotifier.cylinderAdded(dives[i], indexes[i]); } @@ -1114,7 +1115,9 @@ void RemoveCylinder::undo() void RemoveCylinder::redo() { for (size_t i = 0; i < dives.size(); ++i) { + std::vector mapping = get_cylinder_map_for_remove(dives[i]->cylinders.nr, indexes[i]); remove_cylinder(dives[i], indexes[i]); + cylinder_renumber(dives[i], &mapping[0]); emit diveListNotifier.cylinderRemoved(dives[i], indexes[i]); } } diff --git a/core/qthelper.cpp b/core/qthelper.cpp index 7b879e7d6..10e62eabe 100644 --- a/core/qthelper.cpp +++ b/core/qthelper.cpp @@ -1661,3 +1661,36 @@ extern "C" char *get_changes_made() else return nullptr; } + +// Generate a cylinder-renumber map for use when the n-th cylinder +// of a dive with count cylinders is removed. It fills an int vector +// with 0..n, -1, n..count-1. Each entry in the vector represents +// the new id of the cylinder, whereby <0 means that this particular +// cylinder does not get any new id. This should probably be moved +// to the C-core, but using std::vector is simply more convenient. +// The function assumes that n < count! +std::vector get_cylinder_map_for_remove(int count, int n) +{ + // 1) Fill mapping[0]..mapping[n-1] with 0..n-1 + // 2) Set mapping[n] to -1 + // 3) Fill mapping[n+1]..mapping[count-1] with n..count-2 + std::vector mapping(count); + std::iota(mapping.begin(), mapping.begin() + n, 0); + mapping[n] = -1; + std::iota(mapping.begin() + n + 1, mapping.end(), n); + return mapping; +} + +// Generate a cylinder-renumber map for use when a cylinder is added +// before the n-th cylinder. It fills an int vector with +// with 0..n-1, n+1..count. Each entry in the vector represents +// the new id of the cylinder. This probably should be moved +// to the C-core, but using std::vector is simply more convenient. +// This function assumes that that n <= count! +std::vector get_cylinder_map_for_add(int count, int n) +{ + std::vector mapping(count); + std::iota(mapping.begin(), mapping.begin() + n, 0); + std::iota(mapping.begin() + n, mapping.end(), n + 1); + return mapping; +} diff --git a/core/qthelper.h b/core/qthelper.h index bb8876383..848763138 100644 --- a/core/qthelper.h +++ b/core/qthelper.h @@ -83,6 +83,8 @@ QLocale getLocale(); QVector> selectedDivesGasUsed(); QString getUserAgent(); QString printGPSCoords(const location_t *loc); +std::vector get_cylinder_map_for_remove(int count, int n); +std::vector get_cylinder_map_for_add(int count, int n); extern QString (*changesCallback)(); void uiNotification(const QString &msg); diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp index 4b329eafe..3a3f14605 100644 --- a/qt-models/cylindermodel.cpp +++ b/qt-models/cylindermodel.cpp @@ -513,15 +513,7 @@ void CylindersModel::remove(QModelIndex index) changed = true; endRemoveRows(); - // Create a mapping of cylinder indices: - // 1) Fill mapping[0]..mapping[index-1] with 0..index - // 2) Set mapping[index] to -1 - // 3) Fill mapping[index+1]..mapping[end] with index.. - std::vector mapping(d->cylinders.nr + 1); - std::iota(mapping.begin(), mapping.begin() + index.row(), 0); - mapping[index.row()] = -1; - std::iota(mapping.begin() + index.row() + 1, mapping.end(), index.row()); - + std::vector mapping = get_cylinder_map_for_remove(d->cylinders.nr + 1, index.row()); cylinder_renumber(d, &mapping[0]); if (in_planner()) DivePlannerPointsModel::instance()->cylinderRenumber(&mapping[0]); -- cgit v1.2.3-70-g09d2 From dee7fd9f308caae16045038b67dedd604a4d0ac2 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Mon, 2 Mar 2020 21:32:12 +0100 Subject: cleanup: use SAMPLE_EVENT_BOOKMARK in add_event() calls In two cases we were passing the magic value 8 instead of the symbolic SAMPLE_EVENT_BOOKMARK. Use the symbolic version instead. Signed-off-by: Berthold Stoeger --- core/planner.c | 2 +- profile-widget/profilewidget2.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/planner.c b/core/planner.c index 204958a7e..a5f0d36bc 100644 --- a/core/planner.c +++ b/core/planner.c @@ -284,7 +284,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, } if (dp->divemode != type) { type = dp->divemode; - add_event(dc, lasttime, 8, 0, type, "modechange"); + add_event(dc, lasttime, SAMPLE_EVENT_BOOKMARK, 0, type, "modechange"); } /* Create sample */ diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index 1b74f9d88..43ebf0777 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -1653,7 +1653,7 @@ void ProfileWidget2::addDivemodeSwitch() QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint())); for (i = 0; i < NUM_DIVEMODE; i++) if (gettextFromC::tr(divemode_text_ui[i]) == action->text()) - add_event(current_dc, lrint(timeAxis->valueAt(scenePos)), 8, 0, i, + add_event(current_dc, lrint(timeAxis->valueAt(scenePos)), SAMPLE_EVENT_BOOKMARK, 0, i, QT_TRANSLATE_NOOP("gettextFromC", "modechange")); invalidate_dive_cache(current_dive); mark_divelist_changed(true); -- cgit v1.2.3-70-g09d2 From 2417a54675011885c699dbe8a77a427effcb26c5 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Tue, 3 Mar 2020 20:03:56 +0100 Subject: core: split add_event() in two parts add_event() creates and adds an event from the given parameters. For undo, we want to do these separately, therefore split this function in two parts: create_event() and add_event_to_dc(). Keep the add_event() function for convenience. Moreover, keep the remember_event() call in there, so that undo-commands can call remember_event() once, not on every undo/redo action. Signed-off-by: Berthold Stoeger --- core/dive.c | 24 +++++++++++++++++++++--- core/dive.h | 2 ++ 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/dive.c b/core/dive.c index ffdf91ae3..25084a554 100644 --- a/core/dive.c +++ b/core/dive.c @@ -125,10 +125,10 @@ int event_is_gaschange(const struct event *ev) ev->type == SAMPLE_EVENT_GASCHANGE2; } -struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name) +struct event *create_event(unsigned int time, int type, int flags, int value, const char *name) { int gas_index = -1; - struct event *ev, **p; + struct event *ev; unsigned int size, len = strlen(name); size = sizeof(*ev) + len + 1; @@ -163,13 +163,31 @@ struct event *add_event(struct divecomputer *dc, unsigned int time, int type, in break; } + return ev; +} + +void add_event_to_dc(struct divecomputer *dc, struct event *ev) +{ + struct event **p; + p = &dc->events; /* insert in the sorted list of events */ - while (*p && (*p)->time.seconds <= time) + while (*p && (*p)->time.seconds <= ev->time.seconds) p = &(*p)->next; ev->next = *p; *p = ev; +} + +struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name) +{ + struct event *ev = create_event(time, type, flags, value, name); + + if (!ev) + return NULL; + + add_event_to_dc(dc, ev); + remember_event(name); return ev; } diff --git a/core/dive.h b/core/dive.h index 76eccb5e8..5bbce4b00 100644 --- a/core/dive.h +++ b/core/dive.h @@ -377,6 +377,8 @@ extern void copy_samples(const struct divecomputer *s, struct divecomputer *d); 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 void add_event_to_dc(struct divecomputer *dc, struct event *ev); extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name); extern void remove_event(struct event *event); extern void update_event_name(struct dive *d, struct event *event, const char *name); -- cgit v1.2.3-70-g09d2 From 3aa1bb5bfae9a7ebf8f5e6cdbf751afcafdb4baf Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Tue, 3 Mar 2020 21:48:08 +0100 Subject: core: add remove_event_from_dc() function We have a remove_event() function that 1) frees the event 2) works on the current divecomputer 3) compares the events because the profile has copies of events However, for undo commands 1) we want to keep the event so that we can readd it later 2) we have to work on arbitrary divecomputers 3) we don't work with copies of events Therefore, create a new remove_event_from_dc() function that does all that. Moreover, make the event argument to remove_event() const to (slightly) point out the difference in the API. Signed-off-by: Berthold Stoeger --- core/dive.c | 16 +++++++++++++++- core/dive.h | 3 ++- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/dive.c b/core/dive.c index 25084a554..3ec9b1a82 100644 --- a/core/dive.c +++ b/core/dive.c @@ -205,7 +205,21 @@ static int same_event(const struct event *a, const struct event *b) return !strcmp(a->name, b->name); } -void remove_event(struct event *event) +/* Remove given event from dive computer. Does *not* free the event. */ +void remove_event_from_dc(struct divecomputer *dc, struct event *event) +{ + for (struct event **ep = &dc->events; *ep; ep = &(*ep)->next) { + if (*ep == event) { + *ep = event->next; + event->next = NULL; // For good measure. + break; + } + } +} + +/* Remove an event from current dive computer that is identical to the passed in event. + * Frees the event. */ +void remove_event(const struct event *event) { struct event **ep = ¤t_dc->events; while (ep && !same_event(*ep, event)) diff --git a/core/dive.h b/core/dive.h index 5bbce4b00..1de68f4ff 100644 --- a/core/dive.h +++ b/core/dive.h @@ -380,7 +380,8 @@ extern void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int extern struct event *create_event(unsigned int time, int type, int flags, int value, const char *name); extern void add_event_to_dc(struct divecomputer *dc, struct event *ev); extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const char *name); -extern void remove_event(struct event *event); +extern void remove_event_from_dc(struct divecomputer *dc, struct event *event); +extern void remove_event(const struct event *event); extern void update_event_name(struct dive *d, struct event *event, const char *name); extern void add_extra_data(struct divecomputer *dc, const char *key, const char *value); extern void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration); -- cgit v1.2.3-70-g09d2 From 7018783f64f664af97032da4ba4d357c05b52aaf Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Tue, 3 Mar 2020 22:42:51 +0100 Subject: undo: replot profile if event changed Add a DiveListNotifer::eventsChanged signal, which is emitted when the events changed. This is very coarse, at it doesn't differentiate between signal addition / editing / deletion. We might want to be finer in the future. Catch the signal in the profile-widget to replot the dive if this is the currently displayed dive. Reuse the cylindersChanged() slot, but rename it to the now more appropriate profileChanged(). Signed-off-by: Berthold Stoeger --- commands/command_event.cpp | 2 ++ core/subsurface-qt/divelistnotifier.h | 3 +++ profile-widget/profilewidget2.cpp | 5 +++-- profile-widget/profilewidget2.h | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/commands/command_event.cpp b/commands/command_event.cpp index ea35402e4..d945fbb02 100644 --- a/commands/command_event.cpp +++ b/commands/command_event.cpp @@ -23,6 +23,7 @@ void AddEventBase::redo() eventToRemove = eventToAdd.get(); add_event_to_dc(dc, eventToAdd.release()); // return ownership to backend invalidate_dive_cache(d); + emit diveListNotifier.eventsChanged(d); } void AddEventBase::undo() @@ -32,6 +33,7 @@ void AddEventBase::undo() eventToAdd.reset(eventToRemove); // take ownership of event eventToRemove = nullptr; invalidate_dive_cache(d); + emit diveListNotifier.eventsChanged(d); } AddEventBookmark::AddEventBookmark(struct dive *d, int dcNr, int seconds) : diff --git a/core/subsurface-qt/divelistnotifier.h b/core/subsurface-qt/divelistnotifier.h index 2a72cdf49..63355fbcc 100644 --- a/core/subsurface-qt/divelistnotifier.h +++ b/core/subsurface-qt/divelistnotifier.h @@ -113,6 +113,9 @@ signals: void numShownChanged(); void filterReset(); + // Event-related signals. Currently, we're very blunt: only one signal for any changes to the events. + void eventsChanged(dive *d); + // This signal is emited every time a command is executed. // This is used to hide an old multi-dives-edited warning message. // This is necessary, so that the user can't click on the "undo" button and undo diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index 67962b3bb..54881f71a 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -170,7 +170,8 @@ ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent), connect(DivePictureModel::instance(), &DivePictureModel::rowsInserted, this, &ProfileWidget2::plotPictures); connect(DivePictureModel::instance(), &DivePictureModel::picturesRemoved, this, &ProfileWidget2::removePictures); connect(DivePictureModel::instance(), &DivePictureModel::modelReset, this, &ProfileWidget2::plotPictures); - connect(&diveListNotifier, &DiveListNotifier::cylinderEdited, this, &ProfileWidget2::cylinderChanged); + connect(&diveListNotifier, &DiveListNotifier::cylinderEdited, this, &ProfileWidget2::profileChanged); + connect(&diveListNotifier, &DiveListNotifier::eventsChanged, this, &ProfileWidget2::profileChanged); #endif // SUBSURFACE_MOBILE #if !defined(QT_NO_DEBUG) && defined(SHOW_PLOT_INFO_TABLE) @@ -2189,7 +2190,7 @@ void ProfileWidget2::removePictures(const QVector &fileUrls) calculatePictureYPositions(); } -void ProfileWidget2::cylinderChanged(dive *d) +void ProfileWidget2::profileChanged(dive *d) { if (!d || d->id != displayed_dive.id) return; // Cylinders of a differnt dive than the shown one changed. diff --git a/profile-widget/profilewidget2.h b/profile-widget/profilewidget2.h index 0c1db3f62..4f60bf885 100644 --- a/profile-widget/profilewidget2.h +++ b/profile-widget/profilewidget2.h @@ -118,7 +118,7 @@ slots: // Necessary to call from QAction's signals. void pointInserted(const QModelIndex &parent, int start, int end); void pointsRemoved(const QModelIndex &, int start, int end); void updateThumbnail(QString filename, QImage thumbnail, duration_t duration); - void cylinderChanged(dive *d); + void profileChanged(dive *d); /* this is called for every move on the handlers. maybe we can speed up this a bit? */ void recreatePlannedDive(); -- cgit v1.2.3-70-g09d2 From ab8e317b28672cc19fd04e994b9adf9b63f0c603 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Wed, 4 Mar 2020 18:13:02 +0100 Subject: 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 --- commands/command.cpp | 5 +++++ commands/command.h | 1 + commands/command_event.cpp | 27 +++++++++++++++++++++++++++ commands/command_event.h | 12 ++++++++++++ core/dive.c | 20 +++++++++++++++++++- core/dive.h | 3 +++ profile-widget/profilewidget2.cpp | 29 ++++++++++++++++++++--------- 7 files changed, 87 insertions(+), 10 deletions(-) (limited to 'core') 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 -- cgit v1.2.3-70-g09d2 From b1906dd04f0162619df5710cde9248aa4b342a2b Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Wed, 4 Mar 2020 19:29:59 +0100 Subject: cleanup: move add_gas_switch_event to dive.c Since all the other event-functions are also defined there. Ultimately, we should probably move them to their own event.c translation unit. Signed-off-by: Berthold Stoeger --- core/dive.c | 26 ++++++++++++++++++++++++++ core/parse-xml.c | 25 ------------------------- 2 files changed, 26 insertions(+), 25 deletions(-) (limited to 'core') diff --git a/core/dive.c b/core/dive.c index 6d2645cef..d46f2de1d 100644 --- a/core/dive.c +++ b/core/dive.c @@ -11,6 +11,7 @@ #include "device.h" #include "divelist.h" #include "divesite.h" +#include "errorhelper.h" #include "qthelper.h" #include "metadata.h" #include "membuffer.h" @@ -197,6 +198,31 @@ struct event *add_event(struct divecomputer *dc, unsigned int time, int type, in return ev; } +void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx) +{ + /* sanity check so we don't crash */ + if (idx < 0 || idx >= dive->cylinders.nr) { + report_error("Unknown cylinder index: %d", idx); + return; + } + /* The gas switch event format is insane for historical reasons */ + struct gasmix mix = get_cylinder(dive, idx)->gasmix; + int o2 = get_o2(mix); + int he = get_he(mix); + struct event *ev; + int value; + + o2 = (o2 + 5) / 10; + he = (he + 5) / 10; + value = o2 + (he << 16); + + ev = add_event(dc, seconds, he ? SAMPLE_EVENT_GASCHANGE2 : SAMPLE_EVENT_GASCHANGE, 0, value, "gaschange"); + if (ev) { + ev->gas.index = idx; + ev->gas.mix = mix; + } +} + /* Substitutes an event in a divecomputer for another. No reordering is performed! */ void swap_event(struct divecomputer *dc, struct event *from, struct event *to) { diff --git a/core/parse-xml.c b/core/parse-xml.c index 6218fc74d..2f3d7a283 100644 --- a/core/parse-xml.c +++ b/core/parse-xml.c @@ -697,31 +697,6 @@ static void try_to_match_autogroup(const char *name, char *buf) nonmatch("autogroup", name, buf); } -void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx) -{ - /* sanity check so we don't crash */ - if (idx < 0 || idx >= dive->cylinders.nr) { - report_error("Unknown cylinder index: %d", idx); - return; - } - /* The gas switch event format is insane for historical reasons */ - struct gasmix mix = get_cylinder(dive, idx)->gasmix; - int o2 = get_o2(mix); - int he = get_he(mix); - struct event *ev; - int value; - - o2 = (o2 + 5) / 10; - he = (he + 5) / 10; - value = o2 + (he << 16); - - ev = add_event(dc, seconds, he ? SAMPLE_EVENT_GASCHANGE2 : SAMPLE_EVENT_GASCHANGE, 0, value, "gaschange"); - if (ev) { - ev->gas.index = idx; - ev->gas.mix = mix; - } -} - static void get_cylinderindex(char *buffer, uint8_t *i, struct parser_state *state) { *i = atoi(buffer); -- cgit v1.2.3-70-g09d2 From 9fe1951db29a3470e525c9a4e03612d6f7d5ecbb Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Wed, 4 Mar 2020 19:41:40 +0100 Subject: core: split out create_gas_change_event() from add_gas_change_event() For undo, we want to create gas change events without adding them immediately to the dive computer. Signed-off-by: Berthold Stoeger --- core/dive.c | 38 ++++++++++++++++++++++---------------- core/dive.h | 1 + 2 files changed, 23 insertions(+), 16 deletions(-) (limited to 'core') diff --git a/core/dive.c b/core/dive.c index d46f2de1d..849425389 100644 --- a/core/dive.c +++ b/core/dive.c @@ -167,6 +167,26 @@ struct event *create_event(unsigned int time, int type, int flags, int value, co return ev; } +/* warning: does not test idx for validity */ +struct event *create_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx) +{ + /* The gas switch event format is insane for historical reasons */ + struct gasmix mix = get_cylinder(dive, idx)->gasmix; + int o2 = get_o2(mix); + int he = get_he(mix); + struct event *ev; + int value; + + o2 = (o2 + 5) / 10; + he = (he + 5) / 10; + value = o2 + (he << 16); + + ev = create_event(seconds, he ? SAMPLE_EVENT_GASCHANGE2 : SAMPLE_EVENT_GASCHANGE, 0, value, "gaschange"); + ev->gas.index = idx; + ev->gas.mix = mix; + 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); @@ -205,22 +225,8 @@ void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int second report_error("Unknown cylinder index: %d", idx); return; } - /* The gas switch event format is insane for historical reasons */ - struct gasmix mix = get_cylinder(dive, idx)->gasmix; - int o2 = get_o2(mix); - int he = get_he(mix); - struct event *ev; - int value; - - o2 = (o2 + 5) / 10; - he = (he + 5) / 10; - value = o2 + (he << 16); - - ev = add_event(dc, seconds, he ? SAMPLE_EVENT_GASCHANGE2 : SAMPLE_EVENT_GASCHANGE, 0, value, "gaschange"); - if (ev) { - ev->gas.index = idx; - ev->gas.mix = mix; - } + struct event *ev = create_gas_switch_event(dive, dc, seconds, idx); + add_event_to_dc(dc, ev); } /* Substitutes an event in a divecomputer for another. No reordering is performed! */ diff --git a/core/dive.h b/core/dive.h index 727d4bbff..2f4e96504 100644 --- a/core/dive.h +++ b/core/dive.h @@ -378,6 +378,7 @@ 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 *create_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx); 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); -- cgit v1.2.3-70-g09d2 From c585fd9f8ee0c1f27f997b4e19984b50d150f6cb Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Wed, 4 Mar 2020 19:43:18 +0100 Subject: cleanup: remove vintage report_error() function declaration Remove an old commented-out declaration. Signed-off-by: Berthold Stoeger --- core/dive.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'core') diff --git a/core/dive.h b/core/dive.h index 2f4e96504..77e6973c9 100644 --- a/core/dive.h +++ b/core/dive.h @@ -396,8 +396,6 @@ extern int nr_weightsystems(const struct dive *dive); /* UI related protopypes */ -// extern void report_error(GError* error); - extern void remember_event(const char *eventname); extern void invalidate_dive_cache(struct dive *dc); -- cgit v1.2.3-70-g09d2 From 7081674b672b23b6c22feb4bae94cb3febf3fe1c Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Wed, 4 Mar 2020 21:40:45 +0100 Subject: cleanup: remove remove_event() function No user left. Signed-off-by: Berthold Stoeger --- core/dive.c | 18 ------------------ core/dive.h | 1 - 2 files changed, 19 deletions(-) (limited to 'core') diff --git a/core/dive.c b/core/dive.c index 849425389..411607926 100644 --- a/core/dive.c +++ b/core/dive.c @@ -267,24 +267,6 @@ void remove_event_from_dc(struct divecomputer *dc, struct event *event) } } -/* Remove an event from current dive computer that is identical to the passed in event. - * Frees the event. */ -void remove_event(const struct event *event) -{ - struct event **ep = ¤t_dc->events; - while (ep && !same_event(*ep, event)) - ep = &(*ep)->next; - if (ep) { - /* we can't link directly with event->next - * because 'event' can be a copy from another - * dive (for instance the displayed_dive - * that we use on the interface to show things). */ - struct event *temp = (*ep)->next; - free(*ep); - *ep = temp; - } -} - /* since the name is an array as part of the structure (how silly is that?) we * have to actually remove the existing event and replace it with a new one. * WARNING, WARNING... this may end up freeing event in case that event is indeed diff --git a/core/dive.h b/core/dive.h index 77e6973c9..829575194 100644 --- a/core/dive.h +++ b/core/dive.h @@ -385,7 +385,6 @@ extern void swap_event(struct divecomputer *dc, struct event *from, struct event 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); extern void update_event_name(struct dive *d, struct event *event, const char *name); extern void add_extra_data(struct divecomputer *dc, const char *key, const char *value); extern void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration); -- cgit v1.2.3-70-g09d2 From 48b4dc9c845f147d97c6f7e13582b921654a227c Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Wed, 4 Mar 2020 21:58:46 +0100 Subject: cleanup: remove commented-out evn_foreach() function Apparently this was used to hide events in pre-Qt times. However, that has already been reimplemented in different ways. Let's remove that commented-out code. Signed-off-by: Berthold Stoeger --- core/dive.h | 4 ---- core/profile.c | 13 ------------- 2 files changed, 17 deletions(-) (limited to 'core') diff --git a/core/dive.h b/core/dive.h index 829575194..42c3cdaf9 100644 --- a/core/dive.h +++ b/core/dive.h @@ -398,10 +398,6 @@ extern int nr_weightsystems(const struct dive *dive); extern void remember_event(const char *eventname); extern void invalidate_dive_cache(struct dive *dc); -#if WE_DONT_USE_THIS /* this is a missing feature in Qt - selecting which events to display */ -extern int evn_foreach(void (*callback)(const char *, bool *, void *), void *data); -#endif /* WE_DONT_USE_THIS */ - extern void clear_events(void); extern void set_dc_nickname(struct dive *dive); diff --git a/core/profile.c b/core/profile.c index 88b48d1cd..26488cc30 100644 --- a/core/profile.c +++ b/core/profile.c @@ -120,19 +120,6 @@ struct ev_select *ev_namelist; int evn_allocated; int evn_used; -#if WE_DONT_USE_THIS /* we need to implement event filters in Qt */ -int evn_foreach (void (*callback)(const char *, bool *, void *), void *data) -{ - int i; - - for (i = 0; i < evn_used; i++) { - /* here we display an event name on screen - so translate */ - callback(translate("gettextFromC", ev_namelist[i].ev_name), &ev_namelist[i].plot_ev, data); - } - return i; -} -#endif /* WE_DONT_USE_THIS */ - void clear_events(void) { for (int i = 0; i < evn_used; i++) -- cgit v1.2.3-70-g09d2 From bbd3f0dd6d019245b7708b867e7f4c6522332443 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 15 Mar 2020 19:07:44 +0100 Subject: cylinders: use preferences modpO2 preferences value Use the user-editable MOD-pO2 preferences value when creating a default cylinder. It is not clear to me, when that even has a consequence, but it looks like the right thing to do. Reported-by: Robert C. Helling Signed-off-by: Berthold Stoeger --- core/equipment.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/equipment.c b/core/equipment.c index 24d1d826b..494baf5c1 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -397,7 +397,7 @@ void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl) { const char *cyl_name = prefs.default_cylinder; struct tank_info_t *ti = tank_info; - pressure_t pO2 = {.mbar = 1600}; + pressure_t pO2 = {.mbar = lrint(prefs.modpO2 * 1000.0)}; if (!cyl_name) return; -- cgit v1.2.3-70-g09d2 From 5b65776e4313bb088e3eb3dcb1e8d5732be3b1d0 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sun, 22 Mar 2020 23:58:19 +0100 Subject: cleanup: remove same_cylinder The last user was uses a more general function. Signed-off-by: Berthold Stoeger --- core/equipment.c | 9 --------- core/equipment.h | 1 - 2 files changed, 10 deletions(-) (limited to 'core') diff --git a/core/equipment.c b/core/equipment.c index 494baf5c1..27d01692e 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -157,15 +157,6 @@ bool same_weightsystem(weightsystem_t w1, weightsystem_t w2) same_string(w1.description, w2.description); } -bool same_cylinder(cylinder_t cyl1, cylinder_t cyl2) -{ - return same_string(cyl1.type.description, cyl2.type.description) && - same_gasmix(cyl1.gasmix, cyl2.gasmix) && - cyl1.start.mbar == cyl2.start.mbar && - cyl1.end.mbar == cyl2.end.mbar && - cyl1.cylinder_use == cyl2.cylinder_use; -} - void get_gas_string(struct gasmix gasmix, char *text, int len) { if (gasmix_is_air(gasmix)) diff --git a/core/equipment.h b/core/equipment.h index 494f8dc2b..af410467f 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -84,7 +84,6 @@ extern cylinder_t *get_or_create_cylinder(struct dive *d, int idx); extern void add_cylinder_description(const cylinder_type_t *); extern void add_weightsystem_description(const weightsystem_t *); extern bool same_weightsystem(weightsystem_t w1, weightsystem_t w2); -extern bool same_cylinder(cylinder_t cyl1, cylinder_t cyl2); extern void remove_cylinder(struct dive *dive, int idx); extern void set_cylinder(struct dive *dive, int idx, cylinder_t ws); extern void remove_weightsystem(struct dive *dive, int idx); -- cgit v1.2.3-70-g09d2 From 2eeb5f4fc2d6da8a8c8950f0b479b7cb2055af07 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Fri, 27 Mar 2020 21:09:59 +0100 Subject: undo: more fine-grained editing of cylinder Don't overwrite the full cylinder when editing a single field. Implement three "modes": editing of type, pressure and gasmix. Don't consider individual fields, because some of them are related. E.g. you can change the gasmix by setting the MOD. Signed-off-by: Berthold Stoeger --- commands/command.cpp | 4 ++-- commands/command.h | 7 ++++++- commands/command_edit.cpp | 38 +++++++++++++++++++++++++++++++++----- commands/command_edit.h | 9 ++++++++- core/equipment.c | 9 --------- core/equipment.h | 1 - qt-models/cylindermodel.cpp | 18 +++++++++++++++--- 7 files changed, 64 insertions(+), 22 deletions(-) (limited to 'core') diff --git a/commands/command.cpp b/commands/command.cpp index c173494c0..33c866e72 100644 --- a/commands/command.cpp +++ b/commands/command.cpp @@ -304,9 +304,9 @@ int removeCylinder(int index, bool currentDiveOnly) return execute_edit(new RemoveCylinder(index, currentDiveOnly)); } -int editCylinder(int index, cylinder_t cyl, bool currentDiveOnly) +int editCylinder(int index, cylinder_t cyl, EditCylinderType type, bool currentDiveOnly) { - return execute_edit(new EditCylinder(index, cyl, currentDiveOnly)); + return execute_edit(new EditCylinder(index, cyl, type, currentDiveOnly)); } // Trip editing related commands diff --git a/commands/command.h b/commands/command.h index 66122ac99..fc1ddf582 100644 --- a/commands/command.h +++ b/commands/command.h @@ -92,7 +92,12 @@ int removeWeight(int index, bool currentDiveOnly); int editWeight(int index, weightsystem_t ws, bool currentDiveOnly); int addCylinder(bool currentDiveOnly); int removeCylinder(int index, bool currentDiveOnly); -int editCylinder(int index, cylinder_t cyl, bool currentDiveOnly); +enum class EditCylinderType { + TYPE, + PRESSURE, + GASMIX +}; +int editCylinder(int index, cylinder_t cyl, EditCylinderType type, 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! diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index d5e2d12d0..c81e67394 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -1151,9 +1151,23 @@ void RemoveCylinder::redo() } } +static int editCylinderTypeToFlags(EditCylinderType type) +{ + switch (type) { + default: + case EditCylinderType::TYPE: + return SAME_TYPE | SAME_SIZE; + case EditCylinderType::PRESSURE: + return SAME_PRESS; + case EditCylinderType::GASMIX: + return SAME_GAS; + } +} + // ***** Edit Cylinder ***** -EditCylinder::EditCylinder(int index, cylinder_t cylIn, bool currentDiveOnly) : - EditCylinderBase(index, currentDiveOnly, false, SAME_TYPE | SAME_PRESS | SAME_GAS) +EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn, bool currentDiveOnly) : + EditCylinderBase(index, currentDiveOnly, false, editCylinderTypeToFlags(typeIn)), + type(typeIn) { if (dives.empty()) return; @@ -1184,9 +1198,23 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, bool currentDiveOnly) : // The base class copied the cylinders for us, let's edit them for (int i = 0; i < (int)indexes.size(); ++i) { - free_cylinder(cyl[i]); - cyl[i] = cylIn; - cyl[i].type.description = copy_qstring(description); + switch (type) { + case EditCylinderType::TYPE: + free((void *)cyl[i].type.description); + cyl[i].type = cylIn.type; + cyl[i].type.description = copy_qstring(description); + cyl[i].cylinder_use = cylIn.cylinder_use; + break; + case EditCylinderType::PRESSURE: + cyl[i].start.mbar = cylIn.start.mbar; + cyl[i].end.mbar = cylIn.end.mbar; + break; + case EditCylinderType::GASMIX: + cyl[i].gasmix = cylIn.gasmix; + cyl[i].bestmix_o2 = cylIn.bestmix_o2; + cyl[i].bestmix_he = cylIn.bestmix_he; + break; + } } } diff --git a/commands/command_edit.h b/commands/command_edit.h index d7c31f7f2..ab842a13c 100644 --- a/commands/command_edit.h +++ b/commands/command_edit.h @@ -5,6 +5,7 @@ #define COMMAND_EDIT_H #include "command_base.h" +#include "command.h" // for EditCylinderType #include "core/subsurface-qt/divelistnotifier.h" #include @@ -406,10 +407,16 @@ private: void redo() override; }; +// Instead of implementing an undo command for every single field in a cylinder, +// we only have one and pass an edit "type". We either edit the type, pressure +// or gasmix fields. This has mostly historical reasons rooted in the way the +// CylindersModel code works. The model works for undo and also in the planner +// without undo. Having a single undo-command simplifies the code there. class EditCylinder : public EditCylinderBase { public: - EditCylinder(int index, cylinder_t cyl, bool currentDiveOnly); // Clones cylinder + EditCylinder(int index, cylinder_t cyl, EditCylinderType type, bool currentDiveOnly); // Clones cylinder private: + EditCylinderType type; void undo() override; void redo() override; }; diff --git a/core/equipment.c b/core/equipment.c index 27d01692e..4be46ed1e 100644 --- a/core/equipment.c +++ b/core/equipment.c @@ -282,15 +282,6 @@ void remove_cylinder(struct dive *dive, int idx) remove_from_cylinder_table(&dive->cylinders, idx); } -// cyl is cloned. -void set_cylinder(struct dive *dive, int idx, cylinder_t cyl) -{ - if (idx < 0 || idx >= dive->cylinders.nr) - return; - free_cylinder(dive->cylinders.cylinders[idx]); - dive->cylinders.cylinders[idx] = clone_cylinder(cyl); -} - void remove_weightsystem(struct dive *dive, int idx) { remove_from_weightsystem_table(&dive->weightsystems, idx); diff --git a/core/equipment.h b/core/equipment.h index af410467f..081a13835 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -85,7 +85,6 @@ extern void add_cylinder_description(const cylinder_type_t *); extern void add_weightsystem_description(const weightsystem_t *); extern bool same_weightsystem(weightsystem_t w1, weightsystem_t w2); extern void remove_cylinder(struct dive *dive, int idx); -extern void set_cylinder(struct dive *dive, int idx, cylinder_t ws); extern void remove_weightsystem(struct dive *dive, int idx); extern void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws); extern void reset_cylinders(struct dive *dive, bool track_gas); diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp index 8a79ff1e5..c7e1b186d 100644 --- a/qt-models/cylindermodel.cpp +++ b/qt-models/cylindermodel.cpp @@ -296,7 +296,6 @@ cylinder_t *CylindersModel::cylinderAt(const QModelIndex &index) bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if (!d) return false; @@ -324,6 +323,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in tempCyl.type.description = strdup(qPrintable(type)); dataChanged(index, index); } + return true; } case SIZE: if (tempCyl.type.size.mliter != value.toInt()) { @@ -362,10 +362,12 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in if (index.column() != TYPE && !changed) return false; + Command::EditCylinderType type = Command::EditCylinderType::TYPE; switch (index.column()) { case TYPE: newType = qPrintable(vString); cyl.type.description = newType.c_str(); + type = Command::EditCylinderType::TYPE; break; case SIZE: { TankInfoModel *tanks = TankInfoModel::instance(); @@ -375,6 +377,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in if (!matches.isEmpty()) tanks->setData(tanks->index(matches.first().row(), TankInfoModel::ML), cyl.type.size.mliter); } + type = Command::EditCylinderType::TYPE; break; case WORKINGPRESS: { TankInfoModel *tanks = TankInfoModel::instance(); @@ -383,13 +386,16 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in if (!matches.isEmpty()) tanks->setData(tanks->index(matches.first().row(), TankInfoModel::BAR), cyl.type.workingpressure.mbar / 1000.0); } + type = Command::EditCylinderType::TYPE; break; case START: cyl.start = string_to_pressure(qPrintable(vString)); + type = Command::EditCylinderType::PRESSURE; break; case END: //if (!cyl->start.mbar || string_to_pressure(qPrintable(vString)).mbar <= cyl->start.mbar) { cyl.end = string_to_pressure(qPrintable(vString)); + type = Command::EditCylinderType::PRESSURE; break; case O2: { cyl.gasmix.o2 = string_to_fraction(qPrintable(vString)); @@ -405,6 +411,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in cyl.depth = gas_mod(cyl.gasmix, modpO2, d, M_OR_FT(3, 10)); cyl.bestmix_o2 = false; } + type = Command::EditCylinderType::GASMIX; break; case HE: cyl.gasmix.he = string_to_fraction(qPrintable(vString)); @@ -412,9 +419,11 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in if (get_o2(cyl.gasmix) + get_he(cyl.gasmix) > 1000) cyl.gasmix.o2.permille = 1000 - get_he(cyl.gasmix); cyl.bestmix_he = false; + type = Command::EditCylinderType::GASMIX; break; case DEPTH: cyl.depth = string_to_depth(qPrintable(vString)); + type = Command::EditCylinderType::GASMIX; break; case MOD: { if (QString::compare(qPrintable(vString), "*") == 0) { @@ -430,6 +439,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in modpO2.mbar = prefs.decopo2; cyl.depth = gas_mod(cyl.gasmix, modpO2, d, M_OR_FT(3, 10)); } + type = Command::EditCylinderType::GASMIX; break; case MND: if (QString::compare(qPrintable(vString), "*") == 0) { @@ -441,6 +451,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in // Calculate fHe for input depth cyl.gasmix.he = best_he(string_to_depth(qPrintable(vString)), d, prefs.o2narcotic, cyl.gasmix.o2); } + type = Command::EditCylinderType::GASMIX; break; case USE: { int use = vString.toInt(); @@ -448,6 +459,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in use = 0; cyl.cylinder_use = (enum cylinderuse)use; } + type = Command::EditCylinderType::TYPE; break; } @@ -461,7 +473,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in } else { #ifndef SUBSURFACE_MOBILE // On the EquipmentTab - place an editCylinder command. - Command::editCylinder(index.row(), cyl, false); + Command::editCylinder(index.row(), cyl, type, false); #endif } return true; @@ -709,7 +721,7 @@ void CylindersModel::commitTempCyl(int row) if (inPlanner) std::swap(*cyl, tempCyl); else - Command::editCylinder(tempRow, tempCyl, false); + Command::editCylinder(tempRow, tempCyl, Command::EditCylinderType::TYPE, false); } free_cylinder(tempCyl); tempRow = -1; -- cgit v1.2.3-70-g09d2