summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2019-10-13 12:44:39 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2019-10-26 11:36:23 -0700
commit8dea2ada3bc9d0fcfbe1bb101ea079480dfdbe57 (patch)
tree12611a44e6f9efef1fa3ed8ce510d78b6841e63c
parent5c4d163a41c69538c8a658db82dde1a7486b6759 (diff)
downloadsubsurface-8dea2ada3bc9d0fcfbe1bb101ea079480dfdbe57.tar.gz
Undo: turn dive- and trip-fields into flags
The divesEdited signal sends the changed field as a parameter. Since some undo-commands change multiple fields, this led to numerous signals for a single command. This in turn would lead to multiple profile-reloads and statistic recalculations. Therefore, turn the enum into a bitfield. For simplicity, provide a constructor that takes classical flags and turns them into the bitfield. This is necessary because C-style named initialization is only supported on C++20 onward! Is this somewhat overengineered? Yes, maybe. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
-rw-r--r--core/subsurface-qt/DiveListNotifier.h101
-rw-r--r--desktop-widgets/command_edit.cpp39
-rw-r--r--desktop-widgets/mapwidget.cpp2
-rw-r--r--desktop-widgets/tab-widgets/TabDiveEquipment.cpp7
-rw-r--r--desktop-widgets/tab-widgets/TabDiveInformation.cpp24
-rw-r--r--desktop-widgets/tab-widgets/TabDiveStatistics.cpp11
-rw-r--r--desktop-widgets/tab-widgets/maintab.cpp60
7 files changed, 119 insertions, 125 deletions
diff --git a/core/subsurface-qt/DiveListNotifier.h b/core/subsurface-qt/DiveListNotifier.h
index 11da468cf..cda7ea335 100644
--- a/core/subsurface-qt/DiveListNotifier.h
+++ b/core/subsurface-qt/DiveListNotifier.h
@@ -9,30 +9,59 @@
#include <QObject>
-// Dive and trip fields that can be edited.
-// Use "enum class" to not polute the global name space.
-enum class DiveField {
- NR,
- DATETIME,
- DEPTH,
- DURATION,
- AIR_TEMP,
- WATER_TEMP,
- ATM_PRESS,
- DIVESITE,
- DIVEMASTER,
- BUDDY,
- RATING,
- VISIBILITY,
- SUIT,
- TAGS,
- MODE,
- NOTES,
- SALINITY
+// Dive and trip fields that can be edited. Use bit fields so that we can pass multiple fields at once.
+// Provides an inlined flag-based constructur because sadly C-style designated initializers are only supported since C++20.
+struct DiveField {
+ // Note: using int instead of the more natural bool, because gcc produces significantly worse code with
+ // bool. clang, on the other hand, does fine.
+ unsigned int nr : 1;
+ unsigned int datetime : 1;
+ unsigned int depth : 1;
+ unsigned int duration : 1;
+ unsigned int air_temp : 1;
+ unsigned int water_temp : 1;
+ unsigned int atm_press : 1;
+ unsigned int divesite : 1;
+ unsigned int divemaster : 1;
+ unsigned int buddy : 1;
+ unsigned int rating : 1;
+ unsigned int visibility : 1;
+ unsigned int suit : 1;
+ unsigned int tags : 1;
+ unsigned int mode : 1;
+ unsigned int notes : 1;
+ unsigned int salinity : 1;
+ enum Flags {
+ NONE = 0,
+ NR = 1 << 0,
+ DATETIME = 1 << 1,
+ DEPTH = 1 << 2,
+ DURATION = 1 << 3,
+ AIR_TEMP = 1 << 4,
+ WATER_TEMP = 1 << 5,
+ ATM_PRESS = 1 << 6,
+ DIVESITE = 1 << 7,
+ DIVEMASTER = 1 << 8,
+ BUDDY = 1 << 9,
+ RATING = 1 << 10,
+ VISIBILITY = 1 << 11,
+ SUIT = 1 << 12,
+ TAGS = 1 << 13,
+ MODE = 1 << 14,
+ NOTES = 1 << 15,
+ SALINITY = 1 << 16
+ };
+ DiveField(int flags);
};
-enum class TripField {
- LOCATION,
- NOTES
+struct TripField {
+ unsigned int location : 1;
+ unsigned int notes : 1;
+ enum Flags {
+ NONE = 0,
+ LOCATION = 1 << 0,
+ NOTES = 1 << 1
+ };
+ TripField(int flags);
};
class DiveListNotifier : public QObject {
@@ -130,4 +159,30 @@ inline DiveListNotifier::InCommandMarker DiveListNotifier::enterCommand()
return InCommandMarker(*this);
}
+inline DiveField::DiveField(int flags) :
+ nr((flags & NR) != 0),
+ datetime((flags & DATETIME) != 0),
+ depth((flags & DEPTH) != 0),
+ duration((flags & DURATION) != 0),
+ air_temp((flags & AIR_TEMP) != 0),
+ water_temp((flags & WATER_TEMP) != 0),
+ atm_press((flags & ATM_PRESS) != 0),
+ divesite((flags & DIVESITE) != 0),
+ divemaster((flags & DIVEMASTER) != 0),
+ buddy((flags & BUDDY) != 0),
+ rating((flags & RATING) != 0),
+ visibility((flags & VISIBILITY) != 0),
+ suit((flags & SUIT) != 0),
+ tags((flags & TAGS) != 0),
+ mode((flags & MODE) != 0),
+ notes((flags & NOTES) != 0),
+ salinity((flags & SALINITY) != 0)
+{
+}
+
+inline TripField::TripField(int flags) :
+ location((flags & LOCATION) != 0),
+ notes((flags & NOTES) != 0)
+{
+}
#endif
diff --git a/desktop-widgets/command_edit.cpp b/desktop-widgets/command_edit.cpp
index b11ede6a5..5f6f0be3f 100644
--- a/desktop-widgets/command_edit.cpp
+++ b/desktop-widgets/command_edit.cpp
@@ -803,25 +803,16 @@ void PasteDives::undo()
}
// Send signals.
- // TODO: We send one signal per changed field. This means that the dive list may
- // update the entry numerous times. Perhaps change the field-id into flags?
- // There seems to be a number of enums / flags describing dive fields. Perhaps unify them all?
- if (what.notes)
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::NOTES);
- if (what.divemaster)
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::DIVEMASTER);
- if (what.buddy)
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::BUDDY);
- if (what.suit)
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::SUIT);
- if (what.rating)
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::RATING);
- if (what.visibility)
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::VISIBILITY);
- if (what.divesite)
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::DIVESITE);
- if (what.tags)
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::TAGS);
+ DiveField fields(DiveField::NONE);
+ fields.notes = what.notes;
+ fields.divemaster = what.divemaster;
+ fields.buddy = what.buddy;
+ fields.suit = what.suit;
+ fields.rating = what.rating;
+ fields.visibility = what.visibility;
+ fields.divesite = what.divesite;
+ fields.tags = what.tags;
+ emit diveListNotifier.divesChanged(divesToNotify, fields);
if (what.cylinders)
emit diveListNotifier.cylindersReset(divesToNotify);
if (what.weights)
@@ -888,14 +879,8 @@ void ReplanDive::undo()
fixup_dive(d);
QVector<dive *> divesToNotify = { d };
- // TODO: Turn field into flags to avoid multiple signals
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::DATETIME);
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::DURATION);
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::DEPTH);
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::MODE);
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::NOTES);
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::SALINITY);
- emit diveListNotifier.divesChanged(divesToNotify, DiveField::ATM_PRESS);
+ emit diveListNotifier.divesChanged(divesToNotify, DiveField::DATETIME | DiveField::DURATION | DiveField::DEPTH | DiveField::MODE |
+ DiveField::NOTES | DiveField::SALINITY | DiveField::ATM_PRESS);
emit diveListNotifier.cylindersReset(divesToNotify);
}
diff --git a/desktop-widgets/mapwidget.cpp b/desktop-widgets/mapwidget.cpp
index ce98cc3cc..f8f9b0b7b 100644
--- a/desktop-widgets/mapwidget.cpp
+++ b/desktop-widgets/mapwidget.cpp
@@ -104,7 +104,7 @@ void MapWidget::coordinatesChanged(struct dive_site *ds, const location_t &locat
void MapWidget::divesChanged(const QVector<dive *> &, DiveField field)
{
- if (field == DiveField::DIVESITE)
+ if (field.divesite)
reload();
}
diff --git a/desktop-widgets/tab-widgets/TabDiveEquipment.cpp b/desktop-widgets/tab-widgets/TabDiveEquipment.cpp
index db9754140..af4dcbd44 100644
--- a/desktop-widgets/tab-widgets/TabDiveEquipment.cpp
+++ b/desktop-widgets/tab-widgets/TabDiveEquipment.cpp
@@ -108,13 +108,8 @@ void TabDiveEquipment::divesChanged(const QVector<dive *> &dives, DiveField fiel
if (!current_dive || !dives.contains(current_dive))
return;
- switch(field) {
- case DiveField::SUIT:
+ if (field.suit)
ui.suit->setText(QString(current_dive->suit));
- break;
- default:
- break;
- }
}
void TabDiveEquipment::toggleTriggeredColumn()
diff --git a/desktop-widgets/tab-widgets/TabDiveInformation.cpp b/desktop-widgets/tab-widgets/TabDiveInformation.cpp
index 66c1f7401..273bf4525 100644
--- a/desktop-widgets/tab-widgets/TabDiveInformation.cpp
+++ b/desktop-widgets/tab-widgets/TabDiveInformation.cpp
@@ -141,30 +141,18 @@ void TabDiveInformation::divesChanged(const QVector<dive *> &dives, DiveField fi
if (!current_dive || !dives.contains(current_dive))
return;
- switch(field) {
- case DiveField::DURATION:
- case DiveField::DEPTH:
- case DiveField::MODE:
+ if (field.duration || field.depth || field.mode)
updateProfile();
- break;
- case DiveField::AIR_TEMP:
+ if (field.air_temp)
ui->airTemperatureText->setText(get_temperature_string(current_dive->airtemp, true));
- break;
- case DiveField::WATER_TEMP:
+ if (field.water_temp)
ui->waterTemperatureText->setText(get_temperature_string(current_dive->watertemp, true));
- break;
- case DiveField::ATM_PRESS:
+ if (field.atm_press)
ui->atmPressVal->setText(ui->atmPressVal->text().sprintf("%d",current_dive->surface_pressure.mbar));
- break;
- case DiveField::DATETIME:
+ if (field.datetime)
updateWhen();
- break;
- case DiveField::SALINITY:
+ if (field.salinity)
updateSalinity();
- break;
- default:
- break;
- }
}
void TabDiveInformation::on_atmPressType_currentIndexChanged(int index) { updateTextBox(COMBO_CHANGED); }
diff --git a/desktop-widgets/tab-widgets/TabDiveStatistics.cpp b/desktop-widgets/tab-widgets/TabDiveStatistics.cpp
index 3719363df..ee090c6bc 100644
--- a/desktop-widgets/tab-widgets/TabDiveStatistics.cpp
+++ b/desktop-widgets/tab-widgets/TabDiveStatistics.cpp
@@ -53,17 +53,8 @@ void TabDiveStatistics::divesChanged(const QVector<dive *> &dives, DiveField fie
return;
// TODO: make this more fine grained. Currently, the core can only calculate *all* statistics.
- switch(field) {
- case DiveField::DURATION:
- case DiveField::DEPTH:
- case DiveField::MODE:
- case DiveField::AIR_TEMP:
- case DiveField::WATER_TEMP:
+ if (field.duration || field.depth || field.mode || field.air_temp || field.water_temp)
updateData();
- break;
- default:
- break;
- }
}
void TabDiveStatistics::updateData()
diff --git a/desktop-widgets/tab-widgets/maintab.cpp b/desktop-widgets/tab-widgets/maintab.cpp
index 5c6e5104c..9fe647a71 100644
--- a/desktop-widgets/tab-widgets/maintab.cpp
+++ b/desktop-widgets/tab-widgets/maintab.cpp
@@ -284,53 +284,39 @@ void MainTab::divesChanged(const QVector<dive *> &dives, DiveField field)
if (!current_dive || !dives.contains(current_dive))
return;
- switch(field) {
- case DiveField::DURATION:
+ if (field.duration)
ui.duration->setText(render_seconds_to_string(current_dive->duration.seconds));
- profileFromDive(current_dive);
- break;
- case DiveField::DEPTH:
+ if (field.depth)
ui.depth->setText(get_depth_string(current_dive->maxdepth, true));
- profileFromDive(current_dive);
- break;
- case DiveField::AIR_TEMP:
+ if (field.air_temp)
ui.airtemp->setText(get_temperature_string(current_dive->airtemp, true));
- break;
- case DiveField::WATER_TEMP:
+ if (field.water_temp)
ui.watertemp->setText(get_temperature_string(current_dive->watertemp, true));
- break;
- case DiveField::RATING:
+ if (field.rating)
ui.rating->setCurrentStars(current_dive->rating);
- break;
- case DiveField::VISIBILITY:
+ if (field.visibility)
ui.visibility->setCurrentStars(current_dive->visibility);
- break;
- case DiveField::NOTES:
+ if (field.notes)
updateNotes(current_dive);
- break;
- case DiveField::MODE:
+ if (field.mode)
updateMode(current_dive);
- break;
- case DiveField::DATETIME:
+ if (field.datetime) {
updateDateTime(current_dive);
MainWindow::instance()->graphics->dateTimeChanged();
DivePlannerPointsModel::instance()->getDiveplan().when = current_dive->when;
- break;
- case DiveField::DIVESITE:
+ }
+ if (field.divesite)
updateDiveSite(current_dive);
- break;
- case DiveField::TAGS:
+ if (field.tags)
ui.tagWidget->setText(get_taglist_string(current_dive->tag_list));
- break;
- case DiveField::BUDDY:
+ if (field.buddy)
ui.buddy->setText(current_dive->buddy);
- break;
- case DiveField::DIVEMASTER:
+ if (field.divemaster)
ui.divemaster->setText(current_dive->divemaster);
- break;
- default:
- break;
- }
+
+ // If duration or depth changed, the profile needs to be replotted
+ if (field.duration || field.depth)
+ profileFromDive(current_dive);
}
void MainTab::diveSiteEdited(dive_site *ds, int)
@@ -347,16 +333,10 @@ void MainTab::tripChanged(dive_trip *trip, TripField field)
if (currentTrip != trip)
return;
- switch(field) {
- case TripField::NOTES:
+ if (field.notes)
ui.notes->setText(currentTrip->notes);
- break;
- case TripField::LOCATION:
+ if (field.location)
ui.diveTripLocation->setText(currentTrip->location);
- break;
- default:
- break;
- }
}
void MainTab::nextInputField(QKeyEvent *event)