diff --git a/CHANGELOG.md b/CHANGELOG.md index be63cb75d..42f8d88dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +Planner: Add checkbox on considering oxygen narcotic Desktop: register changes when clicking "done" on dive-site edit screen Mobile: re-enable GPS location service icon in global drawer Mobile: add support for editing the dive number of a dive diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index d7bf4606d..98fa5622f 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -3545,7 +3545,8 @@ image::images/PlannerWindow1.jpg["FIGURE: Dive planner startup window",align="ce O~2~% according to the depth set. Set to ''*'' to calculate the best O~2~% for the dive maximum depth. ** MND: the gas Maximum Narcotic Depth (MND). Automatically calculated based on the Best Mix END preference (default 30m / 98 ft). Editing this field will modify the He% according to the depth set. - Set to ''*'' to calculate the best He% for the dive maximum depth. + Set to ''*'' to calculate the best He% for the dive maximum depth. Depending on the checkbox, oxygen + is considered narcotic (the END is used) or not (the EAD is used). - The profile of the planned dive can be created in two ways: * Drag the waypoints diff --git a/core/dive.c b/core/dive.c index d845d8077..9788e64c7 100644 --- a/core/dive.c +++ b/core/dive.c @@ -3761,13 +3761,17 @@ fraction_t best_o2(depth_t depth, const struct dive *dive) } //Calculate He in best mix. O2 is considered narcopic -fraction_t best_he(depth_t depth, const struct dive *dive) +fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcotic, fraction_t fo2) { fraction_t fhe; int pnarcotic, ambient; pnarcotic = depth_to_mbar(prefs.bestmixend.mm, dive); ambient = depth_to_mbar(depth.mm, dive); - fhe.permille = (100 - 100 * pnarcotic / ambient) * 10; //use integer arithmetic to round up to nearest percent + if (o2narcotic) { + fhe.permille = (100 - 100 * pnarcotic / ambient) * 10; //use integer arithmetic to round up to nearest percent + } else { + fhe.permille = 1000 - fo2.permille - N2_IN_AIR * pnarcotic / ambient; + } if (fhe.permille < 0) fhe.permille = 0; return fhe; diff --git a/core/dive.h b/core/dive.h index 87aa3e5fd..6d1bd450d 100644 --- a/core/dive.h +++ b/core/dive.h @@ -226,7 +226,7 @@ extern int explicit_first_cylinder(const struct dive *dive, const struct divecom extern int get_depth_at_time(const struct divecomputer *dc, unsigned int time); extern fraction_t best_o2(depth_t depth, const struct dive *dive); -extern fraction_t best_he(depth_t depth, const struct dive *dive); +extern fraction_t best_he(depth_t depth, const struct dive *dive, bool o2narcotic, fraction_t fo2); extern int get_surface_pressure_in_mbar(const struct dive *dive, bool non_null); extern int calculate_depth_to_mbar(int depth, pressure_t surface_pressure, int salinity); diff --git a/core/pref.h b/core/pref.h index 50e13a117..f7af35415 100644 --- a/core/pref.h +++ b/core/pref.h @@ -160,6 +160,7 @@ struct preferences { bool display_variations; bool doo2breaks; bool dobailout; + bool o2narcotic; bool drop_stone_mode; bool last_stop; // At 6m? int min_switch_duration; // seconds diff --git a/core/settings/qPrefDivePlanner.cpp b/core/settings/qPrefDivePlanner.cpp index f33b390cf..e094bfed0 100644 --- a/core/settings/qPrefDivePlanner.cpp +++ b/core/settings/qPrefDivePlanner.cpp @@ -35,6 +35,7 @@ void qPrefDivePlanner::loadSync(bool doSync) disk_display_variations(doSync); disk_doo2breaks(doSync); disk_dobailout(doSync); + disk_o2narcotic(doSync); disk_drop_stone_mode(doSync); disk_last_stop(doSync); disk_min_switch_duration(doSync); @@ -76,6 +77,7 @@ HANDLE_PREFERENCE_BOOL(DivePlanner, "display_variations", display_variations); HANDLE_PREFERENCE_BOOL(DivePlanner, "doo2breaks", doo2breaks); HANDLE_PREFERENCE_BOOL(DivePlanner, "dobailbout", dobailout); +HANDLE_PREFERENCE_BOOL(DivePlanner, "o2narcotic", o2narcotic); HANDLE_PREFERENCE_BOOL(DivePlanner, "drop_stone_mode", drop_stone_mode); diff --git a/core/settings/qPrefDivePlanner.h b/core/settings/qPrefDivePlanner.h index 09d8fabae..7a75fa4ce 100644 --- a/core/settings/qPrefDivePlanner.h +++ b/core/settings/qPrefDivePlanner.h @@ -23,6 +23,7 @@ class qPrefDivePlanner : public QObject { Q_PROPERTY(bool display_variations READ display_variations WRITE set_display_variations NOTIFY display_variationsChanged); Q_PROPERTY(bool doo2breaks READ doo2breaks WRITE set_doo2breaks NOTIFY doo2breaksChanged); Q_PROPERTY(bool dobailout READ dobailout WRITE set_dobailout NOTIFY dobailoutChanged); + Q_PROPERTY(bool o2narcotic READ o2narcotic WRITE set_o2narcotic NOTIFY o2narcoticChanged) Q_PROPERTY(bool drop_stone_mode READ drop_stone_mode WRITE set_drop_stone_mode NOTIFY drop_stone_modeChanged); Q_PROPERTY(bool last_stop READ last_stop WRITE set_last_stop NOTIFY last_stopChanged); Q_PROPERTY(int min_switch_duration READ min_switch_duration WRITE set_min_switch_duration NOTIFY min_switch_durationChanged); @@ -60,6 +61,7 @@ public: static bool display_variations() { return prefs.display_variations; } static bool doo2breaks() { return prefs.doo2breaks; } static bool dobailout() { return prefs.dobailout; } + static bool o2narcotic() { return prefs.o2narcotic; } static bool drop_stone_mode() { return prefs.drop_stone_mode; } static bool last_stop() { return prefs.last_stop; } static int min_switch_duration() { return prefs.min_switch_duration; } @@ -89,6 +91,7 @@ public slots: static void set_display_variations(bool value); static void set_doo2breaks(bool value); static void set_dobailout(bool value); + static void set_o2narcotic(bool value); static void set_drop_stone_mode(bool value); static void set_last_stop(bool value); static void set_min_switch_duration(int value); @@ -118,6 +121,7 @@ signals: void display_variationsChanged(bool value); void doo2breaksChanged(bool value); void dobailoutChanged(bool value); + void o2narcoticChanged(bool value); void drop_stone_modeChanged(bool value); void last_stopChanged(bool value); void min_switch_durationChanged(int value); @@ -148,6 +152,7 @@ private: static void disk_display_variations(bool doSync); static void disk_doo2breaks(bool doSync); static void disk_dobailout(bool doSync); + static void disk_o2narcotic(bool doSync); static void disk_drop_stone_mode(bool doSync); static void disk_last_stop(bool doSync); static void disk_min_switch_duration(bool doSync); diff --git a/core/subsurfacestartup.c b/core/subsurfacestartup.c index 8b7c14179..920285b14 100644 --- a/core/subsurfacestartup.c +++ b/core/subsurfacestartup.c @@ -73,6 +73,7 @@ struct preferences default_prefs = { .display_duration = true, .display_transitions = true, .display_variations = false, + .o2narcotic = true, .safetystop = true, .bottomsac = 20000, .decosac = 17000, diff --git a/desktop-widgets/diveplanner.cpp b/desktop-widgets/diveplanner.cpp index 33caffd0d..663bb03fb 100644 --- a/desktop-widgets/diveplanner.cpp +++ b/desktop-widgets/diveplanner.cpp @@ -451,6 +451,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f) ui.backgasBreaks->setChecked(prefs.doo2breaks); setBailout(false); setBailoutVisibility(false); + ui.o2narcotic->setChecked(prefs.o2narcotic); ui.drop_stone_mode->setChecked(prefs.drop_stone_mode); ui.switch_at_req_stop->setChecked(prefs.switch_at_req_stop); ui.min_switch_duration->setValue(prefs.min_switch_duration / 60); @@ -496,6 +497,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f) connect(ui.vpmb_conservatism, SIGNAL(valueChanged(int)), plannerModel, SLOT(setVpmbConservatism(int))); connect(ui.backgasBreaks, SIGNAL(toggled(bool)), this, SLOT(setBackgasBreaks(bool))); connect(ui.bailout, SIGNAL(toggled(bool)), this, SLOT(setBailout(bool))); + connect(ui.o2narcotic, SIGNAL(toggled(bool)), this, SLOT(setO2narcotic(bool))); connect(ui.switch_at_req_stop, SIGNAL(toggled(bool)), plannerModel, SLOT(setSwitchAtReqStop(bool))); connect(ui.min_switch_duration, SIGNAL(valueChanged(int)), plannerModel, SLOT(setMinSwitchDuration(int))); connect(ui.surface_segment, SIGNAL(valueChanged(int)), plannerModel, SLOT(setSurfaceSegment(int))); @@ -504,6 +506,7 @@ PlannerSettingsWidget::PlannerSettingsWidget(QWidget *parent, Qt::WindowFlags f) connect(ui.bottompo2, SIGNAL(valueChanged(double)), CylindersModel::instance(), SLOT(updateBestMixes())); connect(ui.bestmixEND, SIGNAL(valueChanged(int)), CylindersModel::instance(), SLOT(updateBestMixes())); + connect(ui.o2narcotic, SIGNAL(toggled(bool)), CylindersModel::instance(), SLOT(updateBestMixes())); connect(modeMapper, SIGNAL(mapped(int)), this, SLOT(disableDecoElements(int))); connect(ui.ascRate75, SIGNAL(valueChanged(int)), this, SLOT(setAscrate75(int))); @@ -679,6 +682,12 @@ void PlannerSettingsWidget::setBailout(bool dobailout) plannerModel->emitDataChanged(); } +void PlannerSettingsWidget::setO2narcotic(bool o2narcotic) +{ + qPrefDivePlanner::instance()->set_o2narcotic(o2narcotic); + plannerModel->emitDataChanged(); +} + void PlannerSettingsWidget::setBailoutVisibility(int mode) { ui.bailout->setDisabled(!(mode == CCR || mode == PSCR)); diff --git a/desktop-widgets/diveplanner.h b/desktop-widgets/diveplanner.h index 6d17c956b..e9e7808b9 100644 --- a/desktop-widgets/diveplanner.h +++ b/desktop-widgets/diveplanner.h @@ -86,6 +86,7 @@ slots: void setBestmixEND(int depth); void setBackgasBreaks(bool dobreaks); void setBailout(bool dobailout); + void setO2narcotic(bool o2narcotic); void disableDecoElements(int mode); void disableBackgasBreaks(bool enabled); void setDiveMode(int mode); diff --git a/desktop-widgets/plannerSettings.ui b/desktop-widgets/plannerSettings.ui index f22d0db45..33e3d2456 100644 --- a/desktop-widgets/plannerSettings.ui +++ b/desktop-widgets/plannerSettings.ui @@ -561,6 +561,83 @@ 2 + + + + Notes + + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + Verbatim dive plan + + + + + + + In diveplan, list transitions or treat them as implicit + + + Display transitions in deco + + + + + + + In dive plan, show runtime (absolute time) of stops + + + Display runtime + + + + + + + true + + + In dive plan, show duration (relative time) of stops + + + Display segment duration + + + + + + + true + + + Compute variations of plan (performance cost) + + + Display plan variations + + + + + + @@ -581,7 +658,7 @@ - + Qt::Vertical @@ -594,7 +671,7 @@ - + Qt::Vertical @@ -692,83 +769,6 @@ - - - - Notes - - - - 2 - - - 2 - - - 2 - - - 2 - - - 2 - - - - - Verbatim dive plan - - - - - - - In diveplan, list transitions or treat them as implicit - - - Display transitions in deco - - - - - - - In dive plan, show runtime (absolute time) of stops - - - Display runtime - - - - - - - true - - - In dive plan, show duration (relative time) of stops - - - Display segment duration - - - - - - - true - - - Compute variations of plan (performance cost) - - - Display plan variations - - - - - - @@ -831,6 +831,16 @@ + + + + Treat oxygen as narcotic when computing best mix + + + O₂ narcotic + + + diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp index 95c6aace2..a05cef23f 100644 --- a/qt-models/cylindermodel.cpp +++ b/qt-models/cylindermodel.cpp @@ -391,11 +391,11 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in if (QString::compare(qPrintable(vString), "*") == 0) { cyl->bestmix_he = true; // Calculate fO2 for max. depth - cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive); + cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2); } else { cyl->bestmix_he = false; // Calculate fHe for input depth - cyl->gasmix.he = best_he(string_to_depth(qPrintable(vString)), &displayed_dive); + cyl->gasmix.he = best_he(string_to_depth(qPrintable(vString)), &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2); } changed = true; } @@ -605,7 +605,7 @@ bool CylindersModel::updateBestMixes() gasUpdated = true; } if (cyl->bestmix_he) { - cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive); + cyl->gasmix.he = best_he(displayed_dive.maxdepth, &displayed_dive, prefs.o2narcotic, cyl->gasmix.o2); // fO2 + fHe must not be greater than 1 if (get_o2(cyl->gasmix) + get_he(cyl->gasmix) > 1000) cyl->gasmix.o2.permille = 1000 - get_he(cyl->gasmix);