Planner: Improve Gas Handling in CCR Mode.
This has become a bit of a catch-all overhaul of a large portion of the planner - I started out wanting to improve the CCR mode, but then as I started pulling all the other threads that needed addressing started to come with it. Improve how the gas selection is handled when planning dives in CCR mode, by making the type (OC / CCR) of segments dependent on the gas use type that was set for the selected gas. Add a preference to allow the user to chose to use OC gases as diluent, in a similar fashion to the original implementation. Hide gases that cannot be used in the currently selected dive mode in all drop downs. Include usage type in gas names if this is needed. Hide columns and disable elements in the 'Dive planner points' table if they can they can not be edited in the curently selected dive mode. Visually identify gases and usage types that are not appropriate for the currently selected dive mode. Move the 'Dive mode' selection to the top of the planner view, to accommodate the fact that this is a property of the dive and not a planner setting. Show a warning instead of the dive plan if the plan contains gases that are not usable in the selected dive mode. Fix the data entry for the setpoint in the 'Dive planner points' table. Fix problems with enabling / disabling planner settings when switching between dive modes. Refactor some names to make them more appropriate for their current usage. One point that is still open is to hide gas usage graphs in the planner profile if the gas isn't used for OC, as there is no way to meaningfully interpolate such usage. Signed-off-by: Michael Keller <github@ike.ch>
3
.gitignore
vendored
|
@ -17,6 +17,9 @@ Documentation/docbook-xsl.css
|
||||||
Documentation/user-manual*.html
|
Documentation/user-manual*.html
|
||||||
Documentation/user-manual*.pdf
|
Documentation/user-manual*.pdf
|
||||||
Documentation/user-manual*.text
|
Documentation/user-manual*.text
|
||||||
|
Documentation/mobile-manual*.html
|
||||||
|
Documentation/mobile-manual*.pdf
|
||||||
|
Documentation/mobile-manual*.text
|
||||||
Documentation/mobile-images/mobile-images
|
Documentation/mobile-images/mobile-images
|
||||||
packaging/windows/subsurface.nsi
|
packaging/windows/subsurface.nsi
|
||||||
packaging/macos/Info.plist
|
packaging/macos/Info.plist
|
||||||
|
|
Before Width: | Height: | Size: 22 KiB |
BIN
Documentation/images/CCR_b1.png
Normal file
After Width: | Height: | Size: 172 KiB |
Before Width: | Height: | Size: 30 KiB |
BIN
Documentation/images/CCR_b2.png
Normal file
After Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 32 KiB |
BIN
Documentation/images/CCR_b3.png
Normal file
After Width: | Height: | Size: 198 KiB |
Before Width: | Height: | Size: 71 KiB |
BIN
Documentation/images/PlannerWindow1.png
Normal file
After Width: | Height: | Size: 350 KiB |
Before Width: | Height: | Size: 81 KiB |
BIN
Documentation/images/Planner_CCR.png
Normal file
After Width: | Height: | Size: 321 KiB |
Before Width: | Height: | Size: 81 KiB |
BIN
Documentation/images/Planner_OC_deco.png
Normal file
After Width: | Height: | Size: 346 KiB |
BIN
Documentation/images/Planner_OC_gas_for_CCR.png
Normal file
After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 69 KiB |
BIN
Documentation/images/Planner_OC_rec1.png
Normal file
After Width: | Height: | Size: 227 KiB |
Before Width: | Height: | Size: 74 KiB |
BIN
Documentation/images/Planner_OC_rec2.png
Normal file
After Width: | Height: | Size: 235 KiB |
BIN
Documentation/images/Planner_issues.png
Normal file
After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 86 KiB |
BIN
Documentation/images/Planner_pSCR.png
Normal file
After Width: | Height: | Size: 341 KiB |
Before Width: | Height: | Size: 31 KiB |
BIN
Documentation/images/planner1.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
Documentation/images/planner2.png
Normal file
After Width: | Height: | Size: 18 KiB |
|
@ -3825,24 +3825,18 @@ user interface. It is explicitly used under the following conditions:
|
||||||
|
|
||||||
=== The _Subsurface_ dive planner screen
|
=== The _Subsurface_ dive planner screen
|
||||||
|
|
||||||
Like the _Subsurface_ dive log, the planner screen is divided into several sections (see image below). The *setup*
|
Like the _Subsurface_ dive log, the planner screen is divided into several sections (see image below):
|
||||||
parameters for a dive are entered into the sections on the left hand and bottom side of the screen.
|
- At the top left of the screen are the *dive parameters* that will be stored with the planned dive, like dive time, dive mode, and water type.
|
||||||
They are: Available Gases, Rates, Planning, Gas Options and Notes.
|
- Below this are tables that allow the user to configure the *cylinders* used on the dive, and the *depth / time and breathing gas* used for the individual parts of the planned dive.
|
||||||
|
- At the bottom of the screen are the *parameters used by the planner* to plan the dive, like ascent / descent rates, planning parameters, and gas options.
|
||||||
At the top right hand is a green *design panel* on which the profile of the dive can be
|
- At the top right hand is a green *design panel* on which the profile of the dive can be manipulated directly by dragging and clicking as explained below. This feature makes the _Subsurface_ dive planner unique in ease of use.
|
||||||
manipulated directly by dragging and clicking as explained below. This feature makes the
|
- On the bottom right is a field for the *dive plan details* - this is where the planner will show the dive plan in text form, which will also persisted to the dive notes when the planned dive is saved. This field is designe to be easily copied to other software. It also shows any warning messages about the dive plan.
|
||||||
_Subsurface_ dive planner unique in ease of use.
|
|
||||||
|
|
||||||
At the bottom right is a text panel with a heading of _Dive Plan Details_. This is where the details of
|
|
||||||
the dive plan are provided in a way that can easily be copied to other software. This is also where
|
|
||||||
any warning messages about the dive plan are printed.
|
|
||||||
|
|
||||||
image::images/PlannerWindow1.jpg["FIGURE: Dive planner startup window",align="center"]
|
|
||||||
|
|
||||||
|
image::images/PlannerWindow1.png["FIGURE: Dive planner startup window",align="center"]
|
||||||
|
|
||||||
=== Open circuit dives
|
=== Open circuit dives
|
||||||
|
|
||||||
- Towards the center bottom of the planner (circled in blue in the image above) is a dropdown list with three options. Select the appropriate one of these:
|
- In the top left of the planner (circled in blue in the image above) is a dropdown list with three options. Select the appropriate one of these:
|
||||||
** Open Circuit (the default)
|
** Open Circuit (the default)
|
||||||
** CCR
|
** CCR
|
||||||
** pSCR
|
** pSCR
|
||||||
|
@ -3882,11 +3876,14 @@ image::images/PlannerWindow1.jpg["FIGURE: Dive planner startup window",align="ce
|
||||||
* The most efficient way to create a dive profile is to enter the appropriate values into the table
|
* The most efficient way to create a dive profile is to enter the appropriate values into the table
|
||||||
marked _Dive planner points_. The first line of the table represents the duration and the final
|
marked _Dive planner points_. The first line of the table represents the duration and the final
|
||||||
depth of the descent from the surface. Subsequent segments describe the bottom phase of the dive.
|
depth of the descent from the surface. Subsequent segments describe the bottom phase of the dive.
|
||||||
The _CC setpoint_ column is only relevant for closed circuit divers.
|
|
||||||
The ascent is usually not specified because this is what the planner is supposed to calculate.
|
The ascent is usually not specified because this is what the planner is supposed to calculate.
|
||||||
Add additional segments to the profile by selecting the "+" icon at the top right hand of the
|
Add additional segments to the profile by selecting the "+" icon at the top right hand of the
|
||||||
table. Segments entered into the _Dive planner points_ table automatically appear in the *Dive
|
table. Segments entered into the _Dive planner points_ table automatically appear in the *Dive
|
||||||
Profile* diagram.
|
Profile* diagram.
|
||||||
|
* If the _Dive mode_ of the planned dive is changed after gases and segments have been added, it can happen that the _Use_ of a gasmix or the _Used gas_ selected for a segment are not appropriate for the selected _Dive mode_. In this case _Subsurface_ will highlight the problematic selection with a red background to help the user identify and correct the issue. The dive plan will not be calculated until all issues are resolved.
|
||||||
|
|
||||||
|
image::images/Planner_issues.png["FIGURE: Dive planner: Issue display",align="center"]
|
||||||
|
|
||||||
|
|
||||||
==== Recreational dives
|
==== Recreational dives
|
||||||
|
|
||||||
|
@ -3963,7 +3960,7 @@ the nitrogen load incurred during previous dives.
|
||||||
Below is an image of a dive plan for a recreational dive at 30 meters with gradient factors of 100. Because the no-deco limit (NDL) is 22
|
Below is an image of a dive plan for a recreational dive at 30 meters with gradient factors of 100. Because the no-deco limit (NDL) is 22
|
||||||
minutes, there remains a significant amount of air in the cylinder at the end of the dive.
|
minutes, there remains a significant amount of air in the cylinder at the end of the dive.
|
||||||
|
|
||||||
image::images/Planner_OC_rec1.jpg["FIGURE: A recreational dive plan: setup",align="center"]
|
image::images/Planner_OC_rec1.png["FIGURE: A recreational dive plan: setup",align="center"]
|
||||||
|
|
||||||
The dive profile in the planner shows the maximum dive time within no-deco limits using the
|
The dive profile in the planner shows the maximum dive time within no-deco limits using the
|
||||||
Bühlmann ZH-L16 algorithm and the gas and depth settings specified as described above. The _Subsurface_ planner
|
Bühlmann ZH-L16 algorithm and the gas and depth settings specified as described above. The _Subsurface_ planner
|
||||||
|
@ -3976,7 +3973,7 @@ it means that recreational dive limits are exceeded and either the dive duration
|
||||||
Below is the same dive plan as above, but with a safety stop and reduced gradient factors for
|
Below is the same dive plan as above, but with a safety stop and reduced gradient factors for
|
||||||
a larger safety margin.
|
a larger safety margin.
|
||||||
|
|
||||||
image::images/Planner_OC_rec2.jpg["FIGURE: A recreational dive plan: gradient factors setup",align="center"]
|
image::images/Planner_OC_rec2.png["FIGURE: A recreational dive plan: gradient factors setup",align="center"]
|
||||||
|
|
||||||
==== Non-recreational open circuit dives, including decompression
|
==== Non-recreational open circuit dives, including decompression
|
||||||
|
|
||||||
|
@ -4093,12 +4090,16 @@ _Type_ select the appropriate cylinder size by using the dropdown list that appe
|
||||||
double-clicking a cell in this column. By default, a large number of sizes are listed,
|
double-clicking a cell in this column. By default, a large number of sizes are listed,
|
||||||
and a new cylinder size can be created by typing this into the text box. The cylinder size, start pressure
|
and a new cylinder size can be created by typing this into the text box. The cylinder size, start pressure
|
||||||
and default switch depths are initialized automatically. Specify the gas composition
|
and default switch depths are initialized automatically. Specify the gas composition
|
||||||
(e.g. helium and oxygen content). A non-zero value in the "CC setpoint" column of the table of dive planner points
|
(e.g. helium and oxygen content) and - in the case of planning a CCR dive, the intended use as diluent or OC bailout gas.
|
||||||
indicates a valid setpoint for oxygen partial pressure and that the segment
|
When planning CCR dives, a segment is calculated as a closed circuit segment if the gas that is used is a _diluent_, and as an open circuit segment if the gas is an _OC-gas_. If the user enables the _Allow open circuit gas to be used as bailout_ option in the _Tech setup_ preferences, then an additional column will be shown allowing the user to select the _Dive mode_ for each segment dived on an _OC-gas_.
|
||||||
is dived using a closed circuit rebreather (CCR). If the last manually entered
|
|
||||||
segment is a CCR segment, the decompression phase is computed assuming the diver
|
image::images/Planner_OC_gas_for_CCR.png["FIGURE: Planning a dive: OC as CCR",align="center"]
|
||||||
|
|
||||||
|
For CCR dives, an additional column is shown in the _Dive planner points_ table, allowing the user to specify the _Setpoint_ for each closed circuit segment.
|
||||||
|
If the last manually entered
|
||||||
|
segment is a closed circuit segment, the decompression phase is computed assuming the diver
|
||||||
uses a CCR with the specified set-point. If the last segment (however
|
uses a CCR with the specified set-point. If the last segment (however
|
||||||
short) is on open circuit (OC, indicated by a zero set-point) the
|
short) is on open circuit the
|
||||||
decompression is computed in OC mode and the planner only considers gas
|
decompression is computed in OC mode and the planner only considers gas
|
||||||
changes in OC mode.
|
changes in OC mode.
|
||||||
|
|
||||||
|
@ -4112,16 +4113,19 @@ you wish to use this gas during the very start of the dive (the other gas is not
|
||||||
Upon pressing Enter on the keyboard, that segment is moved to the top of that table and the plan is adjusted
|
Upon pressing Enter on the keyboard, that segment is moved to the top of that table and the plan is adjusted
|
||||||
automatically to take into account this new segment of the dive plan (image B below).
|
automatically to take into account this new segment of the dive plan (image B below).
|
||||||
|
|
||||||
image::images/planner1.jpg["FIGURE: Planning a dive: segments",align="center"]
|
*A:*
|
||||||
|
image::images/planner1.png["FIGURE: Planning a dive: segments 1/2",align="center"]
|
||||||
|
*B:*
|
||||||
|
image::images/planner2.png["FIGURE: Planning a dive: segments 2/2",align="center"]
|
||||||
|
|
||||||
Below is an example of a dive plan to 55m using Tx20/30 and the Bühlmann algorithm,
|
Below is an example of a dive plan to 55m using Tx20/30 and the Bühlmann algorithm,
|
||||||
followed by an ascent using EAN50 and using the settings as described above.
|
followed by an ascent using EAN50 and using the settings as described above.
|
||||||
|
|
||||||
image::images/Planner_OC_deco.jpg["FIGURE: Planning a dive: setup",align="center"]
|
image::images/Planner_OC_deco.png["FIGURE: Planning a dive: setup",align="center"]
|
||||||
|
|
||||||
Once the above steps have been completed, save by clicking the _Save_ button
|
Once the above steps have been completed, save by clicking the _Save_ button
|
||||||
towards the top middle of the planner. The saved dive plan will appear
|
towards the top middle of the planner. The saved dive plan will appear
|
||||||
in the *Dive List* panel of _Subsurface_.
|
in the _Dive List_ panel of _Subsurface_.
|
||||||
|
|
||||||
*The dive plan details*
|
*The dive plan details*
|
||||||
|
|
||||||
|
@ -4238,7 +4242,7 @@ are specified for pSCR dives. Below is a dive plan for a pSCR dive. The dive is
|
||||||
to that of the CCR dive below, but note the longer ascent duration due to the lower oxygen
|
to that of the CCR dive below, but note the longer ascent duration due to the lower oxygen
|
||||||
in the loop due to the oxygen drop across the mouthpiece of the pSCR equipment.
|
in the loop due to the oxygen drop across the mouthpiece of the pSCR equipment.
|
||||||
|
|
||||||
image::images/Planner_pSCR.jpg["FIGURE: Planning a pSCR dive: setup",align="center"]
|
image::images/Planner_pSCR.png["FIGURE: Planning a pSCR dive: setup",align="center"]
|
||||||
|
|
||||||
==== Planning for pSCR bailout
|
==== Planning for pSCR bailout
|
||||||
|
|
||||||
|
@ -4283,7 +4287,7 @@ columns, as in the cave example, above. See the example of bailout for a CCR div
|
||||||
=== Planning CCR dives
|
=== Planning CCR dives
|
||||||
|
|
||||||
To plan a dive using a closed circuit rebreather, select the _CCR_ option in the dropdown
|
To plan a dive using a closed circuit rebreather, select the _CCR_ option in the dropdown
|
||||||
list, circled in blue in the image below.
|
list.
|
||||||
|
|
||||||
*Available gases*: In the _Available gases_ table, enter the cylinder information for the
|
*Available gases*: In the _Available gases_ table, enter the cylinder information for the
|
||||||
diluent cylinder and for any bail-out cylinders. Do NOT enter the information for the oxygen
|
diluent cylinder and for any bail-out cylinders. Do NOT enter the information for the oxygen
|
||||||
|
@ -4292,12 +4296,7 @@ cylinder since it is implied when the _CCR_ dropdown selection is made.
|
||||||
*Entering setpoints*: Specify a default setpoint in the Preferences tab, by selecting _File -> Preferences -> Tech setup_ from
|
*Entering setpoints*: Specify a default setpoint in the Preferences tab, by selecting _File -> Preferences -> Tech setup_ from
|
||||||
the main menu. All user-entered segments in the _Dive planner points_ table
|
the main menu. All user-entered segments in the _Dive planner points_ table
|
||||||
use the default setpoint value. Then, different setpoints can be specified for dive segments
|
use the default setpoint value. Then, different setpoints can be specified for dive segments
|
||||||
in the _Dive planner points_ table. A zero setpoint
|
in the _Dive planner points_ table.
|
||||||
means the diver bails out to open circuit mode for that segment. Decompression is always calculated
|
|
||||||
using the setpoint of the last manually entered segment. So, to plan a bail out ascent for a
|
|
||||||
CCR dive, add a one-minute dive segment to the end with a setpoint value of 0. The decompression
|
|
||||||
algorithm does not switch deco-gases automatically while in CCR mode (i.e. when a positive setpoint is specified) but
|
|
||||||
this is calculated for bail out ascents.
|
|
||||||
|
|
||||||
If you want the setpoint to change during the planned ascent at a specified depth, you can do this
|
If you want the setpoint to change during the planned ascent at a specified depth, you can do this
|
||||||
using a "fake" cylinder that you add to the gas list: Give that cylinder a name of "SP 1.4" (or use
|
using a "fake" cylinder that you add to the gas list: Give that cylinder a name of "SP 1.4" (or use
|
||||||
|
@ -4307,36 +4306,30 @@ there on.
|
||||||
|
|
||||||
The dive profile for a CCR dive may look something like the image below.
|
The dive profile for a CCR dive may look something like the image below.
|
||||||
|
|
||||||
image::images/Planner_CCR.jpg["FIGURE: Planning a CCR dive: setup",align="center"]
|
image::images/Planner_CCR.png["FIGURE: Planning a CCR dive: setup",align="center"]
|
||||||
|
|
||||||
Note that, in the _Dive plan details_, the gas consumption for a CCR segment is not calculated,
|
Note that, in the _Dive plan details_, the gas consumption for a CCR segment is not calculated,
|
||||||
so gas consumptions of 0 liters are the norm.
|
so gas consumptions of 0 liters are the norm.
|
||||||
|
|
||||||
==== Planning for CCR bailout
|
==== Planning for CCR bailout
|
||||||
|
|
||||||
[icon="images/CCR_b1.jpg"]
|
image::images/CCR_b1.png["FIGURE: Planning a CCR dive: closed circuit deco",align="center"]
|
||||||
[NOTE]
|
|
||||||
It is often necessary to plan for a worst-case bailout event in order to ensure sufficient bailout gas to reach the
|
It is often necessary to plan for a worst-case bailout event in order to ensure sufficient bailout gas to reach the
|
||||||
surface, taking into account decompression. This is done by 1) checking the _Bailout_ checkbox of the dive planner
|
surface, taking into account decompression. This is done by checking the _Rebreather: Bailout / Deco on OC_ checkbox of the dive planner
|
||||||
(bailout will be calculated starting at the last segment of the dive specified in the _Dive planner points_ table);
|
(bailout will be calculated starting at the last segment of the dive specified in the _Dive planner points_ table):
|
||||||
2) defining a 1-minute segment at the end of the bottom part
|
|
||||||
of the dive, as in the image on the left where a CCR dive to 40m for 21 minutes is planned;
|
|
||||||
3) changing to an OC-gas during any segment in the _Dive planner points_ table.
|
|
||||||
|
|
||||||
|
image::images/CCR_b2.png["FIGURE: Planning a CCR dive: open circuit bailout",align="center"]
|
||||||
|
|
||||||
[icon="images/CCR_b2.jpg"]
|
In the _Available gases_
|
||||||
[NOTE]
|
table, change the _Use_ of the gas used for the last segment to _OC-gas_. This signifies bailout.
|
||||||
In the _Dive planner points
|
The appropriate pO~2~ and cylinder pressure
|
||||||
table_, change the _Dive mode_ of this 1-minute segment to _OC_. This signifies bailout. In this case there is bailout to
|
graphs are shown in the dive profile:
|
||||||
the existing diluent cylinder (assuming this cylinder has sufficient gas). The appropriate pO~2~ and cylinder pressure
|
|
||||||
graphs are shown in the dive profile, as in the image on the left. Note that the setpoint drops to zero after bailout, since
|
|
||||||
this value does not apply to breathed bailout gas.
|
|
||||||
|
|
||||||
|
image::images/CCR_b3.png["FIGURE: Planning a CCR dive: open circuit bailout by cylinder selection",align="center"]
|
||||||
|
|
||||||
[icon="images/CCR_b3.jpg"]
|
|
||||||
[NOTE]
|
|
||||||
In order to plan for bailout to an external bailout cylinder, change the _Used gas_ for the 1-minute segment to the
|
In order to plan for bailout to an external bailout cylinder, change the _Used gas_ for the 1-minute segment to the
|
||||||
appropriate cylinder, as in the example on the left. Note that the cylinder change as well as the bailout are indicated with
|
appropriate cylinder, as in the example above. Note that the cylinder change as well as the bailout are indicated with
|
||||||
overlapping icons.
|
overlapping icons.
|
||||||
|
|
||||||
The volumes of gases required for bailout can be found at the bottom of the *Dive plan details* panel.
|
The volumes of gases required for bailout can be found at the bottom of the *Dive plan details* panel.
|
||||||
|
|
|
@ -1260,7 +1260,7 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn,
|
||||||
setText(Command::Base::tr("Edit cylinder (%n dive(s))", "", dives.size()));
|
setText(Command::Base::tr("Edit cylinder (%n dive(s))", "", dives.size()));
|
||||||
|
|
||||||
// The base class copied the cylinders for us, let's edit them
|
// The base class copied the cylinders for us, let's edit them
|
||||||
for (int i = 0; i < (int)indexes.size(); ++i) {
|
for (int i = 0; i < (int)cyl.size(); ++i) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EditCylinderType::TYPE:
|
case EditCylinderType::TYPE:
|
||||||
cyl[i].type = cylIn.type;
|
cyl[i].type = cylIn.type;
|
||||||
|
|
|
@ -1625,6 +1625,35 @@ static bool cylinder_in_use(const struct dive *dive, int idx)
|
||||||
return cylinder_has_data(dive->cylinders[idx]);
|
return cylinder_has_data(dive->cylinders[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_cylinder_use_appropriate(const struct divecomputer &dc, const cylinder_t &cyl, bool allowNonUsable)
|
||||||
|
{
|
||||||
|
switch (cyl.cylinder_use) {
|
||||||
|
case OC:
|
||||||
|
if (dc.divemode == FREEDIVE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case OXYGEN:
|
||||||
|
if (!allowNonUsable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case DILUENT:
|
||||||
|
if (dc.divemode != CCR)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NOT_USED:
|
||||||
|
if (!allowNonUsable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Merging cylinder information is non-trivial, because the two dive computers
|
* Merging cylinder information is non-trivial, because the two dive computers
|
||||||
* may have different ideas of what the different cylinder indexing is.
|
* may have different ideas of what the different cylinder indexing is.
|
||||||
|
|
|
@ -146,6 +146,7 @@ struct dive_or_trip {
|
||||||
|
|
||||||
extern void cylinder_renumber(struct dive &dive, int mapping[]);
|
extern void cylinder_renumber(struct dive &dive, int mapping[]);
|
||||||
extern int same_gasmix_cylinder(const cylinder_t &cyl, int cylid, const struct dive *dive, bool check_unused);
|
extern int same_gasmix_cylinder(const cylinder_t &cyl, int cylid, const struct dive *dive, bool check_unused);
|
||||||
|
extern bool is_cylinder_use_appropriate(const struct divecomputer &dc, const cylinder_t &cyl, bool allowNonUsable);
|
||||||
|
|
||||||
/* Data stored when copying a dive */
|
/* Data stored when copying a dive */
|
||||||
struct dive_paste_data {
|
struct dive_paste_data {
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct divecomputer {
|
||||||
pressure_t surface_pressure;
|
pressure_t surface_pressure;
|
||||||
enum divemode_t divemode = OC; // dive computer type: OC(default) or CCR
|
enum divemode_t divemode = OC; // dive computer type: OC(default) or CCR
|
||||||
uint8_t no_o2sensors = 0; // rebreathers: number of O2 sensors used
|
uint8_t no_o2sensors = 0; // rebreathers: number of O2 sensors used
|
||||||
int salinity = 0; // kg per 10000 l
|
int salinity = 0; // kg per 10000 l
|
||||||
std::string model, serial, fw_version;
|
std::string model, serial, fw_version;
|
||||||
uint32_t deviceid = 0, diveid = 0;
|
uint32_t deviceid = 0, diveid = 0;
|
||||||
// Note: ve store samples, events and extra_data in std::vector<>s.
|
// Note: ve store samples, events and extra_data in std::vector<>s.
|
||||||
|
|
|
@ -4,4 +4,6 @@
|
||||||
|
|
||||||
enum divemode_t {OC, CCR, PSCR, FREEDIVE, NUM_DIVEMODE, UNDEF_COMP_TYPE}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type
|
enum divemode_t {OC, CCR, PSCR, FREEDIVE, NUM_DIVEMODE, UNDEF_COMP_TYPE}; // Flags (Open-circuit and Closed-circuit-rebreather) for setting dive computer type
|
||||||
|
|
||||||
|
#define IS_REBREATHER_MODE(divemode) ((divemode) == CCR || (divemode) == PSCR)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -380,14 +380,17 @@ static int setpoint_change(struct dive *dive, int cylinderid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<gaschanges> analyze_gaslist(struct diveplan *diveplan, struct dive *dive, int depth, int *asc_cylinder, bool ccr)
|
static std::vector<gaschanges> analyze_gaslist(struct diveplan *diveplan, struct dive *dive, int dcNr, int depth, int *asc_cylinder, bool ccr, bool &inappropriate_cylinder_use)
|
||||||
{
|
{
|
||||||
size_t nr = 0;
|
size_t nr = 0;
|
||||||
std::vector<gaschanges> gaschanges;
|
std::vector<gaschanges> gaschanges;
|
||||||
struct divedatapoint *dp = diveplan->dp;
|
struct divedatapoint *dp = diveplan->dp;
|
||||||
struct divedatapoint *best_ascent_dp = NULL;
|
struct divedatapoint *best_ascent_dp = NULL;
|
||||||
bool total_time_zero = true;
|
bool total_time_zero = true;
|
||||||
|
const divecomputer *dc = dive->get_dc(dcNr);
|
||||||
while (dp) {
|
while (dp) {
|
||||||
|
inappropriate_cylinder_use = inappropriate_cylinder_use || !is_cylinder_use_appropriate(*dc, *dive->get_cylinder(dp->cylinderid), false);
|
||||||
|
|
||||||
if (dp->time == 0 && total_time_zero && (ccr == (bool) setpoint_change(dive, dp->cylinderid))) {
|
if (dp->time == 0 && total_time_zero && (ccr == (bool) setpoint_change(dive, dp->cylinderid))) {
|
||||||
if (dp->depth.mm <= depth) {
|
if (dp->depth.mm <= depth) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -661,7 +664,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
bool o2break_next = false;
|
bool o2break_next = false;
|
||||||
int break_cylinder = -1, breakfrom_cylinder = 0;
|
int break_cylinder = -1, breakfrom_cylinder = 0;
|
||||||
bool last_segment_min_switch = false;
|
bool last_segment_min_switch = false;
|
||||||
bool error = false;
|
planner_error_t error = PLAN_OK;
|
||||||
bool decodive = false;
|
bool decodive = false;
|
||||||
int first_stop_depth = 0;
|
int first_stop_depth = 0;
|
||||||
int laststoptime = timestep;
|
int laststoptime = timestep;
|
||||||
|
@ -744,7 +747,11 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
|
|
||||||
/* Find the gases available for deco */
|
/* Find the gases available for deco */
|
||||||
|
|
||||||
std::vector<gaschanges> gaschanges = analyze_gaslist(diveplan, dive, depth, &best_first_ascend_cylinder, divemode == CCR && !prefs.dobailout);
|
bool inappropriate_cylinder_use = false;
|
||||||
|
std::vector<gaschanges> gaschanges = analyze_gaslist(diveplan, dive, dcNr, depth, &best_first_ascend_cylinder, divemode == CCR && !prefs.dobailout, inappropriate_cylinder_use);
|
||||||
|
if (inappropriate_cylinder_use) {
|
||||||
|
error = PLAN_ERROR_INAPPROPRIATE_GAS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the first potential decostopdepth above current depth */
|
/* Find the first potential decostopdepth above current depth */
|
||||||
for (stopidx = 0; stopidx < decostoplevelcount; stopidx++)
|
for (stopidx = 0; stopidx < decostoplevelcount; stopidx++)
|
||||||
|
@ -880,7 +887,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
current_cylinder = 0;
|
current_cylinder = 0;
|
||||||
}
|
}
|
||||||
reset_regression(ds);
|
reset_regression(ds);
|
||||||
while (1) {
|
while (error == PLAN_OK) {
|
||||||
/* We will break out when we hit the surface */
|
/* We will break out when we hit the surface */
|
||||||
do {
|
do {
|
||||||
/* Ascend to next stop depth */
|
/* Ascend to next stop depth */
|
||||||
|
@ -1005,7 +1012,8 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
laststoptime = new_clock - clock;
|
laststoptime = new_clock - clock;
|
||||||
/* Finish infinite deco */
|
/* Finish infinite deco */
|
||||||
if (laststoptime >= 48 * 3600 && depth >= 6000) {
|
if (laststoptime >= 48 * 3600 && depth >= 6000) {
|
||||||
error = true;
|
error = PLAN_ERROR_TIMEOUT;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1070,7 +1078,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
|
||||||
* if the ascent rate is slower, which is completely nonsensical.
|
* if the ascent rate is slower, which is completely nonsensical.
|
||||||
* Assume final ascent takes 20s, which is the time taken to ascend at 9m/min from 3m */
|
* Assume final ascent takes 20s, which is the time taken to ascend at 9m/min from 3m */
|
||||||
ds->deco_time = clock - bottom_time - (M_OR_FT(3,10) * ( prefs.last_stop ? 2 : 1)) / last_ascend_rate + 20;
|
ds->deco_time = clock - bottom_time - (M_OR_FT(3,10) * ( prefs.last_stop ? 2 : 1)) / last_ascend_rate + 20;
|
||||||
} while (!is_final_plan);
|
} while (!is_final_plan && error == PLAN_OK);
|
||||||
decostoptable[decostopcounter].depth = 0;
|
decostoptable[decostopcounter].depth = 0;
|
||||||
|
|
||||||
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode);
|
plan_add_segment(diveplan, clock - previous_point_time, 0, current_cylinder, po2, false, divemode);
|
||||||
|
@ -1112,24 +1120,31 @@ static int get_decimals(const char *begin, const char **endp, const unsigned dec
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Fraction? We only look at the first digit */
|
/* Fraction? We only look at the first digit */
|
||||||
if (*end == '.') {
|
if (*end == '.')
|
||||||
unsigned fraction = 0;
|
end++;
|
||||||
for (unsigned i = 0; i < decimals; i++) {
|
|
||||||
value *= 10;
|
unsigned fraction = 0;
|
||||||
|
for (unsigned i = 0; i < decimals; i++) {
|
||||||
|
value *= 10;
|
||||||
|
|
||||||
|
unsigned digit = 0;
|
||||||
|
if (isdigit(*end)) {
|
||||||
|
digit = *end - '0';
|
||||||
|
|
||||||
end++;
|
end++;
|
||||||
|
} else if (*end != '\0') {
|
||||||
if (!isdigit(*end))
|
return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
fraction = 10 * fraction + (*end - '0');
|
|
||||||
}
|
}
|
||||||
value += fraction;
|
|
||||||
|
|
||||||
do {
|
fraction = 10 * fraction + digit;
|
||||||
end++;
|
|
||||||
} while (isdigit(*end));
|
|
||||||
}
|
}
|
||||||
|
value += fraction;
|
||||||
|
|
||||||
|
do {
|
||||||
|
end++;
|
||||||
|
} while (isdigit(*end));
|
||||||
|
|
||||||
*endp = end;
|
*endp = end;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -1209,5 +1224,9 @@ int validate_po2(const char *text, int *mbar_po2)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*mbar_po2 = po2 * 10;
|
*mbar_po2 = po2 * 10;
|
||||||
|
|
||||||
|
if (*mbar_po2 < 160)
|
||||||
|
*mbar_po2 = 160;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,17 @@ struct diveplan {
|
||||||
|
|
||||||
struct deco_state_cache;
|
struct deco_state_cache;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PLAN_OK,
|
||||||
|
PLAN_ERROR_TIMEOUT,
|
||||||
|
PLAN_ERROR_INAPPROPRIATE_GAS,
|
||||||
|
} planner_error_t;
|
||||||
|
|
||||||
extern int validate_gas(const char *text, struct gasmix *gas);
|
extern int validate_gas(const char *text, struct gasmix *gas);
|
||||||
extern int validate_po2(const char *text, int *mbar_po2);
|
extern int validate_po2(const char *text, int *mbar_po2);
|
||||||
extern int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_t time);
|
extern int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_t time);
|
||||||
extern bool diveplan_empty(struct diveplan *diveplan);
|
extern bool diveplan_empty(struct diveplan *diveplan);
|
||||||
extern void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, bool error);
|
extern void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, planner_error_t error);
|
||||||
extern const char *get_planner_disclaimer();
|
extern const char *get_planner_disclaimer();
|
||||||
|
|
||||||
extern void free_dps(struct diveplan *diveplan);
|
extern void free_dps(struct diveplan *diveplan);
|
||||||
|
|
|
@ -96,7 +96,7 @@ extern std::string get_planner_disclaimer_formatted()
|
||||||
return format_string_std(get_planner_disclaimer(), deco);
|
return format_string_std(get_planner_disclaimer(), deco);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, bool error)
|
void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_disclaimer, planner_error_t error)
|
||||||
{
|
{
|
||||||
std::string buf;
|
std::string buf;
|
||||||
std::string icdbuf;
|
std::string icdbuf;
|
||||||
|
@ -122,12 +122,31 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d
|
||||||
if (!dp)
|
if (!dp)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (error) {
|
if (error != PLAN_OK) {
|
||||||
|
const char *message;
|
||||||
|
switch (error) {
|
||||||
|
case PLAN_ERROR_TIMEOUT:
|
||||||
|
message = translate("gettextFromC", "Decompression calculation aborted due to excessive time");
|
||||||
|
|
||||||
|
break;
|
||||||
|
case PLAN_ERROR_INAPPROPRIATE_GAS:
|
||||||
|
message = translate("gettextFromC", "One or more tanks with a tank use type inappropriate for the selected dive mode are included in the dive plan. "
|
||||||
|
"Please change them to appropriate tanks to enable the generation of a dive plan.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
message = translate("gettextFromC", "An error occurred during dive plan generation");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
buf += format_string_std("<span style='color: red;'>%s </span> %s<br/>",
|
buf += format_string_std("<span style='color: red;'>%s </span> %s<br/>",
|
||||||
translate("gettextFromC", "Warning:"),
|
translate("gettextFromC", "Warning:"), message);
|
||||||
translate("gettextFromC", "Decompression calculation aborted due to excessive time"));
|
|
||||||
// TODO: avoid copy
|
// TODO: avoid copy
|
||||||
dive->notes = buf;
|
dive->notes = buf;
|
||||||
|
dive->notes = strdup(buf.c_str());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,7 @@ preferences::preferences() :
|
||||||
vpmb_conservatism(3),
|
vpmb_conservatism(3),
|
||||||
zoomed_plot(false),
|
zoomed_plot(false),
|
||||||
infobox(true),
|
infobox(true),
|
||||||
|
allowOcGasAsDiluent(false),
|
||||||
coordinates_traditional(true),
|
coordinates_traditional(true),
|
||||||
unit_system(METRIC),
|
unit_system(METRIC),
|
||||||
units(SI_UNITS)
|
units(SI_UNITS)
|
||||||
|
|
|
@ -201,6 +201,7 @@ struct preferences {
|
||||||
int vpmb_conservatism;
|
int vpmb_conservatism;
|
||||||
bool zoomed_plot;
|
bool zoomed_plot;
|
||||||
bool infobox;
|
bool infobox;
|
||||||
|
bool allowOcGasAsDiluent;
|
||||||
|
|
||||||
// ********** Units **********
|
// ********** Units **********
|
||||||
bool coordinates_traditional;
|
bool coordinates_traditional;
|
||||||
|
|
|
@ -1151,19 +1151,51 @@ QString get_gas_string(struct gasmix gas)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList get_dive_gas_list(const struct dive *d)
|
QString get_dive_gas(const struct dive *d, int dcNr, int cylinderId)
|
||||||
{
|
{
|
||||||
QStringList list;
|
const cylinder_t *cyl = d->get_cylinder(cylinderId);
|
||||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
const divecomputer *dc = d->get_dc(dcNr);
|
||||||
/* Check if we have the same gasmix two or more times
|
|
||||||
* If yes return more verbose string */
|
bool showUse = (dc->divemode == CCR) | !is_cylinder_use_appropriate(*dc, *cyl, false);
|
||||||
int same_gas = same_gasmix_cylinder(cyl, i, d, true);
|
|
||||||
if (same_gas == -1)
|
QString gasType = get_gas_string(cyl->gasmix);
|
||||||
list.push_back(get_gas_string(cyl.gasmix));
|
QString gasName;
|
||||||
else
|
/* Check if we have the same gasmix two or more times
|
||||||
list.push_back(get_gas_string(cyl.gasmix) + QStringLiteral(" (%1 %2 ").arg(gettextFromC::tr("cyl.")).arg(i + 1) +
|
* If yes return more verbose string */
|
||||||
QString::fromStdString(cyl.type.description) + ")");
|
int same_gas = same_gasmix_cylinder(*cyl, cylinderId, d, true);
|
||||||
|
if (same_gas != -1) {
|
||||||
|
gasType += QString(" (%1 %2").arg(gettextFromC::tr("cyl.")).arg(cylinderId + 1);
|
||||||
|
gasName = QString::fromStdString(d->get_cylinder(cylinderId)->type.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showUse) {
|
||||||
|
if (gasName.isNull())
|
||||||
|
gasType += " (";
|
||||||
|
else
|
||||||
|
gasType += ", ";
|
||||||
|
gasType += gettextFromC::tr(cylinderuse_text[d->get_cylinder(cylinderId)->cylinder_use]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gasName.isNull())
|
||||||
|
gasType += QString(", %1").arg(gasName);
|
||||||
|
|
||||||
|
if (!gasName.isNull() || showUse)
|
||||||
|
gasType += ")";
|
||||||
|
|
||||||
|
return gasType;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<int, QString>> get_dive_gas_list(const struct dive *d, int dcNr, bool showOnlyAppropriate)
|
||||||
|
{
|
||||||
|
const divecomputer *dc = d->get_dc(dcNr);
|
||||||
|
std::vector<std::pair<int, QString>> list;
|
||||||
|
for (unsigned int i = 0; i < d->cylinders.size(); i++) {
|
||||||
|
if (showOnlyAppropriate && !is_cylinder_use_appropriate(*dc, *d->get_cylinder(i), false))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list.push_back(std::pair(i, get_dive_gas(d, dcNr, i)));
|
||||||
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@ enum watertypes {FRESHWATER, BRACKISHWATER, EN13319WATER, SALTWATER, DC_WATERTYP
|
||||||
QString distance_string(int distanceInMeters);
|
QString distance_string(int distanceInMeters);
|
||||||
bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out = 0);
|
bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out = 0);
|
||||||
QString get_gas_string(struct gasmix gas);
|
QString get_gas_string(struct gasmix gas);
|
||||||
QStringList get_dive_gas_list(const struct dive *d);
|
QString get_dive_gas(const struct dive *d, int dcNr, int cylinderId);
|
||||||
|
std::vector<std::pair<int, QString>> get_dive_gas_list(const struct dive *d, int dcNr, bool showOnlyAppropriate);
|
||||||
QStringList stringToList(const QString &s);
|
QStringList stringToList(const QString &s);
|
||||||
void read_hashes();
|
void read_hashes();
|
||||||
void write_hashes();
|
void write_hashes();
|
||||||
|
|
|
@ -14,6 +14,7 @@ qPrefTechnicalDetails *qPrefTechnicalDetails::instance()
|
||||||
|
|
||||||
void qPrefTechnicalDetails::loadSync(bool doSync)
|
void qPrefTechnicalDetails::loadSync(bool doSync)
|
||||||
{
|
{
|
||||||
|
disk_allowOcGasAsDiluent(doSync);
|
||||||
disk_calcalltissues(doSync);
|
disk_calcalltissues(doSync);
|
||||||
disk_calcceiling(doSync);
|
disk_calcceiling(doSync);
|
||||||
disk_calcceiling3m(doSync);
|
disk_calcceiling3m(doSync);
|
||||||
|
@ -100,6 +101,8 @@ void qPrefTechnicalDetails::disk_gflow(bool doSync)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HANDLE_PREFERENCE_BOOL(TechnicalDetails, "allowOcGasAsDiluent", allowOcGasAsDiluent);
|
||||||
|
|
||||||
HANDLE_PREFERENCE_BOOL(TechnicalDetails, "gf_low_at_maxdepth", gf_low_at_maxdepth);
|
HANDLE_PREFERENCE_BOOL(TechnicalDetails, "gf_low_at_maxdepth", gf_low_at_maxdepth);
|
||||||
|
|
||||||
HANDLE_PREFERENCE_BOOL(TechnicalDetails, "InfoBox", infobox);
|
HANDLE_PREFERENCE_BOOL(TechnicalDetails, "InfoBox", infobox);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
class qPrefTechnicalDetails : public QObject {
|
class qPrefTechnicalDetails : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool allowOcGasAsDiluent READ allowOcGasAsDiluent WRITE set_allowOcGasAsDiluent NOTIFY allowOcGasAsDiluentChanged)
|
||||||
Q_PROPERTY(bool calcalltissues READ calcalltissues WRITE set_calcalltissues NOTIFY calcalltissuesChanged)
|
Q_PROPERTY(bool calcalltissues READ calcalltissues WRITE set_calcalltissues NOTIFY calcalltissuesChanged)
|
||||||
Q_PROPERTY(bool calcceiling READ calcceiling WRITE set_calcceiling NOTIFY calcceilingChanged)
|
Q_PROPERTY(bool calcceiling READ calcceiling WRITE set_calcceiling NOTIFY calcceilingChanged)
|
||||||
Q_PROPERTY(bool calcceiling3m READ calcceiling3m WRITE set_calcceiling3m NOTIFY calcceiling3mChanged)
|
Q_PROPERTY(bool calcceiling3m READ calcceiling3m WRITE set_calcceiling3m NOTIFY calcceiling3mChanged)
|
||||||
|
@ -44,6 +45,7 @@ public:
|
||||||
static void sync() { loadSync(true); }
|
static void sync() { loadSync(true); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static bool allowOcGasAsDiluent() { return prefs.allowOcGasAsDiluent; }
|
||||||
static bool calcalltissues() { return prefs.calcalltissues; }
|
static bool calcalltissues() { return prefs.calcalltissues; }
|
||||||
static bool calcceiling() { return prefs.calcceiling; }
|
static bool calcceiling() { return prefs.calcceiling; }
|
||||||
static bool calcceiling3m() { return prefs.calcceiling3m; }
|
static bool calcceiling3m() { return prefs.calcceiling3m; }
|
||||||
|
@ -73,6 +75,7 @@ public:
|
||||||
static bool infobox() { return prefs.infobox; }
|
static bool infobox() { return prefs.infobox; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
static void set_allowOcGasAsDiluent(bool value);
|
||||||
static void set_calcalltissues(bool value);
|
static void set_calcalltissues(bool value);
|
||||||
static void set_calcceiling(bool value);
|
static void set_calcceiling(bool value);
|
||||||
static void set_calcceiling3m(bool value);
|
static void set_calcceiling3m(bool value);
|
||||||
|
@ -102,6 +105,7 @@ public slots:
|
||||||
static void set_infobox(bool value);
|
static void set_infobox(bool value);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void allowOcGasAsDiluentChanged(bool value);
|
||||||
void calcalltissuesChanged(bool value);
|
void calcalltissuesChanged(bool value);
|
||||||
void calcceilingChanged(bool value);
|
void calcceilingChanged(bool value);
|
||||||
void calcceiling3mChanged(bool value);
|
void calcceiling3mChanged(bool value);
|
||||||
|
@ -133,6 +137,7 @@ signals:
|
||||||
private:
|
private:
|
||||||
qPrefTechnicalDetails() {}
|
qPrefTechnicalDetails() {}
|
||||||
|
|
||||||
|
static void disk_allowOcGasAsDiluent(bool doSync);
|
||||||
static void disk_calcalltissues(bool doSync);
|
static void disk_calcalltissues(bool doSync);
|
||||||
static void disk_calcceiling(bool doSync);
|
static void disk_calcceiling(bool doSync);
|
||||||
static void disk_calcceiling3m(bool doSync);
|
static void disk_calcceiling3m(bool doSync);
|
||||||
|
|
|
@ -23,27 +23,32 @@
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DivePlannerWidget::DivePlannerWidget(dive &planned_dive, int dcNr, PlannerWidgets *parent)
|
DivePlannerWidget::DivePlannerWidget(const dive &planned_dive, int &dcNr, PlannerWidgets *parent)
|
||||||
{
|
{
|
||||||
DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
|
DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
|
||||||
CylindersModel *cylinders = DivePlannerPointsModel::instance()->cylindersModel();
|
CylindersModel *cylinders = DivePlannerPointsModel::instance()->cylindersModel();
|
||||||
|
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
|
|
||||||
|
// should be the same order as in dive_comp_type!
|
||||||
|
QStringList divemodes = QStringList();
|
||||||
|
for (int i = 0; i < FREEDIVE; i++)
|
||||||
|
divemodes.append(gettextFromC::tr(divemode_text_ui[i]));
|
||||||
|
ui.divemode->insertItems(0, divemodes);
|
||||||
|
|
||||||
ui.tableWidget->setTitle(tr("Dive planner points"));
|
ui.tableWidget->setTitle(tr("Dive planner points"));
|
||||||
|
ui.tableWidget->setBtnToolTip(tr("Add dive data point"));
|
||||||
ui.tableWidget->setModel(plannerModel);
|
ui.tableWidget->setModel(plannerModel);
|
||||||
connect(ui.tableWidget, &TableView::itemClicked, plannerModel, &DivePlannerPointsModel::remove);
|
connect(ui.tableWidget, &TableView::itemClicked, plannerModel, &DivePlannerPointsModel::remove);
|
||||||
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::GAS, new AirTypesDelegate(planned_dive, this));
|
connect(ui.tableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addDefaultStop);
|
||||||
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::DIVEMODE, new DiveTypesDelegate(this));
|
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::GAS, new GasTypesDelegate(planned_dive, dcNr, this));
|
||||||
|
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::DIVEMODE, new DiveTypesDelegate(planned_dive, dcNr, this));
|
||||||
|
|
||||||
ui.cylinderTableWidget->setTitle(tr("Available gases"));
|
ui.cylinderTableWidget->setTitle(tr("Available gases"));
|
||||||
ui.cylinderTableWidget->setBtnToolTip(tr("Add cylinder"));
|
ui.cylinderTableWidget->setBtnToolTip(tr("Add cylinder"));
|
||||||
ui.cylinderTableWidget->setModel(cylinders);
|
ui.cylinderTableWidget->setModel(cylinders);
|
||||||
connect(ui.cylinderTableWidget, &TableView::itemClicked, cylinders, &CylindersModel::remove);
|
|
||||||
ui.waterType->setItemData(0, FRESHWATER_SALINITY);
|
|
||||||
ui.waterType->setItemData(1, SEAWATER_SALINITY);
|
|
||||||
ui.waterType->setItemData(2, EN13319_SALINITY);
|
|
||||||
waterTypeUpdateTexts();
|
|
||||||
|
|
||||||
QTableView *view = ui.cylinderTableWidget->view();
|
QTableView *view = ui.cylinderTableWidget->view();
|
||||||
|
connect(ui.cylinderTableWidget, &TableView::itemClicked, cylinders, &CylindersModel::remove);
|
||||||
view->setColumnHidden(CylindersModel::START, true);
|
view->setColumnHidden(CylindersModel::START, true);
|
||||||
view->setColumnHidden(CylindersModel::END, true);
|
view->setColumnHidden(CylindersModel::END, true);
|
||||||
view->setColumnHidden(CylindersModel::DEPTH, false);
|
view->setColumnHidden(CylindersModel::DEPTH, false);
|
||||||
|
@ -52,18 +57,22 @@ DivePlannerWidget::DivePlannerWidget(dive &planned_dive, int dcNr, PlannerWidget
|
||||||
view->setColumnHidden(CylindersModel::SENSORS, true);
|
view->setColumnHidden(CylindersModel::SENSORS, true);
|
||||||
view->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate(this));
|
view->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate(this));
|
||||||
auto tankUseDelegate = new TankUseDelegate(this);
|
auto tankUseDelegate = new TankUseDelegate(this);
|
||||||
tankUseDelegate->setCurrentDC(planned_dive.get_dc(dcNr));
|
tankUseDelegate->setDiveDc(planned_dive, dcNr);
|
||||||
view->setItemDelegateForColumn(CylindersModel::USE, tankUseDelegate);
|
view->setItemDelegateForColumn(CylindersModel::USE, tankUseDelegate);
|
||||||
connect(ui.cylinderTableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addCylinder_clicked);
|
connect(ui.cylinderTableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addCylinder_clicked);
|
||||||
connect(ui.tableWidget, &TableView::addButtonClicked, plannerModel, &DivePlannerPointsModel::addDefaultStop);
|
|
||||||
connect(cylinders, &CylindersModel::dataChanged, plannerModel, &DivePlannerPointsModel::emitDataChanged);
|
connect(cylinders, &CylindersModel::dataChanged, plannerModel, &DivePlannerPointsModel::emitDataChanged);
|
||||||
connect(cylinders, &CylindersModel::dataChanged, plannerModel, &DivePlannerPointsModel::cylinderModelEdited);
|
connect(cylinders, &CylindersModel::dataChanged, plannerModel, &DivePlannerPointsModel::cylinderModelEdited);
|
||||||
connect(cylinders, &CylindersModel::rowsInserted, plannerModel, &DivePlannerPointsModel::cylinderModelEdited);
|
connect(cylinders, &CylindersModel::rowsInserted, plannerModel, &DivePlannerPointsModel::cylinderModelEdited);
|
||||||
connect(cylinders, &CylindersModel::rowsRemoved, plannerModel, &DivePlannerPointsModel::cylinderModelEdited);
|
connect(cylinders, &CylindersModel::rowsRemoved, plannerModel, &DivePlannerPointsModel::cylinderModelEdited);
|
||||||
|
|
||||||
ui.tableWidget->setBtnToolTip(tr("Add dive data point"));
|
ui.waterType->setItemData(0, FRESHWATER_SALINITY);
|
||||||
|
ui.waterType->setItemData(1, SEAWATER_SALINITY);
|
||||||
|
ui.waterType->setItemData(2, EN13319_SALINITY);
|
||||||
|
waterTypeUpdateTexts();
|
||||||
|
|
||||||
connect(ui.startTime, &QDateEdit::timeChanged, plannerModel, &DivePlannerPointsModel::setStartTime);
|
connect(ui.startTime, &QDateEdit::timeChanged, plannerModel, &DivePlannerPointsModel::setStartTime);
|
||||||
connect(ui.dateEdit, &QDateEdit::dateChanged, plannerModel, &DivePlannerPointsModel::setStartDate);
|
connect(ui.dateEdit, &QDateEdit::dateChanged, plannerModel, &DivePlannerPointsModel::setStartDate);
|
||||||
|
connect(ui.divemode, QOverload<int>::of(&QComboBox::currentIndexChanged), parent, &PlannerWidgets::setDiveMode);
|
||||||
connect(ui.ATMPressure, QOverload<int>::of(&QSpinBox::valueChanged), this, &DivePlannerWidget::atmPressureChanged);
|
connect(ui.ATMPressure, QOverload<int>::of(&QSpinBox::valueChanged), this, &DivePlannerWidget::atmPressureChanged);
|
||||||
connect(ui.atmHeight, QOverload<int>::of(&QSpinBox::valueChanged), this, &DivePlannerWidget::heightChanged);
|
connect(ui.atmHeight, QOverload<int>::of(&QSpinBox::valueChanged), this, &DivePlannerWidget::heightChanged);
|
||||||
connect(ui.waterType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DivePlannerWidget::waterTypeChanged);
|
connect(ui.waterType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DivePlannerWidget::waterTypeChanged);
|
||||||
|
@ -77,14 +86,14 @@ DivePlannerWidget::DivePlannerWidget(dive &planned_dive, int dcNr, PlannerWidget
|
||||||
QShortcut *closeKey = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
QShortcut *closeKey = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||||
connect(closeKey, &QShortcut::activated, plannerModel, &DivePlannerPointsModel::cancelPlan);
|
connect(closeKey, &QShortcut::activated, plannerModel, &DivePlannerPointsModel::cancelPlan);
|
||||||
|
|
||||||
// This makes shure the spinbox gets a setMinimum(0) on it so we can't have negative time or depth.
|
// This makes sure the spinbox gets a setMinimum(0) on it so we can't have negative time or depth.
|
||||||
// Limit segments to a depth of 1000 m/3300 ft and a duration of 100 h. Setting the limit for
|
// Limit segments to a depth of 1000 m/3300 ft and a duration of 100 h. Setting the limit for
|
||||||
// the depth will be done in settingChanged() since this depends on the chosen units.
|
// the depth will be done in settingChanged() since this depends on the chosen units.
|
||||||
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::RUNTIME, new SpinBoxDelegate(0, INT_MAX, 1, this));
|
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::RUNTIME, new SpinBoxDelegate(0, INT_MAX, 1, this));
|
||||||
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::DURATION, new SpinBoxDelegate(0, 6000, 1, this));
|
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::DURATION, new SpinBoxDelegate(0, 6000, 1, this));
|
||||||
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::CCSETPOINT, new DoubleSpinBoxDelegate(0, 2, 0.01, this));
|
ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::CCSETPOINT, new DoubleSpinBoxDelegate(0, 2, 0.01, this));
|
||||||
|
|
||||||
connect(&diveListNotifier, &DiveListNotifier::settingsChanged, this, &DivePlannerWidget::settingsChanged);
|
connect(&diveListNotifier, &DiveListNotifier::settingsChanged, parent, &PlannerWidgets::settingsChanged);
|
||||||
|
|
||||||
/* set defaults. */
|
/* set defaults. */
|
||||||
ui.ATMPressure->setValue(1013);
|
ui.ATMPressure->setValue(1013);
|
||||||
|
@ -116,11 +125,6 @@ void DivePlannerWidget::setSurfacePressure(int surface_pressure)
|
||||||
ui.ATMPressure->setValue(surface_pressure);
|
ui.ATMPressure->setValue(surface_pressure);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlannerSettingsWidget::setDiveMode(int mode)
|
|
||||||
{
|
|
||||||
ui.rebreathermode->setCurrentIndex(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DivePlannerWidget::setSalinity(int salinity)
|
void DivePlannerWidget::setSalinity(int salinity)
|
||||||
{
|
{
|
||||||
bool mapped = false;
|
bool mapped = false;
|
||||||
|
@ -212,7 +216,23 @@ void DivePlannerWidget::customSalinityChanged(double density)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlannerSettingsWidget::disableDecoElements(int mode, divemode_t rebreathermode)
|
void DivePlannerWidget::setDiveMode(int mode)
|
||||||
|
{
|
||||||
|
ui.divemode->setCurrentIndex(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivePlannerWidget::setColumnVisibility(int mode)
|
||||||
|
{
|
||||||
|
ui.tableWidget->view()->setColumnHidden(DivePlannerPointsModel::CCSETPOINT, mode != CCR);
|
||||||
|
ui.tableWidget->view()->setColumnHidden(DivePlannerPointsModel::DIVEMODE, mode == OC || (mode == CCR && !prefs.allowOcGasAsDiluent));
|
||||||
|
|
||||||
|
// This is needed as Qt sets the column width to 0 when hiding a column
|
||||||
|
ui.tableWidget->view()->setVisible(false); // This will cause the resize to include rows outside the current viewport
|
||||||
|
ui.tableWidget->view()->resizeColumnsToContents();
|
||||||
|
ui.tableWidget->view()->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlannerSettingsWidget::disableDecoElements(int mode, divemode_t divemode)
|
||||||
{
|
{
|
||||||
if (mode == RECREATIONAL) {
|
if (mode == RECREATIONAL) {
|
||||||
ui.label_gflow->setDisabled(false);
|
ui.label_gflow->setDisabled(false);
|
||||||
|
@ -265,7 +285,7 @@ void PlannerSettingsWidget::disableDecoElements(int mode, divemode_t rebreatherm
|
||||||
ui.backgasBreaks->setChecked(false);
|
ui.backgasBreaks->setChecked(false);
|
||||||
ui.backgasBreaks->blockSignals(false);
|
ui.backgasBreaks->blockSignals(false);
|
||||||
}
|
}
|
||||||
ui.bailout->setDisabled(!(rebreathermode == CCR || rebreathermode == PSCR));
|
ui.bailout->setDisabled(!IS_REBREATHER_MODE(divemode));
|
||||||
ui.bottompo2->setDisabled(false);
|
ui.bottompo2->setDisabled(false);
|
||||||
ui.decopo2->setDisabled(false);
|
ui.decopo2->setDisabled(false);
|
||||||
ui.safetystop->setDisabled(true);
|
ui.safetystop->setDisabled(true);
|
||||||
|
@ -277,7 +297,7 @@ void PlannerSettingsWidget::disableDecoElements(int mode, divemode_t rebreatherm
|
||||||
ui.min_switch_duration->setDisabled(false);
|
ui.min_switch_duration->setDisabled(false);
|
||||||
ui.surface_segment->setDisabled(false);
|
ui.surface_segment->setDisabled(false);
|
||||||
ui.label_min_switch_duration->setDisabled(false);
|
ui.label_min_switch_duration->setDisabled(false);
|
||||||
ui.sacfactor->setDisabled(false);
|
ui.sacfactor->setDisabled(IS_REBREATHER_MODE(divemode));
|
||||||
ui.problemsolvingtime->setDisabled(false);
|
ui.problemsolvingtime->setDisabled(false);
|
||||||
ui.sacfactor->setValue(PlannerShared::sacfactor());
|
ui.sacfactor->setValue(PlannerShared::sacfactor());
|
||||||
ui.problemsolvingtime->setValue(prefs.problemsolvingtime);
|
ui.problemsolvingtime->setValue(prefs.problemsolvingtime);
|
||||||
|
@ -299,7 +319,7 @@ void PlannerSettingsWidget::disableDecoElements(int mode, divemode_t rebreatherm
|
||||||
ui.backgasBreaks->setChecked(false);
|
ui.backgasBreaks->setChecked(false);
|
||||||
ui.backgasBreaks->blockSignals(false);
|
ui.backgasBreaks->blockSignals(false);
|
||||||
}
|
}
|
||||||
ui.bailout->setDisabled(!(rebreathermode == CCR || rebreathermode == PSCR));
|
ui.bailout->setDisabled(!IS_REBREATHER_MODE(divemode));
|
||||||
ui.bottompo2->setDisabled(false);
|
ui.bottompo2->setDisabled(false);
|
||||||
ui.decopo2->setDisabled(false);
|
ui.decopo2->setDisabled(false);
|
||||||
ui.safetystop->setDisabled(true);
|
ui.safetystop->setDisabled(true);
|
||||||
|
@ -311,7 +331,7 @@ void PlannerSettingsWidget::disableDecoElements(int mode, divemode_t rebreatherm
|
||||||
ui.min_switch_duration->setDisabled(false);
|
ui.min_switch_duration->setDisabled(false);
|
||||||
ui.surface_segment->setDisabled(false);
|
ui.surface_segment->setDisabled(false);
|
||||||
ui.label_min_switch_duration->setDisabled(false);
|
ui.label_min_switch_duration->setDisabled(false);
|
||||||
ui.sacfactor->setDisabled(false);
|
ui.sacfactor->setDisabled(IS_REBREATHER_MODE(divemode));
|
||||||
ui.problemsolvingtime->setDisabled(false);
|
ui.problemsolvingtime->setDisabled(false);
|
||||||
ui.sacfactor->setValue(PlannerShared::sacfactor());
|
ui.sacfactor->setValue(PlannerShared::sacfactor());
|
||||||
ui.problemsolvingtime->setValue(prefs.problemsolvingtime);
|
ui.problemsolvingtime->setValue(prefs.problemsolvingtime);
|
||||||
|
@ -359,7 +379,6 @@ PlannerSettingsWidget::PlannerSettingsWidget(PlannerWidgets *parent)
|
||||||
ui.decopo2->setValue(PlannerShared::decopo2());
|
ui.decopo2->setValue(PlannerShared::decopo2());
|
||||||
ui.backgasBreaks->setChecked(prefs.doo2breaks);
|
ui.backgasBreaks->setChecked(prefs.doo2breaks);
|
||||||
PlannerShared::set_dobailout(false);
|
PlannerShared::set_dobailout(false);
|
||||||
setBailoutVisibility(false);
|
|
||||||
ui.o2narcotic->setChecked(prefs.o2narcotic);
|
ui.o2narcotic->setChecked(prefs.o2narcotic);
|
||||||
ui.drop_stone_mode->setChecked(prefs.drop_stone_mode);
|
ui.drop_stone_mode->setChecked(prefs.drop_stone_mode);
|
||||||
ui.switch_at_req_stop->setChecked(prefs.switch_at_req_stop);
|
ui.switch_at_req_stop->setChecked(prefs.switch_at_req_stop);
|
||||||
|
@ -370,12 +389,6 @@ PlannerSettingsWidget::PlannerSettingsWidget(PlannerWidgets *parent)
|
||||||
ui.vpmb_deco->setChecked(prefs.planner_deco_mode == VPMB);
|
ui.vpmb_deco->setChecked(prefs.planner_deco_mode == VPMB);
|
||||||
disableDecoElements((int) prefs.planner_deco_mode, OC);
|
disableDecoElements((int) prefs.planner_deco_mode, OC);
|
||||||
|
|
||||||
// should be the same order as in dive_comp_type!
|
|
||||||
QStringList rebreather_modes = QStringList();
|
|
||||||
for (int i = 0; i < FREEDIVE; i++)
|
|
||||||
rebreather_modes.append(gettextFromC::tr(divemode_text_ui[i]));
|
|
||||||
ui.rebreathermode->insertItems(0, rebreather_modes);
|
|
||||||
|
|
||||||
connect(ui.recreational_deco, &QAbstractButton::clicked, [] { PlannerShared::set_planner_deco_mode(RECREATIONAL); });
|
connect(ui.recreational_deco, &QAbstractButton::clicked, [] { PlannerShared::set_planner_deco_mode(RECREATIONAL); });
|
||||||
connect(ui.buehlmann_deco, &QAbstractButton::clicked, [] { PlannerShared::set_planner_deco_mode(BUEHLMANN); });
|
connect(ui.buehlmann_deco, &QAbstractButton::clicked, [] { PlannerShared::set_planner_deco_mode(BUEHLMANN); });
|
||||||
connect(ui.vpmb_deco, &QAbstractButton::clicked, [] { PlannerShared::set_planner_deco_mode(VPMB); });
|
connect(ui.vpmb_deco, &QAbstractButton::clicked, [] { PlannerShared::set_planner_deco_mode(VPMB); });
|
||||||
|
@ -404,12 +417,10 @@ PlannerSettingsWidget::PlannerSettingsWidget(PlannerWidgets *parent)
|
||||||
connect(ui.switch_at_req_stop, &QAbstractButton::toggled, plannerModel, &DivePlannerPointsModel::setSwitchAtReqStop);
|
connect(ui.switch_at_req_stop, &QAbstractButton::toggled, plannerModel, &DivePlannerPointsModel::setSwitchAtReqStop);
|
||||||
connect(ui.min_switch_duration, QOverload<int>::of(&QSpinBox::valueChanged), &PlannerShared::set_min_switch_duration);
|
connect(ui.min_switch_duration, QOverload<int>::of(&QSpinBox::valueChanged), &PlannerShared::set_min_switch_duration);
|
||||||
connect(ui.surface_segment, QOverload<int>::of(&QSpinBox::valueChanged), &PlannerShared::set_surface_segment);
|
connect(ui.surface_segment, QOverload<int>::of(&QSpinBox::valueChanged), &PlannerShared::set_surface_segment);
|
||||||
connect(ui.rebreathermode, QOverload<int>::of(&QComboBox::currentIndexChanged), plannerModel, &DivePlannerPointsModel::setRebreatherMode);
|
|
||||||
connect(ui.rebreathermode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PlannerSettingsWidget::setBailoutVisibility);
|
|
||||||
|
|
||||||
connect(ui.recreational_deco, &QAbstractButton::clicked, [this, parent] { disableDecoElements(RECREATIONAL, parent->getRebreatherMode()); });
|
connect(ui.recreational_deco, &QAbstractButton::clicked, [this, parent] { disableDecoElements(RECREATIONAL, parent->getDiveMode()); });
|
||||||
connect(ui.buehlmann_deco, &QAbstractButton::clicked, [this, parent] { disableDecoElements(BUEHLMANN, parent->getRebreatherMode()); });
|
connect(ui.buehlmann_deco, &QAbstractButton::clicked, [this, parent] { disableDecoElements(BUEHLMANN, parent->getDiveMode()); });
|
||||||
connect(ui.vpmb_deco, &QAbstractButton::clicked, [this, parent] { disableDecoElements(VPMB, parent->getRebreatherMode()); });
|
connect(ui.vpmb_deco, &QAbstractButton::clicked, [this, parent] { disableDecoElements(VPMB, parent->getDiveMode()); });
|
||||||
|
|
||||||
connect(ui.sacfactor, QOverload<double>::of(&QDoubleSpinBox::valueChanged), &PlannerShared::set_sacfactor);
|
connect(ui.sacfactor, QOverload<double>::of(&QDoubleSpinBox::valueChanged), &PlannerShared::set_sacfactor);
|
||||||
connect(ui.problemsolvingtime, QOverload<int>::of(&QSpinBox::valueChanged), plannerModel, &DivePlannerPointsModel::setProblemSolvingTime);
|
connect(ui.problemsolvingtime, QOverload<int>::of(&QSpinBox::valueChanged), plannerModel, &DivePlannerPointsModel::setProblemSolvingTime);
|
||||||
|
@ -519,8 +530,9 @@ void PlannerSettingsWidget::setBackgasBreaks(bool dobreaks)
|
||||||
|
|
||||||
void PlannerSettingsWidget::setBailoutVisibility(int mode)
|
void PlannerSettingsWidget::setBailoutVisibility(int mode)
|
||||||
{
|
{
|
||||||
ui.bailout->setDisabled(!(mode == CCR || mode == PSCR));
|
bool isRebreatherMode = IS_REBREATHER_MODE(mode);
|
||||||
ui.sacFactor->setDisabled(mode == CCR);
|
ui.bailout->setDisabled(!isRebreatherMode);
|
||||||
|
ui.sacfactor->setDisabled(isRebreatherMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlannerDetails::PlannerDetails(QWidget *parent) : QWidget(parent)
|
PlannerDetails::PlannerDetails(QWidget *parent) : QWidget(parent)
|
||||||
|
@ -561,7 +573,7 @@ int PlannerWidgets::getDcNr()
|
||||||
return dcNr;
|
return dcNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
divemode_t PlannerWidgets::getRebreatherMode() const
|
divemode_t PlannerWidgets::getDiveMode() const
|
||||||
{
|
{
|
||||||
return planned_dive->get_dc(dcNr)->divemode;
|
return planned_dive->get_dc(dcNr)->divemode;
|
||||||
}
|
}
|
||||||
|
@ -575,13 +587,14 @@ void PlannerWidgets::preparePlanDive(const dive *currentDive, int currentDcNr)
|
||||||
|
|
||||||
// plan the dive in the same mode as the currently selected one
|
// plan the dive in the same mode as the currently selected one
|
||||||
if (currentDive) {
|
if (currentDive) {
|
||||||
plannerSettingsWidget.setDiveMode(currentDive->get_dc(currentDcNr)->divemode);
|
planned_dive->get_dc(dcNr)->divemode = currentDive->get_dc(currentDcNr)->divemode;
|
||||||
plannerSettingsWidget.setBailoutVisibility(currentDive->get_dc(currentDcNr)->divemode);
|
|
||||||
if (currentDive->salinity)
|
if (currentDive->salinity)
|
||||||
plannerWidget.setSalinity(currentDive->salinity);
|
plannerWidget.setSalinity(currentDive->salinity);
|
||||||
else // No salinity means salt water
|
else // No salinity means salt water
|
||||||
plannerWidget.setSalinity(SEAWATER_SALINITY);
|
plannerWidget.setSalinity(SEAWATER_SALINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDiveMode(getDiveMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlannerWidgets::planDive()
|
void PlannerWidgets::planDive()
|
||||||
|
@ -589,6 +602,7 @@ void PlannerWidgets::planDive()
|
||||||
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN);
|
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN);
|
||||||
|
|
||||||
plannerWidget.setReplanButton(false);
|
plannerWidget.setReplanButton(false);
|
||||||
|
|
||||||
plannerWidget.setupStartTime(timestampToDateTime(planned_dive->when)); // This will reload the profile!
|
plannerWidget.setupStartTime(timestampToDateTime(planned_dive->when)); // This will reload the profile!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,6 +610,8 @@ void PlannerWidgets::prepareReplanDive(const dive *currentDive, int currentDcNr)
|
||||||
{
|
{
|
||||||
copy_dive(currentDive, planned_dive.get());
|
copy_dive(currentDive, planned_dive.get());
|
||||||
dcNr = currentDcNr;
|
dcNr = currentDcNr;
|
||||||
|
|
||||||
|
setDiveMode(getDiveMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlannerWidgets::replanDive()
|
void PlannerWidgets::replanDive()
|
||||||
|
@ -609,6 +625,7 @@ void PlannerWidgets::replanDive()
|
||||||
plannerWidget.setSurfacePressure(planned_dive->surface_pressure.mbar);
|
plannerWidget.setSurfacePressure(planned_dive->surface_pressure.mbar);
|
||||||
if (planned_dive->salinity)
|
if (planned_dive->salinity)
|
||||||
plannerWidget.setSalinity(planned_dive->salinity);
|
plannerWidget.setSalinity(planned_dive->salinity);
|
||||||
|
|
||||||
reset_cylinders(planned_dive.get(), true);
|
reset_cylinders(planned_dive.get(), true);
|
||||||
DivePlannerPointsModel::instance()->cylindersModel()->updateDive(planned_dive.get(), dcNr);
|
DivePlannerPointsModel::instance()->cylindersModel()->updateDive(planned_dive.get(), dcNr);
|
||||||
}
|
}
|
||||||
|
@ -657,3 +674,16 @@ void PlannerWidgets::printDecoPlan()
|
||||||
plannerDetails.divePlanOutput()->setHtml(origPlan); // restore original plan
|
plannerDetails.divePlanOutput()->setHtml(origPlan); // restore original plan
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlannerWidgets::setDiveMode(int mode)
|
||||||
|
{
|
||||||
|
DivePlannerPointsModel::instance()->setDiveMode(mode);
|
||||||
|
plannerWidget.setColumnVisibility(mode);
|
||||||
|
plannerSettingsWidget.setBailoutVisibility(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlannerWidgets::settingsChanged()
|
||||||
|
{
|
||||||
|
plannerWidget.settingsChanged();
|
||||||
|
setDiveMode(getDiveMode());
|
||||||
|
}
|
||||||
|
|
|
@ -18,9 +18,11 @@ struct dive;
|
||||||
class DivePlannerWidget : public QWidget {
|
class DivePlannerWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit DivePlannerWidget(dive &planned_dive, int dcNr, PlannerWidgets *parent);
|
explicit DivePlannerWidget(const dive &planned_dive, int &dcNr, PlannerWidgets *parent);
|
||||||
~DivePlannerWidget();
|
~DivePlannerWidget();
|
||||||
void setReplanButton(bool replan);
|
void setReplanButton(bool replan);
|
||||||
|
void setColumnVisibility(int mode);
|
||||||
|
void setDiveMode(int mode);
|
||||||
public
|
public
|
||||||
slots:
|
slots:
|
||||||
void setupStartTime(QDateTime startTime);
|
void setupStartTime(QDateTime startTime);
|
||||||
|
@ -48,9 +50,8 @@ public
|
||||||
slots:
|
slots:
|
||||||
void settingsChanged();
|
void settingsChanged();
|
||||||
void setBackgasBreaks(bool dobreaks);
|
void setBackgasBreaks(bool dobreaks);
|
||||||
void disableDecoElements(int mode, divemode_t rebreathermode);
|
void disableDecoElements(int mode, divemode_t divemode);
|
||||||
void disableBackgasBreaks(bool enabled);
|
void disableBackgasBreaks(bool enabled);
|
||||||
void setDiveMode(int mode);
|
|
||||||
void setBailoutVisibility(int mode);
|
void setBailoutVisibility(int mode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -86,10 +87,12 @@ public:
|
||||||
void replanDive();
|
void replanDive();
|
||||||
struct dive *getDive() const;
|
struct dive *getDive() const;
|
||||||
int getDcNr();
|
int getDcNr();
|
||||||
divemode_t getRebreatherMode() const;
|
divemode_t getDiveMode() const;
|
||||||
|
void settingsChanged();
|
||||||
public
|
public
|
||||||
slots:
|
slots:
|
||||||
void printDecoPlan();
|
void printDecoPlan();
|
||||||
|
void setDiveMode(int mode);
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<dive> planned_dive;
|
std::unique_ptr<dive> planned_dive;
|
||||||
int dcNr;
|
int dcNr;
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0" colspan="2">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
@ -98,7 +98,30 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2" colspan="2">
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Dive mode</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QComboBox" name="divemode">
|
||||||
|
<property name="currentText">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="maxVisibleItems">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3" colspan="2">
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
@ -112,20 +135,20 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Altitude</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>ATM pressure</string>
|
<string>ATM pressure</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Altitude</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Water type</string>
|
<string>Water type</string>
|
||||||
|
@ -133,6 +156,25 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
|
<widget class="QSpinBox" name="ATMPressure">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string>mbar</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>689</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>1100</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
<widget class="QSpinBox" name="atmHeight">
|
<widget class="QSpinBox" name="atmHeight">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
@ -154,26 +196,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="3">
|
||||||
<widget class="QSpinBox" name="ATMPressure">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="suffix">
|
|
||||||
<string>mbar</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>689</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>1100</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2">
|
|
||||||
<widget class="QComboBox" name="waterType">
|
<widget class="QComboBox" name="waterType">
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -197,7 +220,7 @@
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="3">
|
<item row="3" column="4">
|
||||||
<widget class="QDoubleSpinBox" name="customSalinity">
|
<widget class="QDoubleSpinBox" name="customSalinity">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
|
@ -237,7 +260,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0" colspan="4">
|
<item row="4" column="0" colspan="5">
|
||||||
<widget class="TableView" name="cylinderTableWidget" native="true">
|
<widget class="TableView" name="cylinderTableWidget" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
@ -253,7 +276,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="4">
|
<item row="5" column="0" colspan="5">
|
||||||
<widget class="TableView" name="tableWidget" native="true">
|
<widget class="TableView" name="tableWidget" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||||
|
@ -285,6 +308,7 @@
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>startTime</tabstop>
|
<tabstop>startTime</tabstop>
|
||||||
|
<tabstop>divemode</tabstop>
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
<tabstop>scrollArea</tabstop>
|
<tabstop>scrollArea</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
|
|
|
@ -688,6 +688,7 @@ void MainWindow::on_actionDivePlanner_triggered()
|
||||||
setApplicationState(ApplicationState::PlanDive);
|
setApplicationState(ApplicationState::PlanDive);
|
||||||
|
|
||||||
disableShortcuts(true);
|
disableShortcuts(true);
|
||||||
|
profile->exitEditMode();
|
||||||
plannerWidgets->preparePlanDive(current_dive, profile->dc);
|
plannerWidgets->preparePlanDive(current_dive, profile->dc);
|
||||||
profile->setPlanState(plannerWidgets->getDive(), plannerWidgets->getDcNr());
|
profile->setPlanState(plannerWidgets->getDive(), plannerWidgets->getDcNr());
|
||||||
plannerWidgets->planDive();
|
plannerWidgets->planDive();
|
||||||
|
|
|
@ -246,24 +246,32 @@ void TankInfoDelegate::editorClosed(QWidget *, QAbstractItemDelegate::EndEditHin
|
||||||
mymodel->setData(IDX(CylindersModel::TYPE), currCombo.activeText, CylindersModel::COMMIT_ROLE);
|
mymodel->setData(IDX(CylindersModel::TYPE), currCombo.activeText, CylindersModel::COMMIT_ROLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
TankUseDelegate::TankUseDelegate(QObject *parent) : QStyledItemDelegate(parent), currentdc(nullptr)
|
TankUseDelegate::TankUseDelegate(QObject *parent) : QStyledItemDelegate(parent), currentDive(nullptr), currentDcNr(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void TankUseDelegate::setCurrentDC(divecomputer *dc)
|
void TankUseDelegate::setDiveDc(const dive &d, int &dcNr)
|
||||||
{
|
{
|
||||||
currentdc = dc;
|
currentDive = &d;
|
||||||
|
currentDcNr = &dcNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *TankUseDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
|
QWidget *TankUseDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
|
||||||
{
|
{
|
||||||
QComboBox *comboBox = new QComboBox(parent);
|
QComboBox *comboBox = new QComboBox(parent);
|
||||||
if (!currentdc)
|
const divecomputer *dc = currentDive->get_dc(*currentDcNr);
|
||||||
|
if (!dc)
|
||||||
return comboBox;
|
return comboBox;
|
||||||
bool isCcrDive = currentdc->divemode == CCR;
|
bool isCcrDive = dc->divemode == CCR;
|
||||||
|
bool isFreeDive = dc->divemode == FREEDIVE;
|
||||||
for (int i = 0; i < NUM_GAS_USE; i++) {
|
for (int i = 0; i < NUM_GAS_USE; i++) {
|
||||||
if (isCcrDive || (i != DILUENT && i != OXYGEN))
|
if (isFreeDive && i != NOT_USED)
|
||||||
comboBox->addItem(gettextFromC::tr(cylinderuse_text[i]));
|
continue;
|
||||||
|
|
||||||
|
if (!isCcrDive && (i == DILUENT || i == OXYGEN))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
comboBox->addItem(gettextFromC::tr(cylinderuse_text[i]));
|
||||||
}
|
}
|
||||||
return comboBox;
|
return comboBox;
|
||||||
}
|
}
|
||||||
|
@ -350,21 +358,20 @@ WSInfoDelegate::WSInfoDelegate(QObject *parent) : ComboBoxDelegate(&createWSInfo
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AirTypesDelegate::editorClosed(QWidget *, QAbstractItemDelegate::EndEditHint)
|
void GasTypesDelegate::editorClosed(QWidget *, QAbstractItemDelegate::EndEditHint)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AirTypesDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
void GasTypesDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
QComboBox *combo = qobject_cast<QComboBox *>(editor);
|
QComboBox *combo = qobject_cast<QComboBox *>(editor);
|
||||||
model->setData(index, QVariant(combo->currentIndex()));
|
model->setData(index, combo->currentData(Qt::UserRole));
|
||||||
}
|
}
|
||||||
|
|
||||||
AirTypesDelegate::AirTypesDelegate(const dive &d, QObject *parent) :
|
GasTypesDelegate::GasTypesDelegate(const dive &d, int &dcNr, QObject *parent) :
|
||||||
ComboBoxDelegate([&d] (QWidget *parent) { return new GasSelectionModel(d, parent); },
|
ComboBoxDelegate([&d, &dcNr] (QWidget *parent) { return new GasSelectionModel(d, dcNr, parent); }, parent, false)
|
||||||
parent, false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,15 +384,11 @@ void DiveTypesDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
QComboBox *combo = qobject_cast<QComboBox *>(editor);
|
QComboBox *combo = qobject_cast<QComboBox *>(editor);
|
||||||
model->setData(index, QVariant(combo->currentIndex()));
|
model->setData(index, combo->currentData(Qt::UserRole));
|
||||||
}
|
}
|
||||||
|
|
||||||
static QAbstractItemModel *createDiveTypeSelectionModel(QWidget *parent)
|
DiveTypesDelegate::DiveTypesDelegate(const dive &d, int &dcNr, QObject *parent) :
|
||||||
{
|
ComboBoxDelegate([&d, &dcNr] (QWidget *parent) { return new DiveTypeSelectionModel(d, dcNr, parent); }, parent, false)
|
||||||
return new DiveTypeSelectionModel(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
DiveTypesDelegate::DiveTypesDelegate(QObject *parent) : ComboBoxDelegate(&createDiveTypeSelectionModel, parent, false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,12 +75,13 @@ class TankUseDelegate : public QStyledItemDelegate {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit TankUseDelegate(QObject *parent = 0);
|
explicit TankUseDelegate(QObject *parent = 0);
|
||||||
void setCurrentDC(divecomputer *dc);
|
void setDiveDc(const dive &d, int &dcNr);
|
||||||
private:
|
private:
|
||||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||||
divecomputer *currentdc;
|
const dive *currentDive;
|
||||||
|
int *currentDcNr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SensorDelegate : public QStyledItemDelegate {
|
class SensorDelegate : public QStyledItemDelegate {
|
||||||
|
@ -103,10 +104,10 @@ private:
|
||||||
void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override;
|
void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AirTypesDelegate : public ComboBoxDelegate {
|
class GasTypesDelegate : public ComboBoxDelegate {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit AirTypesDelegate(const dive &d, QObject *parent = 0);
|
explicit GasTypesDelegate(const dive &d, int &dcNr, QObject *parent = 0);
|
||||||
private:
|
private:
|
||||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||||
void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override;
|
void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override;
|
||||||
|
@ -115,7 +116,7 @@ private:
|
||||||
class DiveTypesDelegate : public ComboBoxDelegate {
|
class DiveTypesDelegate : public ComboBoxDelegate {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit DiveTypesDelegate(QObject *parent = 0);
|
explicit DiveTypesDelegate(const dive &d, int &dcNr, QObject *parent = 0);
|
||||||
private:
|
private:
|
||||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||||
void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override;
|
void editorClosed(QWidget *widget, QAbstractItemDelegate::EndEditHint hint) override;
|
||||||
|
|
|
@ -255,7 +255,7 @@
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="4" column="2">
|
<item row="3" column="2">
|
||||||
<widget class="QSpinBox" name="reserve_gas">
|
<widget class="QSpinBox" name="reserve_gas">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>bar</string>
|
<string>bar</string>
|
||||||
|
@ -274,7 +274,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="5" column="1">
|
||||||
<spacer name="verticalSpacer_6">
|
<spacer name="verticalSpacer_6">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
@ -287,7 +287,7 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="22" column="1" colspan="2">
|
<item row="21" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="switch_at_req_stop">
|
<widget class="QCheckBox" name="switch_at_req_stop">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Postpone gas change if a stop is not required</string>
|
<string>Postpone gas change if a stop is not required</string>
|
||||||
|
@ -297,14 +297,14 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="18" column="1" colspan="2">
|
<item row="17" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="lastStop">
|
<widget class="QCheckBox" name="lastStop">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Last stop at 6m</string>
|
<string>Last stop at 6m</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="15" column="2">
|
<item row="14" column="2">
|
||||||
<widget class="QSpinBox" name="vpmb_conservatism">
|
<widget class="QSpinBox" name="vpmb_conservatism">
|
||||||
<property name="prefix">
|
<property name="prefix">
|
||||||
<string>+</string>
|
<string>+</string>
|
||||||
|
@ -314,7 +314,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="12" column="2">
|
<item row="11" column="2">
|
||||||
<widget class="QSpinBox" name="gfhigh">
|
<widget class="QSpinBox" name="gfhigh">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>%</string>
|
<string>%</string>
|
||||||
|
@ -327,7 +327,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="23" column="2">
|
<item row="22" column="2">
|
||||||
<widget class="QSpinBox" name="min_switch_duration">
|
<widget class="QSpinBox" name="min_switch_duration">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>min</string>
|
<string>min</string>
|
||||||
|
@ -346,14 +346,14 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="20" column="1" colspan="2">
|
<item row="19" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="backgasBreaks">
|
<widget class="QCheckBox" name="backgasBreaks">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Plan backgas breaks</string>
|
<string>Plan backgas breaks</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="25" column="1">
|
<item row="24" column="1">
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
@ -366,21 +366,21 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="23" column="1">
|
<item row="22" column="1">
|
||||||
<widget class="QLabel" name="label_min_switch_duration">
|
<widget class="QLabel" name="label_min_switch_duration">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Min. switch duration O₂% below 100%</string>
|
<string>Min. switch duration O₂% below 100%</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="17" column="1" colspan="2">
|
<item row="16" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="drop_stone_mode">
|
<widget class="QCheckBox" name="drop_stone_mode">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Drop to first depth</string>
|
<string>Drop to first depth</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="2">
|
<item row="10" column="2">
|
||||||
<widget class="QSpinBox" name="gflow">
|
<widget class="QSpinBox" name="gflow">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>%</string>
|
<string>%</string>
|
||||||
|
@ -393,7 +393,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QLabel" name="label_gflow">
|
<widget class="QLabel" name="label_gflow">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>GFLow</string>
|
<string>GFLow</string>
|
||||||
|
@ -403,7 +403,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="12" column="1">
|
<item row="11" column="1">
|
||||||
<widget class="QLabel" name="label_gfhigh">
|
<widget class="QLabel" name="label_gfhigh">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>GFHigh</string>
|
<string>GFHigh</string>
|
||||||
|
@ -413,7 +413,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QRadioButton" name="recreational_deco">
|
<widget class="QRadioButton" name="recreational_deco">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Maximize bottom time allowed by gas and no decompression limits</string>
|
<string>Maximize bottom time allowed by gas and no decompression limits</string>
|
||||||
|
@ -423,7 +423,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="15" column="1">
|
<item row="14" column="1">
|
||||||
<widget class="QLabel" name="label_vpmb_conservatism">
|
<widget class="QLabel" name="label_vpmb_conservatism">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Conservatism level</string>
|
<string>Conservatism level</string>
|
||||||
|
@ -440,7 +440,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1" alignment="Qt::AlignHCenter">
|
<item row="4" column="1" alignment="Qt::AlignHCenter">
|
||||||
<widget class="QCheckBox" name="safetystop">
|
<widget class="QCheckBox" name="safetystop">
|
||||||
<property name="layoutDirection">
|
<property name="layoutDirection">
|
||||||
<enum>Qt::LeftToRight</enum>
|
<enum>Qt::LeftToRight</enum>
|
||||||
|
@ -453,7 +453,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" column="1">
|
<item row="12" column="1">
|
||||||
<spacer name="verticalSpacer_7">
|
<spacer name="verticalSpacer_7">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
@ -466,7 +466,7 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="16" column="1">
|
<item row="15" column="1">
|
||||||
<spacer name="verticalSpacer_5">
|
<spacer name="verticalSpacer_5">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
@ -479,24 +479,7 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="6" column="1">
|
||||||
<widget class="QComboBox" name="rebreathermode">
|
|
||||||
<property name="currentText">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="maxVisibleItems">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLabel" name="label_dive_type">
|
|
||||||
<property name="text">
|
|
||||||
<string>Dive mode</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QRadioButton" name="buehlmann_deco">
|
<widget class="QRadioButton" name="buehlmann_deco">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bühlmann deco</string>
|
<string>Bühlmann deco</string>
|
||||||
|
@ -506,7 +489,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QLabel" name="label_reserve_gas">
|
<widget class="QLabel" name="label_reserve_gas">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Reserve gas</string>
|
<string>Reserve gas</string>
|
||||||
|
@ -516,21 +499,21 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QCheckBox" name="bailout">
|
<widget class="QCheckBox" name="bailout">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bailout: Deco on OC</string>
|
<string>Rebreather: Bailout / Deco on OC</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="24" column="1">
|
<item row="23" column="1">
|
||||||
<widget class="QLabel" name="label_surface_segment">
|
<widget class="QLabel" name="label_surface_segment">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Surface segment</string>
|
<string>Surface segment</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="24" column="2">
|
<item row="23" column="2">
|
||||||
<widget class="QSpinBox" name="surface_segment">
|
<widget class="QSpinBox" name="surface_segment">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>min</string>
|
<string>min</string>
|
||||||
|
@ -777,7 +760,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="sacFactor">
|
<widget class="QLabel" name="label_sacfactor">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>SAC factor</string>
|
<string>SAC factor</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -857,7 +840,7 @@
|
||||||
<tabstop>ascRateStops</tabstop>
|
<tabstop>ascRateStops</tabstop>
|
||||||
<tabstop>ascRateLast6m</tabstop>
|
<tabstop>ascRateLast6m</tabstop>
|
||||||
<tabstop>descRate</tabstop>
|
<tabstop>descRate</tabstop>
|
||||||
<tabstop>rebreathermode</tabstop>
|
<tabstop>divemode</tabstop>
|
||||||
<tabstop>recreational_deco</tabstop>
|
<tabstop>recreational_deco</tabstop>
|
||||||
<tabstop>reserve_gas</tabstop>
|
<tabstop>reserve_gas</tabstop>
|
||||||
<tabstop>safetystop</tabstop>
|
<tabstop>safetystop</tabstop>
|
||||||
|
|
|
@ -50,6 +50,7 @@ void PreferencesGraph::refreshSettings()
|
||||||
ui->pscrfactor->setValue(lrint(1000.0 / prefs.pscr_ratio));
|
ui->pscrfactor->setValue(lrint(1000.0 / prefs.pscr_ratio));
|
||||||
|
|
||||||
ui->show_icd->setChecked(prefs.show_icd);
|
ui->show_icd->setChecked(prefs.show_icd);
|
||||||
|
ui->allowOcGasAsDiluent->setChecked(prefs.allowOcGasAsDiluent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreferencesGraph::syncSettings()
|
void PreferencesGraph::syncSettings()
|
||||||
|
@ -75,6 +76,7 @@ void PreferencesGraph::syncSettings()
|
||||||
qPrefTechnicalDetails::set_show_scr_ocpo2(ui->show_scr_ocpo2->isChecked());
|
qPrefTechnicalDetails::set_show_scr_ocpo2(ui->show_scr_ocpo2->isChecked());
|
||||||
qPrefTechnicalDetails::set_show_icd(ui->show_icd->isChecked());
|
qPrefTechnicalDetails::set_show_icd(ui->show_icd->isChecked());
|
||||||
qPrefTechnicalDetails::set_display_deco_mode(ui->vpmb->isChecked() ? VPMB : BUEHLMANN);
|
qPrefTechnicalDetails::set_display_deco_mode(ui->vpmb->isChecked() ? VPMB : BUEHLMANN);
|
||||||
|
qPrefTechnicalDetails::set_allowOcGasAsDiluent(ui->allowOcGasAsDiluent->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *danger_gf(int gf)
|
static const char *danger_gf(int gf)
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Gas pressure display setup</string>
|
<string>Gas pressure display setup</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout_1">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_12">
|
<widget class="QLabel" name="label_12">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
|
@ -125,21 +125,30 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_5">
|
||||||
|
<property name="title">
|
||||||
|
<string>Rebreather setup</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_26">
|
<widget class="QLabel" name="label_26">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>CCR options:</string>
|
<string>CCR options:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_27">
|
<widget class="QLabel" name="label_27">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Dive planner default setpoint</string>
|
<string>Dive planner default setpoint</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="2">
|
<item row="0" column="2">
|
||||||
<widget class="QDoubleSpinBox" name="defaultSetpoint">
|
<widget class="QDoubleSpinBox" name="defaultSetpoint">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>bar</string>
|
<string>bar</string>
|
||||||
|
@ -155,38 +164,35 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1" colspan="2">
|
<item row="1" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="show_ccr_sensors">
|
<widget class="QCheckBox" name="show_ccr_sensors">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show O₂ sensor values when viewing pO₂</string>
|
<string>Show O₂ sensor values when viewing pO₂</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1" colspan="2">
|
<item row="2" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="show_ccr_setpoint">
|
<widget class="QCheckBox" name="show_ccr_setpoint">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show CCR setpoints when viewing pO₂</string>
|
<string>Show CCR setpoints when viewing pO₂</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="pSCR">
|
<widget class="QLabel" name="pSCR">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>pSCR options:</string>
|
<string>pSCR options:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QLabel" name="MetabolicRate">
|
<widget class="QLabel" name="MetabolicRate">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>pSCR metabolic rate O₂</string>
|
<string>pSCR metabolic rate O₂</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="2">
|
<item row="3" column="2">
|
||||||
<widget class="QDoubleSpinBox" name="psro2rate">
|
<widget class="QDoubleSpinBox" name="psro2rate">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string>ℓ/min</string>
|
<string>ℓ/min</string>
|
||||||
|
@ -196,7 +202,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="3">
|
<item row="3" column="3">
|
||||||
<widget class="QLabel" name="label_28">
|
<widget class="QLabel" name="label_28">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Dilution ratio</string>
|
<string>Dilution ratio</string>
|
||||||
|
@ -206,7 +212,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="4">
|
<item row="3" column="4">
|
||||||
<widget class="QSpinBox" name="pscrfactor">
|
<widget class="QSpinBox" name="pscrfactor">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string/>
|
<string/>
|
||||||
|
@ -216,29 +222,45 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QCheckBox" name="show_scr_ocpo2">
|
<widget class="QCheckBox" name="show_scr_ocpo2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show equivalent OC pO₂ with pSCR pO₂</string>
|
<string>Show equivalent OC pO₂ with pSCR pO₂</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0">
|
|
||||||
<widget class="QCheckBox" name="show_icd">
|
|
||||||
<property name="text">
|
|
||||||
<string>Show warnings for isobaric counterdiffusion</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_5">
|
<widget class="QGroupBox" name="groupBox_6">
|
||||||
|
<property name="title">
|
||||||
|
<string>Planner setup</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="show_icd">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show warnings for isobaric counterdiffusion</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="allowOcGasAsDiluent">
|
||||||
|
<property name="text">
|
||||||
|
<string>Allow open circuit gas to be used as diluent for CCR</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_7">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Ceiling display setup</string>
|
<string>Ceiling display setup</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
<item row="3" column="3">
|
<item row="3" column="3">
|
||||||
<widget class="QLabel" name="label_GFhigh">
|
<widget class="QLabel" name="label_GFhigh">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|
|
@ -306,7 +306,6 @@ void ProfileWidget::cylindersChanged(struct dive *changed, int pos)
|
||||||
|
|
||||||
void ProfileWidget::setPlanState(const struct dive *d, int dcNr)
|
void ProfileWidget::setPlanState(const struct dive *d, int dcNr)
|
||||||
{
|
{
|
||||||
exitEditMode();
|
|
||||||
dc = dcNr;
|
dc = dcNr;
|
||||||
view->setPlanState(d, dcNr);
|
view->setPlanState(d, dcNr);
|
||||||
setDive(d, dcNr);
|
setDive(d, dcNr);
|
||||||
|
|
|
@ -26,6 +26,7 @@ public:
|
||||||
void setEnabledToolbar(bool enabled);
|
void setEnabledToolbar(bool enabled);
|
||||||
void nextDC();
|
void nextDC();
|
||||||
void prevDC();
|
void prevDC();
|
||||||
|
void exitEditMode();
|
||||||
dive *d;
|
dive *d;
|
||||||
int dc;
|
int dc;
|
||||||
private
|
private
|
||||||
|
@ -45,7 +46,6 @@ private:
|
||||||
QStackedWidget *stack;
|
QStackedWidget *stack;
|
||||||
void setDive(const struct dive *d, int dcNr);
|
void setDive(const struct dive *d, int dcNr);
|
||||||
void editDive();
|
void editDive();
|
||||||
void exitEditMode();
|
|
||||||
void rotateDC(int dir);
|
void rotateDC(int dir);
|
||||||
std::unique_ptr<dive> editedDive;
|
std::unique_ptr<dive> editedDive;
|
||||||
bool placingCommand;
|
bool placingCommand;
|
||||||
|
|
|
@ -143,7 +143,7 @@ void TabDiveEquipment::updateData(const std::vector<dive *> &, dive *currentDive
|
||||||
cylindersModel->updateDive(currentDive, currentDC);
|
cylindersModel->updateDive(currentDive, currentDC);
|
||||||
weightModel->updateDive(currentDive);
|
weightModel->updateDive(currentDive);
|
||||||
sensorDelegate.setCurrentDC(dc);
|
sensorDelegate.setCurrentDC(dc);
|
||||||
tankUseDelegate.setCurrentDC(dc);
|
tankUseDelegate.setDiveDc(*currentDive, currentDC);
|
||||||
|
|
||||||
if (currentDive && !currentDive->suit.empty())
|
if (currentDive && !currentDive->suit.empty())
|
||||||
ui.suit->setText(QString::fromStdString(currentDive->suit));
|
ui.suit->setText(QString::fromStdString(currentDive->suit));
|
||||||
|
|
|
@ -235,7 +235,7 @@ public slots:
|
||||||
void set_ascrate75(int value) { DivePlannerPointsModel::instance()->setAscrate75Display(value); }
|
void set_ascrate75(int value) { DivePlannerPointsModel::instance()->setAscrate75Display(value); }
|
||||||
void set_descrate(int value) { DivePlannerPointsModel::instance()->setDescrateDisplay(value); }
|
void set_descrate(int value) { DivePlannerPointsModel::instance()->setDescrateDisplay(value); }
|
||||||
|
|
||||||
void set_dive_mode(DIVE_MODE value) { DivePlannerPointsModel::instance()->setRebreatherMode((int)value); }
|
void set_dive_mode(DIVE_MODE value) { DivePlannerPointsModel::instance()->setDiveMode((int)value); }
|
||||||
void set_planner_deco_mode(DECO_MODE value) { PlannerShared::set_planner_deco_mode((deco_mode)value); }
|
void set_planner_deco_mode(DECO_MODE value) { PlannerShared::set_planner_deco_mode((deco_mode)value); }
|
||||||
void set_reserve_gas(int value) { PlannerShared::set_reserve_gas(value); }
|
void set_reserve_gas(int value) { PlannerShared::set_reserve_gas(value); }
|
||||||
void set_safetystop(bool value) { DivePlannerPointsModel::instance()->setSafetyStop(value); }
|
void set_safetystop(bool value) { DivePlannerPointsModel::instance()->setSafetyStop(value); }
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
DiveHandler::DiveHandler(const struct dive *d) : dive(d)
|
DiveHandler::DiveHandler(const struct dive *d, int currentDcNr) : dive(d), dcNr(currentDcNr)
|
||||||
{
|
{
|
||||||
setRect(-5, -5, 10, 10);
|
setRect(-5, -5, 10, 10);
|
||||||
setFlags(ItemIgnoresTransformations | ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges);
|
setFlags(ItemIgnoresTransformations | ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges);
|
||||||
|
@ -31,14 +31,15 @@ void DiveHandler::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
|
||||||
QMenu m;
|
QMenu m;
|
||||||
// Don't have a gas selection for the last point
|
// Don't have a gas selection for the last point
|
||||||
emit released();
|
emit released();
|
||||||
|
|
||||||
DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
|
DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
|
||||||
QModelIndex index = plannerModel->index(parentIndex(), DivePlannerPointsModel::GAS);
|
QModelIndex index = plannerModel->index(parentIndex(), DivePlannerPointsModel::GAS);
|
||||||
if (index.sibling(index.row() + 1, index.column()).isValid()) {
|
if (index.sibling(index.row() + 1, index.column()).isValid()) {
|
||||||
QStringList gases = get_dive_gas_list(dive);
|
std::vector<std::pair<int, QString>> gases = get_dive_gas_list(dive, dcNr, true);
|
||||||
for (int i = 0; i < gases.size(); i++) {
|
for (unsigned i = 0; i < gases.size(); i++) {
|
||||||
QAction *action = new QAction(&m);
|
QAction *action = new QAction(&m);
|
||||||
action->setText(gases[i]);
|
action->setText(gases[i].second);
|
||||||
action->setData(i);
|
action->setData(gases[i].first);
|
||||||
connect(action, &QAction::triggered, this, &DiveHandler::changeGas);
|
connect(action, &QAction::triggered, this, &DiveHandler::changeGas);
|
||||||
m.addAction(action);
|
m.addAction(action);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ struct dive;
|
||||||
class DiveHandler : public QObject, public QGraphicsEllipseItem {
|
class DiveHandler : public QObject, public QGraphicsEllipseItem {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DiveHandler(const struct dive *d);
|
DiveHandler(const struct dive *d, int currentDcNr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
|
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
|
||||||
|
@ -29,6 +29,7 @@ slots:
|
||||||
void changeGas();
|
void changeGas();
|
||||||
private:
|
private:
|
||||||
const struct dive *dive;
|
const struct dive *dive;
|
||||||
|
int dcNr;
|
||||||
QElapsedTimer t;
|
QElapsedTimer t;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -656,7 +656,7 @@ void DiveGasPressureItem::plotGasValue(double mbar, double sec, const cylinder_t
|
||||||
QString gas = get_gas_string(cylinder->gasmix);
|
QString gas = get_gas_string(cylinder->gasmix);
|
||||||
QString label;
|
QString label;
|
||||||
if (showDescription)
|
if (showDescription)
|
||||||
label = QStringLiteral("(%1) %2").arg(QString::fromStdString(cylinder->type.description), gas);
|
label = QStringLiteral("(%1) %2").arg(QString::fromStdString(cylinder->type.description), std::move(gas));
|
||||||
else
|
else
|
||||||
label = gas;
|
label = gas;
|
||||||
auto text = std::make_unique<DiveTextItem>(dpr, 1.0, align, this);
|
auto text = std::make_unique<DiveTextItem>(dpr, 1.0, align, this);
|
||||||
|
|
|
@ -500,16 +500,6 @@ struct int ProfileWidget2::getEntryFromPos(QPointF pos)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SUBSURFACE_MOBILE
|
#ifndef SUBSURFACE_MOBILE
|
||||||
/// Prints cylinder information for display.
|
|
||||||
/// eg : "Cyl 1 (AL80 EAN32)"
|
|
||||||
static QString printCylinderDescription(int i, const cylinder_t &cylinder)
|
|
||||||
{
|
|
||||||
QString label = gettextFromC::tr("Cyl") + QString(" %1").arg(i+1);
|
|
||||||
QString mix = get_gas_string(cylinder.gasmix);
|
|
||||||
label += QString(" (%2 %3)").arg(QString::fromStdString(cylinder.type.description)).arg(mix);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isDiveTextItem(const QGraphicsItem *item, const DiveTextItem *textItem)
|
static bool isDiveTextItem(const QGraphicsItem *item, const DiveTextItem *textItem)
|
||||||
{
|
{
|
||||||
while (item) {
|
while (item) {
|
||||||
|
@ -520,6 +510,16 @@ static bool isDiveTextItem(const QGraphicsItem *item, const DiveTextItem *textIt
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProfileWidget2::addGasChangeMenu(QMenu &m, QString menuTitle, const struct dive &d, int dcNr, int changeTime)
|
||||||
|
{
|
||||||
|
QMenu *gasChange = m.addMenu(menuTitle);
|
||||||
|
std::vector<std::pair<int, QString>> gases = get_dive_gas_list(&d, dcNr, true);
|
||||||
|
for (unsigned i = 0; i < gases.size(); i++) {
|
||||||
|
int cylinderIndex = gases[i].first;
|
||||||
|
gasChange->addAction(gases[i].second, [this, cylinderIndex, changeTime] { addGasSwitch(cylinderIndex, changeTime); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
|
void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
|
||||||
{
|
{
|
||||||
if (currentState == EDIT || currentState == PLAN) {
|
if (currentState == EDIT || currentState == PLAN) {
|
||||||
|
@ -558,19 +558,10 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event)
|
||||||
|
|
||||||
// Add or edit Gas Change
|
// Add or edit Gas Change
|
||||||
if (d && item && item->ev.is_gaschange()) {
|
if (d && item && item->ev.is_gaschange()) {
|
||||||
int eventTime = item->ev.time.seconds;
|
addGasChangeMenu(m, tr("Edit Gas Change"), *d, dc, item->ev.time.seconds);
|
||||||
QMenu *gasChange = m.addMenu(tr("Edit Gas Change"));
|
|
||||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
|
||||||
QString label = printCylinderDescription(i, cyl);
|
|
||||||
gasChange->addAction(label, [this, idx = i, eventTime] { addGasSwitch(idx, eventTime); });
|
|
||||||
}
|
|
||||||
} else if (d && d->cylinders.size() > 1) {
|
} else if (d && d->cylinders.size() > 1) {
|
||||||
// if we have more than one gas, offer to switch to another one
|
// if we have more than one gas, offer to switch to another one
|
||||||
QMenu *gasChange = m.addMenu(tr("Add gas change"));
|
addGasChangeMenu(m, tr("Add gas change"), *d, dc, seconds);
|
||||||
for (auto [i, cyl]: enumerated_range(d->cylinders)) {
|
|
||||||
QString label = printCylinderDescription(i, cyl);
|
|
||||||
gasChange->addAction(label, [this, idx = i, seconds] { addGasSwitch(idx, seconds); });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m.addAction(tr("Add setpoint change"), [this, seconds]() { ProfileWidget2::addSetpointChange(seconds); });
|
m.addAction(tr("Add setpoint change"), [this, seconds]() { ProfileWidget2::addSetpointChange(seconds); });
|
||||||
m.addAction(tr("Add bookmark"), [this, seconds]() { addBookmark(seconds); });
|
m.addAction(tr("Add bookmark"), [this, seconds]() { addBookmark(seconds); });
|
||||||
|
@ -837,7 +828,7 @@ int ProfileWidget2::handleIndex(const DiveHandler *h) const
|
||||||
|
|
||||||
DiveHandler *ProfileWidget2::createHandle()
|
DiveHandler *ProfileWidget2::createHandle()
|
||||||
{
|
{
|
||||||
DiveHandler *item = new DiveHandler(d);
|
DiveHandler *item = new DiveHandler(d, dc);
|
||||||
scene()->addItem(item);
|
scene()->addItem(item);
|
||||||
connect(item, &DiveHandler::moved, this, &ProfileWidget2::divePlannerHandlerMoved);
|
connect(item, &DiveHandler::moved, this, &ProfileWidget2::divePlannerHandlerMoved);
|
||||||
connect(item, &DiveHandler::clicked, this, &ProfileWidget2::divePlannerHandlerClicked);
|
connect(item, &DiveHandler::clicked, this, &ProfileWidget2::divePlannerHandlerClicked);
|
||||||
|
|
|
@ -104,6 +104,7 @@ private:
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
void keyPressEvent(QKeyEvent *e) override;
|
void keyPressEvent(QKeyEvent *e) override;
|
||||||
|
void addGasChangeMenu(QMenu &m, QString menuTitle, const struct dive &d, int dcNr, int changeTime);
|
||||||
#endif
|
#endif
|
||||||
void dropEvent(QDropEvent *event) override;
|
void dropEvent(QDropEvent *event) override;
|
||||||
void dragEnterEvent(QDragEnterEvent *event) override;
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||||
|
|
|
@ -156,25 +156,34 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
||||||
const cylinder_t *cyl = index.row() == tempRow ? &tempCyl : d->get_cylinder(index.row());
|
const cylinder_t *cyl = index.row() == tempRow ? &tempCyl : d->get_cylinder(index.row());
|
||||||
|
|
||||||
|
bool isInappropriateUse = !is_cylinder_use_appropriate(*d->get_dc(dcNr), *cyl, true);
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Qt::BackgroundRole: {
|
case Qt::BackgroundRole:
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
// mark the cylinder start / end pressure in red if the values
|
// mark the cylinder start / end pressure in red if the values
|
||||||
// seem implausible
|
// seem implausible
|
||||||
case START:
|
case START:
|
||||||
case END:
|
case END:
|
||||||
pressure_t startp, endp;
|
{
|
||||||
startp = cyl->start.mbar ? cyl->start : cyl->sample_start;
|
pressure_t startp = cyl->start.mbar ? cyl->start : cyl->sample_start;
|
||||||
endp = cyl->end.mbar ? cyl->end : cyl->sample_end;
|
pressure_t endp = cyl->end.mbar ? cyl->end : cyl->sample_end;
|
||||||
if ((startp.mbar && !endp.mbar) ||
|
if ((startp.mbar && !endp.mbar) ||
|
||||||
(endp.mbar && startp.mbar <= endp.mbar))
|
(endp.mbar && startp.mbar <= endp.mbar))
|
||||||
|
return REDORANGE1_HIGH_TRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case USE:
|
||||||
|
if (isInappropriateUse)
|
||||||
return REDORANGE1_HIGH_TRANS;
|
return REDORANGE1_HIGH_TRANS;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case Qt::FontRole: {
|
case Qt::FontRole: {
|
||||||
QFont font = defaultModelFont();
|
QFont font = defaultModelFont();
|
||||||
|
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
// if we don't have manually set pressure data use italic font
|
// if we don't have manually set pressure data use italic font
|
||||||
case START:
|
case START:
|
||||||
|
@ -184,6 +193,9 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const
|
||||||
font.setItalic(!cyl->end.mbar);
|
font.setItalic(!cyl->end.mbar);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
font.setItalic(isInappropriateUse);
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
case Qt::TextAlignmentRole:
|
case Qt::TextAlignmentRole:
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
#include "diveplannermodel.h"
|
#include "diveplannermodel.h"
|
||||||
|
#include "core/color.h"
|
||||||
#include "core/dive.h"
|
#include "core/dive.h"
|
||||||
#include "core/divelist.h"
|
#include "core/divelist.h"
|
||||||
#include "core/divelog.h"
|
#include "core/divelog.h"
|
||||||
#include "core/event.h"
|
#include "core/event.h"
|
||||||
#include "core/subsurface-string.h"
|
#include "core/subsurface-string.h"
|
||||||
#include "qt-models/cylindermodel.h"
|
#include "qt-models/cylindermodel.h"
|
||||||
#include "qt-models/models.h" // For defaultModelFont().
|
#include "core/metrics.h" // For defaultModelFont().
|
||||||
#include "core/planner.h"
|
#include "core/planner.h"
|
||||||
#include "core/device.h"
|
#include "core/device.h"
|
||||||
#include "core/qthelper.h"
|
#include "core/qthelper.h"
|
||||||
|
@ -88,12 +89,12 @@ void DivePlannerPointsModel::createSimpleDive(struct dive *dIn)
|
||||||
// If we're in drop_stone_mode, don't add a first point.
|
// If we're in drop_stone_mode, don't add a first point.
|
||||||
// It will be added implicitly.
|
// It will be added implicitly.
|
||||||
if (!prefs.drop_stone_mode)
|
if (!prefs.drop_stone_mode)
|
||||||
addStop(M_OR_FT(15, 45), 1 * 60, cylinderid, 0, true, UNDEF_COMP_TYPE);
|
addStop(M_OR_FT(15, 45), 1 * 60, cylinderid, prefs.defaultsetpoint, true, UNDEF_COMP_TYPE);
|
||||||
|
|
||||||
addStop(M_OR_FT(15, 45), 20 * 60, 0, 0, true, UNDEF_COMP_TYPE);
|
addStop(M_OR_FT(15, 45), 20 * 60, 0, prefs.defaultsetpoint, true, UNDEF_COMP_TYPE);
|
||||||
if (!isPlanner()) {
|
if (!isPlanner()) {
|
||||||
addStop(M_OR_FT(5, 15), 42 * 60, 0, cylinderid, true, UNDEF_COMP_TYPE);
|
addStop(M_OR_FT(5, 15), 42 * 60, cylinderid, prefs.defaultsetpoint, true, UNDEF_COMP_TYPE);
|
||||||
addStop(M_OR_FT(5, 15), 45 * 60, 0, cylinderid, true, UNDEF_COMP_TYPE);
|
addStop(M_OR_FT(5, 15), 45 * 60, cylinderid, prefs.defaultsetpoint, true, UNDEF_COMP_TYPE);
|
||||||
}
|
}
|
||||||
updateDiveProfile();
|
updateDiveProfile();
|
||||||
}
|
}
|
||||||
|
@ -260,13 +261,40 @@ int DivePlannerPointsModel::columnCount(const QModelIndex&) const
|
||||||
return COLUMNS; // to disable CCSETPOINT subtract one
|
return COLUMNS; // to disable CCSETPOINT subtract one
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static divemode_t get_local_divemode(struct dive *d, int dcNr, const divedatapoint &p)
|
||||||
|
{
|
||||||
|
divemode_t divemode;
|
||||||
|
switch (d->get_dc(dcNr)->divemode) {
|
||||||
|
case OC:
|
||||||
|
default:
|
||||||
|
divemode = OC;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CCR:
|
||||||
|
divemode = d->get_cylinder(p.cylinderid)->cylinder_use == DILUENT ? CCR : OC;
|
||||||
|
if (prefs.allowOcGasAsDiluent && d->get_cylinder(p.cylinderid)->cylinder_use == OC_GAS && p.divemode == CCR)
|
||||||
|
divemode = CCR;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case PSCR:
|
||||||
|
divemode = p.divemode == PSCR ? PSCR : OC;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return divemode;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
|
QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
divedatapoint p = divepoints.at(index.row());
|
const divedatapoint p = divepoints.at(index.row());
|
||||||
|
bool isInappropriateCylinder = !is_cylinder_use_appropriate(*d->get_dc(dcNr), *d->get_cylinder(p.cylinderid), false);
|
||||||
|
divemode_t divemode = get_local_divemode(d, dcNr, p);
|
||||||
if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
||||||
|
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
case CCSETPOINT:
|
case CCSETPOINT:
|
||||||
return (double)p.setpoint / 1000;
|
return (divemode == CCR) ? (double)(p.setpoint / 1000.0) : QVariant();
|
||||||
case DEPTH:
|
case DEPTH:
|
||||||
return (int) lrint(get_depth_units(p.depth.mm, NULL, NULL));
|
return (int) lrint(get_depth_units(p.depth.mm, NULL, NULL));
|
||||||
case RUNTIME:
|
case RUNTIME:
|
||||||
|
@ -277,18 +305,9 @@ QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
|
||||||
else
|
else
|
||||||
return p.time / 60;
|
return p.time / 60;
|
||||||
case DIVEMODE:
|
case DIVEMODE:
|
||||||
return gettextFromC::tr(divemode_text_ui[p.divemode]);
|
return gettextFromC::tr(divemode_text_ui[divemode]);
|
||||||
case GAS:
|
case GAS:
|
||||||
/* Check if we have the same gasmix two or more times
|
return get_dive_gas(d, dcNr, p.cylinderid);
|
||||||
* If yes return more verbose string */
|
|
||||||
const cylinder_t &cyl = d->cylinders[p.cylinderid];
|
|
||||||
int same_gas = same_gasmix_cylinder(cyl, p.cylinderid, d, true);
|
|
||||||
if (same_gas == -1)
|
|
||||||
return get_gas_string(cyl.gasmix);
|
|
||||||
else
|
|
||||||
return get_gas_string(cyl.gasmix) +
|
|
||||||
QString(" (%1 %2 ").arg(tr("cyl.")).arg(p.cylinderid + 1) +
|
|
||||||
QString::fromStdString(cyl.type.description) + ")";
|
|
||||||
}
|
}
|
||||||
} else if (role == Qt::DecorationRole) {
|
} else if (role == Qt::DecorationRole) {
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
|
@ -307,14 +326,28 @@ QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
|
||||||
return trashForbiddenIcon().size();
|
return trashForbiddenIcon().size();
|
||||||
}
|
}
|
||||||
} else if (role == Qt::FontRole) {
|
} else if (role == Qt::FontRole) {
|
||||||
if (divepoints.at(index.row()).entered) {
|
QFont font = defaultModelFont();
|
||||||
return defaultModelFont();
|
|
||||||
} else {
|
font.setBold(!p.entered);
|
||||||
QFont font = defaultModelFont();
|
|
||||||
font.setBold(true);
|
font.setItalic(isInappropriateCylinder);
|
||||||
return font;
|
|
||||||
|
return font;
|
||||||
|
} else if (role == Qt::BackgroundRole) {
|
||||||
|
switch (index.column()) {
|
||||||
|
case GAS:
|
||||||
|
if (isInappropriateCylinder)
|
||||||
|
return REDORANGE1_HIGH_TRANS;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case CCSETPOINT:
|
||||||
|
if (divemode != CCR)
|
||||||
|
return MED_GRAY_HIGH_TRANS;
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,7 +410,6 @@ bool DivePlannerPointsModel::setData(const QModelIndex &index, const QVariant &v
|
||||||
case DIVEMODE:
|
case DIVEMODE:
|
||||||
if (value.toInt() < FREEDIVE) {
|
if (value.toInt() < FREEDIVE) {
|
||||||
p.divemode = (enum divemode_t) value.toInt();
|
p.divemode = (enum divemode_t) value.toInt();
|
||||||
p.setpoint = p.divemode == CCR ? prefs.defaultsetpoint : 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -416,7 +448,7 @@ QVariant DivePlannerPointsModel::headerData(int section, Qt::Orientation orienta
|
||||||
case GAS:
|
case GAS:
|
||||||
return tr("Used gas");
|
return tr("Used gas");
|
||||||
case CCSETPOINT:
|
case CCSETPOINT:
|
||||||
return tr("CC setpoint");
|
return tr("Setpoint");
|
||||||
case DIVEMODE:
|
case DIVEMODE:
|
||||||
return tr("Dive mode");
|
return tr("Dive mode");
|
||||||
}
|
}
|
||||||
|
@ -428,10 +460,29 @@ QVariant DivePlannerPointsModel::headerData(int section, Qt::Orientation orienta
|
||||||
|
|
||||||
Qt::ItemFlags DivePlannerPointsModel::flags(const QModelIndex &index) const
|
Qt::ItemFlags DivePlannerPointsModel::flags(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (index.column() != REMOVE)
|
if (!index.isValid())
|
||||||
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
|
|
||||||
else
|
|
||||||
return QAbstractItemModel::flags(index);
|
return QAbstractItemModel::flags(index);
|
||||||
|
|
||||||
|
if (index.column() == REMOVE)
|
||||||
|
return Qt::ItemIsEnabled;
|
||||||
|
|
||||||
|
const divedatapoint p = divepoints.at(index.row());
|
||||||
|
switch (index.column()) {
|
||||||
|
case REMOVE:
|
||||||
|
return QAbstractItemModel::flags(index);
|
||||||
|
case CCSETPOINT:
|
||||||
|
if (get_local_divemode(d, dcNr, p) != CCR)
|
||||||
|
return QAbstractItemModel::flags(index) & ~Qt::ItemIsEditable & ~Qt::ItemIsEnabled;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case DIVEMODE:
|
||||||
|
if (!((d->get_dc(dcNr)->divemode == CCR && prefs.allowOcGasAsDiluent && d->get_cylinder(p.cylinderid)->cylinder_use == OC_GAS) || d->get_dc(dcNr)->divemode == PSCR))
|
||||||
|
return QAbstractItemModel::flags(index) & ~Qt::ItemIsEditable & ~Qt::ItemIsEnabled;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivePlannerPointsModel::rowCount(const QModelIndex&) const
|
int DivePlannerPointsModel::rowCount(const QModelIndex&) const
|
||||||
|
@ -537,14 +588,16 @@ int DivePlannerPointsModel::gfLow() const
|
||||||
return diveplan.gflow;
|
return diveplan.gflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::setRebreatherMode(int mode)
|
void DivePlannerPointsModel::setDiveMode(int mode)
|
||||||
{
|
{
|
||||||
d->get_dc(dcNr)->divemode = (divemode_t) mode;
|
struct divecomputer *dc = d->get_dc(dcNr);
|
||||||
for (int i = 0; i < rowCount(); i++) {
|
if (dc)
|
||||||
divepoints[i].setpoint = mode == CCR ? prefs.defaultsetpoint : 0;
|
dc->divemode = (divemode_t) mode;
|
||||||
divepoints[i].divemode = (enum divemode_t) mode;
|
|
||||||
}
|
cylinders.updateDive(d, dcNr);
|
||||||
|
|
||||||
emitDataChanged();
|
emitDataChanged();
|
||||||
|
cylinders.emitDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::setVpmbConservatism(int level)
|
void DivePlannerPointsModel::setVpmbConservatism(int level)
|
||||||
|
@ -753,13 +806,13 @@ int DivePlannerPointsModel::lastEnteredPoint() const
|
||||||
void DivePlannerPointsModel::addDefaultStop()
|
void DivePlannerPointsModel::addDefaultStop()
|
||||||
{
|
{
|
||||||
removeDeco();
|
removeDeco();
|
||||||
addStop(0, 0, -1, 0, true, UNDEF_COMP_TYPE);
|
addStop(0, 0, -1, prefs.defaultsetpoint, true, UNDEF_COMP_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::addStop(int milimeters, int seconds)
|
void DivePlannerPointsModel::addStop(int milimeters, int seconds)
|
||||||
{
|
{
|
||||||
removeDeco();
|
removeDeco();
|
||||||
addStop(milimeters, seconds, -1, 0, true, UNDEF_COMP_TYPE);
|
addStop(milimeters, seconds, -1, prefs.defaultsetpoint, true, UNDEF_COMP_TYPE);
|
||||||
updateDiveProfile();
|
updateDiveProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,18 +828,20 @@ int DivePlannerPointsModel::addStop(int milimeters, int seconds, int cylinderid_
|
||||||
usePrevious = true;
|
usePrevious = true;
|
||||||
|
|
||||||
int row = divepoints.count();
|
int row = divepoints.count();
|
||||||
if (seconds == 0 && milimeters == 0 && row != 0) {
|
if (seconds == 0 && milimeters == 0) {
|
||||||
/* this is only possible if the user clicked on the 'plus' sign on the DivePoints Table */
|
if (row == 0) {
|
||||||
const divedatapoint t = divepoints.at(lastEnteredPoint());
|
milimeters = M_OR_FT(5, 15); // 5m / 15ft
|
||||||
milimeters = t.depth.mm;
|
seconds = 600; // 10 min
|
||||||
seconds = t.time + 600; // 10 minutes.
|
// Default to the first cylinder
|
||||||
cylinderid = t.cylinderid;
|
cylinderid = 0;
|
||||||
ccpoint = t.setpoint;
|
} else {
|
||||||
} else if (seconds == 0 && milimeters == 0 && row == 0) {
|
/* this is only possible if the user clicked on the 'plus' sign on the DivePoints Table */
|
||||||
milimeters = M_OR_FT(5, 15); // 5m / 15ft
|
const divedatapoint t = divepoints.at(lastEnteredPoint());
|
||||||
seconds = 600; // 10 min
|
milimeters = t.depth.mm;
|
||||||
// Default to the first cylinder
|
seconds = t.time + 600; // 10 minutes.
|
||||||
cylinderid = 0;
|
cylinderid = t.cylinderid;
|
||||||
|
ccpoint = t.setpoint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if there's already a new stop before this one:
|
// check if there's already a new stop before this one:
|
||||||
|
@ -1037,16 +1092,17 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
||||||
|
|
||||||
int lastIndex = -1;
|
int lastIndex = -1;
|
||||||
for (int i = 0; i < rowCount(); i++) {
|
for (int i = 0; i < rowCount(); i++) {
|
||||||
divedatapoint p = at(i);
|
const divedatapoint p = at(i);
|
||||||
|
divemode_t divemode = get_local_divemode(d, dcNr, p);
|
||||||
int deltaT = lastIndex != -1 ? p.time - at(lastIndex).time : p.time;
|
int deltaT = lastIndex != -1 ? p.time - at(lastIndex).time : p.time;
|
||||||
lastIndex = i;
|
lastIndex = i;
|
||||||
if (i == 0 && mode == PLAN && prefs.drop_stone_mode) {
|
if (i == 0 && mode == PLAN && prefs.drop_stone_mode) {
|
||||||
/* Okay, we add a first segment where we go down to depth */
|
/* Okay, we add a first segment where we go down to depth */
|
||||||
plan_add_segment(&diveplan, p.depth.mm / prefs.descrate, p.depth.mm, p.cylinderid, p.setpoint, true, p.divemode);
|
plan_add_segment(&diveplan, p.depth.mm / prefs.descrate, p.depth.mm, p.cylinderid, divemode == CCR ? p.setpoint : 0, true, divemode);
|
||||||
deltaT -= p.depth.mm / prefs.descrate;
|
deltaT -= p.depth.mm / prefs.descrate;
|
||||||
}
|
}
|
||||||
if (p.entered)
|
if (p.entered)
|
||||||
plan_add_segment(&diveplan, deltaT, p.depth.mm, p.cylinderid, p.setpoint, true, p.divemode);
|
plan_add_segment(&diveplan, deltaT, p.depth.mm, p.cylinderid, divemode == CCR ? p.setpoint : 0, true, divemode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_PLAN
|
#if DEBUG_PLAN
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
|
|
||||||
void loadFromDive(dive *d, int dcNr);
|
void loadFromDive(dive *d, int dcNr);
|
||||||
void addStop(int millimeters, int seconds);
|
void addStop(int millimeters, int seconds);
|
||||||
|
void setDiveMode(int mode);
|
||||||
public
|
public
|
||||||
slots:
|
slots:
|
||||||
void addDefaultStop();
|
void addDefaultStop();
|
||||||
|
@ -96,7 +97,6 @@ slots:
|
||||||
void removeDeco();
|
void removeDeco();
|
||||||
void deleteTemporaryPlan();
|
void deleteTemporaryPlan();
|
||||||
void emitDataChanged();
|
void emitDataChanged();
|
||||||
void setRebreatherMode(int mode);
|
|
||||||
void setReserveGas(int reserve);
|
void setReserveGas(int reserve);
|
||||||
void setSwitchAtReqStop(bool value);
|
void setSwitchAtReqStop(bool value);
|
||||||
void setMinSwitchDuration(int duration);
|
void setMinSwitchDuration(int duration);
|
||||||
|
|
|
@ -13,44 +13,84 @@
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
|
||||||
Qt::ItemFlags GasSelectionModel::flags(const QModelIndex&) const
|
GasSelectionModel::GasSelectionModel(const dive &d, int dcNr, QObject *parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
gasNames = get_dive_gas_list(&d, dcNr, true);
|
||||||
}
|
|
||||||
|
|
||||||
GasSelectionModel::GasSelectionModel(const dive &d, QObject *parent)
|
|
||||||
: QStringListModel(parent)
|
|
||||||
{
|
|
||||||
setStringList(get_dive_gas_list(&d));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant GasSelectionModel::data(const QModelIndex &index, int role) const
|
QVariant GasSelectionModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (role == Qt::FontRole)
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::FontRole:
|
||||||
return defaultModelFont();
|
return defaultModelFont();
|
||||||
return QStringListModel::data(index, role);
|
case Qt::DisplayRole:
|
||||||
|
return gasNames.at(index.row()).second;
|
||||||
|
case Qt::UserRole:
|
||||||
|
return gasNames.at(index.row()).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GasSelectionModel::rowCount(const QModelIndex&) const
|
||||||
|
{
|
||||||
|
return gasNames.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dive Type Model for the divetype combo box
|
// Dive Type Model for the divetype combo box
|
||||||
|
|
||||||
Qt::ItemFlags DiveTypeSelectionModel::flags(const QModelIndex&) const
|
DiveTypeSelectionModel::DiveTypeSelectionModel(const dive &d, int dcNr, QObject *parent) : QAbstractListModel(parent)
|
||||||
{
|
{
|
||||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
divemode_t mode = d.get_dc(dcNr)->divemode;
|
||||||
}
|
for (int i = 0; i < FREEDIVE; i++) {
|
||||||
|
switch (mode) {
|
||||||
|
case OC:
|
||||||
|
default:
|
||||||
|
if (i != OC)
|
||||||
|
continue;
|
||||||
|
|
||||||
DiveTypeSelectionModel::DiveTypeSelectionModel(QObject *parent) : QStringListModel(parent)
|
break;
|
||||||
{
|
case CCR:
|
||||||
QStringList modes;
|
if (i != OC && i != CCR)
|
||||||
for (int i = 0; i < FREEDIVE; i++)
|
continue;
|
||||||
modes.append(gettextFromC::tr(divemode_text_ui[i]));
|
|
||||||
setStringList(modes);
|
break;
|
||||||
|
case PSCR:
|
||||||
|
if (i != OC && i != PSCR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diveTypes.push_back(std::pair(i, gettextFromC::tr(divemode_text_ui[i])));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant DiveTypeSelectionModel::data(const QModelIndex &index, int role) const
|
QVariant DiveTypeSelectionModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (role == Qt::FontRole)
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::FontRole:
|
||||||
return defaultModelFont();
|
return defaultModelFont();
|
||||||
return QStringListModel::data(index, role);
|
case Qt::DisplayRole:
|
||||||
|
return diveTypes.at(index.row()).second;
|
||||||
|
case Qt::UserRole:
|
||||||
|
return diveTypes.at(index.row()).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
int DiveTypeSelectionModel::rowCount(const QModelIndex&) const
|
||||||
|
{
|
||||||
|
return diveTypes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Language Model, The Model to populate the list of possible Languages.
|
// Language Model, The Model to populate the list of possible Languages.
|
||||||
|
|
|
@ -21,20 +21,24 @@
|
||||||
|
|
||||||
struct dive;
|
struct dive;
|
||||||
|
|
||||||
class GasSelectionModel : public QStringListModel {
|
class GasSelectionModel : public QAbstractListModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
GasSelectionModel(const dive &d, QObject *parent);
|
GasSelectionModel(const dive &d, int dcNr, QObject *parent);
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<int, QString>> gasNames;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DiveTypeSelectionModel : public QStringListModel {
|
class DiveTypeSelectionModel : public QAbstractListModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DiveTypeSelectionModel(QObject *parent);
|
DiveTypeSelectionModel(const dive &d, int dcNr, QObject *parent);
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<int, QString>> diveTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LanguageModel : public QAbstractListModel {
|
class LanguageModel : public QAbstractListModel {
|
||||||
|
|
|
@ -113,6 +113,11 @@ TestCase {
|
||||||
var x27 = PrefTechnicalDetails.zoomed_plot
|
var x27 = PrefTechnicalDetails.zoomed_plot
|
||||||
PrefTechnicalDetails.zoomed_plot = true
|
PrefTechnicalDetails.zoomed_plot = true
|
||||||
compare(PrefTechnicalDetails.zoomed_plot, true)
|
compare(PrefTechnicalDetails.zoomed_plot, true)
|
||||||
|
|
||||||
|
var x28 = PrefTechnicalDetails.allowOcGasAsDiluent
|
||||||
|
PrefTechnicalDetails.allowOcGasAsDiluent = true
|
||||||
|
compare(PrefTechnicalDetails.allowOcGasAsDiluent, true)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -204,6 +209,7 @@ TestCase {
|
||||||
PrefTechnicalDetails.tankbar = ! PrefTechnicalDetails.tankbar
|
PrefTechnicalDetails.tankbar = ! PrefTechnicalDetails.tankbar
|
||||||
PrefTechnicalDetails.vpmb_conservatism = -127
|
PrefTechnicalDetails.vpmb_conservatism = -127
|
||||||
PrefTechnicalDetails.zoomed_plot = ! PrefTechnicalDetails.zoomed_plot
|
PrefTechnicalDetails.zoomed_plot = ! PrefTechnicalDetails.zoomed_plot
|
||||||
|
PrefTechnicalDetails.allowOcGasAsDiluent = ! PrefTechnicalDetails.allowOcGasAsDiluent
|
||||||
|
|
||||||
compare(spyCatcher.spy1, true)
|
compare(spyCatcher.spy1, true)
|
||||||
compare(spyCatcher.spy2, true)
|
compare(spyCatcher.spy2, true)
|
||||||
|
|