summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2019-11-08 22:47:38 +0100
committerGravatar Dirk Hohndel <dirk@hohndel.org>2019-12-05 10:14:25 -0800
commit72c6b838662f1fb79a806ac2264c7215efa0aa67 (patch)
tree8b10fe7ad548a62ed428347c8a35882ee291b41a
parent029c9ccf020fdb73c148da489e0e7b1acd3ca149 (diff)
downloadsubsurface-72c6b838662f1fb79a806ac2264c7215efa0aa67.tar.gz
Undo: make weight editing undoable
Implement the EditWeight undo command. Since there is common code (storage of the old weight), this creates a common base class for RemoveWeight and EditWeight. The model calls directly into the undo command, which is somewhat unfortunate as it feels like a layering violation. It's the easy thing to do for now. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
-rw-r--r--commands/command.cpp5
-rw-r--r--commands/command.h1
-rw-r--r--commands/command_edit.cpp70
-rw-r--r--commands/command_edit.h26
-rw-r--r--core/equipment.c9
-rw-r--r--core/equipment.h1
-rw-r--r--core/subsurface-qt/DiveListNotifier.h1
-rw-r--r--desktop-widgets/tab-widgets/TabDiveEquipment.cpp15
-rw-r--r--qt-models/weightmodel.cpp60
-rw-r--r--qt-models/weightmodel.h1
10 files changed, 131 insertions, 58 deletions
diff --git a/commands/command.cpp b/commands/command.cpp
index 9417eec0e..9ea0e860f 100644
--- a/commands/command.cpp
+++ b/commands/command.cpp
@@ -278,6 +278,11 @@ int removeWeight(int index, bool currentDiveOnly)
return execute_edit(new RemoveWeight(index, currentDiveOnly));
}
+int editWeight(int index, weightsystem_t ws, bool currentDiveOnly)
+{
+ return execute_edit(new EditWeight(index, ws, currentDiveOnly));
+}
+
// Trip editing related commands
void editTripLocation(dive_trip *trip, const QString &s)
{
diff --git a/commands/command.h b/commands/command.h
index 5c60ac316..0f93a3e85 100644
--- a/commands/command.h
+++ b/commands/command.h
@@ -83,6 +83,7 @@ void replanDive(dive *d); // dive computer(s) and cylinder(s) will be reset!
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);
// 5) Trip editing commands
diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp
index 61b2f0d7a..2ca13199d 100644
--- a/commands/command_edit.cpp
+++ b/commands/command_edit.cpp
@@ -6,6 +6,7 @@
#include "core/selection.h"
#include "core/subsurface-string.h"
#include "core/tag.h"
+#include "qt-models/weightsysteminfomodel.h"
namespace Command {
@@ -993,7 +994,7 @@ static int find_weightsystem_index(const struct dive *d, weightsystem_t ws)
return -1;
}
-RemoveWeight::RemoveWeight(int index, bool currentDiveOnly) :
+EditWeightBase::EditWeightBase(int index, bool currentDiveOnly) :
EditDivesBase(currentDiveOnly),
ws(empty_weightsystem)
{
@@ -1024,21 +1025,25 @@ RemoveWeight::RemoveWeight(int index, bool currentDiveOnly) :
}
}
dives = std::move(divesNew);
-
- //: remove the part in parentheses for %n = 1
- setText(tr("Remove weight (%n dive(s))", "", dives.size()));
}
-RemoveWeight::~RemoveWeight()
+EditWeightBase::~EditWeightBase()
{
free_weightsystem(ws);
}
-bool RemoveWeight::workToBeDone()
+bool EditWeightBase::workToBeDone()
{
return !dives.empty();
}
+RemoveWeight::RemoveWeight(int index, bool currentDiveOnly) :
+ EditWeightBase(index, currentDiveOnly)
+{
+ //: remove the part in parentheses for %n = 1
+ setText(tr("Remove weight (%n dive(s))", "", dives.size()));
+}
+
void RemoveWeight::undo()
{
for (size_t i = 0; i < dives.size(); ++i) {
@@ -1055,4 +1060,57 @@ void RemoveWeight::redo()
}
}
+EditWeight::EditWeight(int index, weightsystem_t wsIn, bool currentDiveOnly) :
+ EditWeightBase(index, currentDiveOnly),
+ new_ws(empty_weightsystem)
+{
+ if (dives.empty())
+ return;
+
+ //: remove the part in parentheses for %n = 1
+ setText(tr("Edit weight (%n dive(s))", "", dives.size()));
+
+ // Try to untranslate the weightsystem name
+ new_ws = clone_weightsystem(wsIn);
+ QString vString(new_ws.description);
+ for (int i = 0; i < MAX_WS_INFO && ws_info[i].name; ++i) {
+ if (gettextFromC::tr(ws_info[i].name) == vString) {
+ free_weightsystem(new_ws);
+ new_ws.description = copy_string(ws_info[i].name);
+ break;
+ }
+ }
+
+ // If that doesn't change anything, do nothing
+ if (same_weightsystem(ws, new_ws)) {
+ dives.clear();
+ return;
+ }
+
+ WSInfoModel *wsim = WSInfoModel::instance();
+ QModelIndexList matches = wsim->match(wsim->index(0, 0), Qt::DisplayRole, gettextFromC::tr(new_ws.description));
+ if (!matches.isEmpty())
+ wsim->setData(wsim->index(matches.first().row(), WSInfoModel::GR), new_ws.weight.grams);
+}
+
+EditWeight::~EditWeight()
+{
+ free_weightsystem(new_ws);
+}
+
+void EditWeight::redo()
+{
+ for (size_t i = 0; i < dives.size(); ++i) {
+ set_weightsystem(dives[i], indexes[i], new_ws);
+ emit diveListNotifier.weightEdited(dives[i], indexes[i]);
+ }
+ std::swap(ws, new_ws);
+}
+
+// Undo and redo do the same as just the stored value is exchanged
+void EditWeight::undo()
+{
+ redo();
+}
+
} // namespace Command
diff --git a/commands/command_edit.h b/commands/command_edit.h
index c23f06094..76b538b4d 100644
--- a/commands/command_edit.h
+++ b/commands/command_edit.h
@@ -339,16 +339,32 @@ private:
bool workToBeDone() override;
};
-class RemoveWeight : public EditDivesBase {
+class EditWeightBase : public EditDivesBase {
+protected:
+ EditWeightBase(int index, bool currentDiveOnly);
+ ~EditWeightBase();
+
+ weightsystem_t ws;
+ std::vector<int> indexes; // An index for each dive in the dives vector.
+ bool workToBeDone() override;
+};
+
+class RemoveWeight : public EditWeightBase {
public:
RemoveWeight(int index, bool currentDiveOnly);
- ~RemoveWeight();
private:
- weightsystem_t ws;
- std::vector<int> indexes; // An index for each dive in the dives vector.
void undo() override;
void redo() override;
- bool workToBeDone() override;
+};
+
+class EditWeight : public EditWeightBase {
+public:
+ EditWeight(int index, weightsystem_t ws, bool currentDiveOnly); // Clones ws
+ ~EditWeight();
+private:
+ weightsystem_t new_ws;
+ void undo() override;
+ void redo() override;
};
} // namespace Command
diff --git a/core/equipment.c b/core/equipment.c
index e7ac327fd..07e468c1c 100644
--- a/core/equipment.c
+++ b/core/equipment.c
@@ -288,6 +288,15 @@ void remove_weightsystem(struct dive *dive, int idx)
remove_from_weightsystem_table(&dive->weightsystems, idx);
}
+// ws is cloned.
+void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws)
+{
+ if (idx < 0 || idx >= dive->weightsystems.nr)
+ return;
+ free_weightsystem(dive->weightsystems.weightsystems[idx]);
+ dive->weightsystems.weightsystems[idx] = clone_weightsystem(ws);
+}
+
/* when planning a dive we need to make sure that all cylinders have a sane depth assigned
* and if we are tracking gas consumption the pressures need to be reset to start = end = workingpressure */
void reset_cylinders(struct dive *dive, bool track_gas)
diff --git a/core/equipment.h b/core/equipment.h
index 77fd9c430..11d6f37c1 100644
--- a/core/equipment.h
+++ b/core/equipment.h
@@ -83,6 +83,7 @@ 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 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);
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);
diff --git a/core/subsurface-qt/DiveListNotifier.h b/core/subsurface-qt/DiveListNotifier.h
index 8c681948e..fc7115a99 100644
--- a/core/subsurface-qt/DiveListNotifier.h
+++ b/core/subsurface-qt/DiveListNotifier.h
@@ -88,6 +88,7 @@ signals:
void weightsystemsReset(const QVector<dive *> &dives);
void weightAdded(dive *d, int pos);
void weightRemoved(dive *d, int pos);
+ void weightEdited(dive *d, int pos);
// Trip edited signal
void tripChanged(dive_trip *trip, TripField field);
diff --git a/desktop-widgets/tab-widgets/TabDiveEquipment.cpp b/desktop-widgets/tab-widgets/TabDiveEquipment.cpp
index 4baca44b2..ed15c20bc 100644
--- a/desktop-widgets/tab-widgets/TabDiveEquipment.cpp
+++ b/desktop-widgets/tab-widgets/TabDiveEquipment.cpp
@@ -179,12 +179,10 @@ void TabDiveEquipment::editWeightWidget(const QModelIndex &index)
if (!index.isValid())
return;
- if (index.column() == WeightModel::REMOVE) {
+ if (index.column() == WeightModel::REMOVE)
divesEdited(Command::removeWeight(index.row(), false));
- } else {
- MainWindow::instance()->mainTab->enableEdition();
+ else
ui.weights->edit(index);
- }
}
// tricky little macro to edit all the selected dives
@@ -256,15 +254,6 @@ void TabDiveEquipment::acceptChanges()
do_replot = true;
}
- if (weightModel->changed) {
- mark_divelist_changed(true);
- MODIFY_DIVES(selectedDives,
- if (weightsystems_equal(mydive, cd))
- copy_weights(&displayed_dive.weightsystems, &mydive->weightsystems);
- );
- copy_weights(&displayed_dive.weightsystems, &cd->weightsystems);
- }
-
if (do_replot)
MainWindow::instance()->graphics->replot();
diff --git a/qt-models/weightmodel.cpp b/qt-models/weightmodel.cpp
index dbdbcdb88..46b084cae 100644
--- a/qt-models/weightmodel.cpp
+++ b/qt-models/weightmodel.cpp
@@ -6,6 +6,9 @@
#include "core/qthelper.h"
#include "core/subsurface-qt/DiveListNotifier.h"
#include "qt-models/weightsysteminfomodel.h"
+#ifndef SUBSURFACE_MOBILE
+#include "commands/command.h"
+#endif
WeightModel::WeightModel(QObject *parent) : CleanerTableModel(parent),
changed(false),
@@ -18,6 +21,7 @@ WeightModel::WeightModel(QObject *parent) : CleanerTableModel(parent),
connect(&diveListNotifier, &DiveListNotifier::weightsystemsReset, this, &WeightModel::weightsystemsReset);
connect(&diveListNotifier, &DiveListNotifier::weightAdded, this, &WeightModel::weightAdded);
connect(&diveListNotifier, &DiveListNotifier::weightRemoved, this, &WeightModel::weightRemoved);
+ connect(&diveListNotifier, &DiveListNotifier::weightEdited, this, &WeightModel::weightEdited);
}
weightsystem_t WeightModel::weightSystemAt(const QModelIndex &index) const
@@ -105,50 +109,30 @@ void WeightModel::clearTempWS()
void WeightModel::commitTempWS()
{
- if (tempRow < 0)
+#ifndef SUBSURFACE_MOBILE
+ if (tempRow < 0 || !d || tempRow > d->weightsystems.nr)
return;
+ // Only submit a command if the type changed
+ weightsystem_t ws = d->weightsystems.weightsystems[tempRow];
+ if (!same_string(ws.description, tempWS.description) || gettextFromC::tr(ws.description) != QString(tempWS.description))
+ Command::editWeight(tempRow, tempWS, false);
tempRow = -1;
- setData(index(tempRow, TYPE), QVariant::fromValue(QString(tempWS.description)), Qt::EditRole);
- setData(index(tempRow, WEIGHT), QVariant::fromValue(get_weight_string(tempWS.weight, true)), Qt::EditRole);
+#endif
}
bool WeightModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
+#ifndef SUBSURFACE_MOBILE
QString vString = value.toString();
- weightsystem_t *ws = &d->weightsystems.weightsystems[index.row()];
+ weightsystem_t ws = weightSystemAt(index);
switch (index.column()) {
- case TYPE:
- if (!value.isNull()) {
- //TODO: C-function weight_system_set_description ?
- if (!ws->description || gettextFromC::tr(ws->description) != vString) {
- // loop over translations to see if one matches
- int i = -1;
- while (i < MAX_WS_INFO && ws_info[++i].name) {
- if (gettextFromC::tr(ws_info[i].name) == vString) {
- ws->description = copy_string(ws_info[i].name);
- break;
- }
- }
- if (i == MAX_WS_INFO || ws_info[i].name == NULL) // didn't find a match
- ws->description = copy_qstring(vString);
- changed = true;
- }
- }
- break;
case WEIGHT:
- if (CHANGED()) {
- ws->weight = string_to_weight(qPrintable(vString));
- // now update the ws_info
- changed = true;
- WSInfoModel *wsim = WSInfoModel::instance();
- QModelIndexList matches = wsim->match(wsim->index(0, 0), Qt::DisplayRole, gettextFromC::tr(ws->description));
- if (!matches.isEmpty())
- wsim->setData(wsim->index(matches.first().row(), WSInfoModel::GR), ws->weight.grams);
- }
- break;
+ ws.weight = string_to_weight(qPrintable(vString));
+ Command::editWeight(index.row(), ws, false);
+ return true;
}
- dataChanged(index, index);
- return true;
+ return false;
+#endif
}
Qt::ItemFlags WeightModel::flags(const QModelIndex &index) const
@@ -200,3 +184,11 @@ void WeightModel::weightRemoved(struct dive *changed, int pos)
beginRemoveRows(QModelIndex(), pos, pos);
endRemoveRows();
}
+
+void WeightModel::weightEdited(struct dive *changed, int pos)
+{
+ if (d != changed)
+ return;
+
+ dataChanged(index(pos, TYPE), index(pos, WEIGHT));
+}
diff --git a/qt-models/weightmodel.h b/qt-models/weightmodel.h
index c8f9c9776..1ef7cdf53 100644
--- a/qt-models/weightmodel.h
+++ b/qt-models/weightmodel.h
@@ -35,6 +35,7 @@ slots:
void weightsystemsReset(const QVector<dive *> &dives);
void weightAdded(dive *d, int pos);
void weightRemoved(dive *d, int pos);
+ void weightEdited(dive *d, int pos);
private:
dive *d;