diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2019-10-13 12:44:39 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2019-10-26 11:36:23 -0700 |
commit | 8dea2ada3bc9d0fcfbe1bb101ea079480dfdbe57 (patch) | |
tree | 12611a44e6f9efef1fa3ed8ce510d78b6841e63c | |
parent | 5c4d163a41c69538c8a658db82dde1a7486b6759 (diff) | |
download | subsurface-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.h | 101 | ||||
-rw-r--r-- | desktop-widgets/command_edit.cpp | 39 | ||||
-rw-r--r-- | desktop-widgets/mapwidget.cpp | 2 | ||||
-rw-r--r-- | desktop-widgets/tab-widgets/TabDiveEquipment.cpp | 7 | ||||
-rw-r--r-- | desktop-widgets/tab-widgets/TabDiveInformation.cpp | 24 | ||||
-rw-r--r-- | desktop-widgets/tab-widgets/TabDiveStatistics.cpp | 11 | ||||
-rw-r--r-- | desktop-widgets/tab-widgets/maintab.cpp | 60 |
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) |