Since the taxonomy is now a real C++ struct with constructor
and destructor, dive_site has to be converted to C++ as well.
A bit hairy for now, but will ultimately be distinctly simpler.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Use std::vector<> instead of fixed size array.
Doesn't do any logic change, even though the back-translation
logic is ominous.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old code was wild: For the yearly statistics it would allocate
one entry per dive in the log. Of course, it would also leak
C-style strings.
Convert the whole thing to somewhat idiomatic C++.
Somewhat wasted work, because I'd like to convert the whole thing
to the new statistics code. But let's finish the conversion to C++
first.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Fix an issue introduced in #4148.
Essentially the refactoring missed the fact that in the imperial system
tank size is tracked as the free gas volume, but in the metric system
(which is the one used in most of Subsurface's calculations) tank size
is tracked as water capacity.
So when updating a tank template tracking imperial measurements, the
given (metric) volume in l has to be multiplied by the working pressure,
and vice versa.
This also combines all the logic dealing with `tank_info` data in one
place, hopefully making it less likely that this will be broken by
inconsistencies in the future.
Fixes#4239.
Signed-off-by: Michael Keller <github@ike.ch>
The roles DIVE_IDX and SELECTED_ROLE were used for the old selection
system and removed in b8e7a600d2.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
- show the correct gasmix in the profile;
- make gases available for gas switches in the profile after they have
been added;
- persist gas changes;
- add air as a default gas when adding a dive.
This still has problems when undoing a gas switch - instead of
completely removing the gas switch it is just moved to the next point in the
profile.
Signed-off-by: Michael Keller <github@ike.ch>
- standardise the naming;
- use it consistently;
- apply the 'samples < 50' only when putting manually added dives into
edit mode - everywhere else manually added dives should be treated as
such;
- do not show a warning before editing a manually added dive in planner.
Signed-off-by: Michael Keller <github@ike.ch>
The lambda that created the list of gases took a copy not a
reference of the planned dive. Of course, that never had its
gases updated. Ultimately this would crash, because this sent
an index of "-1" on change.
Fix by
1) Using a reference to the dive, not the copy
2) Catch an invalid "-1" index (by Michael Keller <github@ike.ch>)
Fixes#4188
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently editing of planned dives that have been merged with actual
(logged) dives only works if the 'Planned dive' divecomputer is the
first divecomputer, and this divecomputer is selected when clicking
'Edit planned dive'. In other cases the profile of the first
divecomputer is overlaid with the profile of the planned dive, and the
first divecomputer's profile is overwritten when saving the dive plan.
Fix this problem.
Triggered by @SeppoTakalo's comment (https://github.com/subsurface/subsurface/issues/1913#issuecomment-2075562119): Users don't like that planned dives show up as their own entries in the dive list, so being able to merge them with the actual dive after it has been executed is a good feature - but this wasn't working well until now.
Signed-off-by: Michael Keller <github@ike.ch>
The old code was leaking memory. Use std::unique_ptr<> for
ownership management.
This is still very primitive and divetags are kept during
application lifetime. There should probably be some form
of reference counting. And the taglist should not be global,
but attached to the divelog.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The deco timestep is a parameter to the plan() function. There
seems no need to define this as a global macro. Probably some
code reshuffeling artifact.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The combo-boxes (cylinder type, weightsystem, etc.) were controlled
by global models. Keeping these models up-to-date was very combersome
and buggy.
Create a new model everytime a combobox is opened. Ultimately it
might even be better to create a copy of the strings and switch
to simple QStringListModel. Set data in the core directly and
don't do this via the models.
The result is much simpler and easier to handle.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Q_FOREACH and foreach are anachronisms.
Range based for may cause a performance regression: it can
lead to a copy of shared containers (one reason why Qt's
COW containers are broken). However, as long as there is no
user noticeable delay, there is no point in analyzing each case.
And also no point in slapping an 'asConst' on every container
that is looped over.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
qthelper.h is an absolute monstrosity and it is unclear what
report_info and SSRF_INFO have to do with Qt.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The automatic conversion from char * to QVariant failed to
compile for me. Let's hint that this should be interpreted
as a string. No idea, why this happens for me, but apparently
not on CI.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Fix the persisting and use of gradient factor preferences for dive
profiles in the mobile version.
Also rename the mobile backend gradient factor settings to make it
obvious that they are used by the (not currently enabled) planner.
Signed-off-by: Michael Keller <github@ike.ch>
Mostly irrelevant std::move() stuff of copy-on-write Qt objects,
a few real bugs, a timestamp_t downconversion and some codingsyle
adaptation.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Unfortunately Coverity doesn't understand that most Qt data
structures are copy-on-write. It's a mis-feature of Qt, but
it is the way it is. Thus, passing by value is not an issue.
Out of ca. 25 warnings only two were legit. Let's silence
the others by either std::move()ing or passing by reference,
as would be idiomatic C++, which Qt is not.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Include unused tanks in merges of multiple logs into a single dive if
the 'Show unused cylinders' preference is enabled.
Also rename the preference (in code) to `include_unused_tanks` to
reflect the fact that it is already used in more places than just the
display (exporting, cloning dives).
Simplified the cylinder model to make forced inclusion of unused tanks
dependent on use of the model in planner.
Leaving the persisted name of the preference as `display_unused_tanks`
to avoid resetting this for all users - is there a good way to migrate
preference names?
Signed-off-by: Michael Keller <github@ike.ch>
There was this completely weird loop that the planner-widget would
call the planner-model to get the current rebreather mode, which
would then access the dive in the planner widget. Just keep those
things in the planner widgets.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The only user of the DivePlannerPointsModel and the
GasSelectionModel is the planner. Let's keep these models
there.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The gas and dive-type models were repopulated in the
diveplanner model. The former are used in the planner.
However, the latter is also used outside of the planner,
when editing non-planned dives. Thus the former shouldn't
be repopulated by the latter, but by the code that needs
it.
Side note: repopulating the dive-type model seems to
make no sense whatsoever since the values never change,
but let's keep it for now.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The mode was accessed via the global `displayed_dive`. In an effort
to remove globals, access it via the DivePlannerPointsModel instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The current dc global makes no sense on mobile. Therefore,
move the logic of the currently displayed dive computer
to the profile widget and remove the dc_number global
variable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The signals/slot names for dive selection changes were a mess.
Unify on divesSelected(). Firstly, selectionChanged() is a Qt
thing. Secondly, it is consistent with tripSelected().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The trip selection code was an awkward layering violation.
Whereas dive selections due to dive undo-commands trickled
down via DiveTripModel-->MultiFilterSortModel-->DiveListView,
for trip editing, the DiveListView directly intercepted the
TripEdited signal.
Instead, mimic the dive-selection code. This is a bit longer
but more consistent and logical. The undo/redo of trip changes
is now also a "programmatical" change of the selection.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
After sending a selection-change signal, there follows a current
dive changed signal. Combine these two into a single signal, since
usually the current dive is changed when the selection is changed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of accessing the global dc_number from the
DivePlannerPointsModel and the CylinderModel, pass them
in the respective initialization functions.
The dc_number global might not make sense on mobile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This tries to encapsulate the management of the current dive and
divecomputer in the selection code. The current dive is alreay
set by setSelection(). Add a new parameter to also set the
current divecomputer. If -1 is passed, then the current
computer number is remained. This will allow us to audit the code.
Because for now, the whole "current dive computer" thing seems
to be ill-defined.
This fixes a bug: the dive-computer number wasn't validated
when making a new dive the current dive. The new code has some
drawbacks though: when selecting a whole trip, the validation
will be called for all dives in the trip and thus the dive computer
number will depend on the dive with the lowest amount of dive
computers in the trip. This will need to be fixed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The parser API was very annoying, as a number of tables
to-be-filled were passed in as pointers. The goal of this
commit is to collect all these tables in a single struct.
This should make it (more or less) clear what is actually
written into the divelog files.
Moreover, it should now be rather easy to search for
instances, where the global logfile is accessed (and it
turns out that there are many!).
The divelog struct does not contain the tables as substructs,
but only collects pointers. The idea is that the "divelog.h"
file can be included without all the other files describing
the numerous tables.
To make it easier to use from C++ parts of the code, the
struct implements a constructor and a destructor. Sadly,
we can't use smart pointers, since the pointers are accessed
from C code. Therfore the constructor and destructor are
quite complex.
The whole commit is large, but was mostly an automatic
conversion.
One oddity of note: the divelog structure also contains
the "autogroup" flag, since that is saved in the divelog.
This actually fixes a bug: Before, when importing dives
from a different log, the autogroup flag was overwritten.
This was probably not intended and does not happen anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since the only caller was C++ code, this can be done in
C++ code, which removes memory-management headaches.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Fix a bug that results in dive plans outside of the configured risk
profile being produced when planning a CCR dive with the first segment
set to open circuit.
`d->dc.divemode` is already set in `setRebreatherMode`, which is
sufficient, and congruent with the setting of other dive parameters,
like `diveplan.gflow`.
Signed-off-by: Michael Keller <github@ike.ch>
Changed the way dive data points for OC cylinders to be added to the
dive plan are created in `createTemporaryPlan()` in
`diveplannermodel.cpp`. This now uses `plan_add_segment()` like all
other places where dive data points are added, in particular the planner
tests.
This also allowed for `create_dp()` to be made static.
Signed-off-by: Michael Keller <github@ike.ch>
Use the drop down for editing the tank use in the gas list in both the
equipment tab and the dive planner.
The tank use column is now available in the equipment tab for all dives
and not just CCR dives, as 'not used' is a valid entry in both cases.
However, if the current dive is an OC dive, only 'OC-gas' and 'not used' are
shown.
There still seems to be a problem that in some cases, when opening the
planner after selecting an existing CCR dive the drop down in the
planner does not list CCR gas uses - for some reason `displayed_dive`
does not seem to be updated correctly on opening of the planner. But I have not been able to
reproduce this consistently, and changing 'Dive mode' fixes this.
Signed-off-by: Michael Keller <github@ike.ch>
For dives with many samples (i.e. logged dives), samples are merged.
I'm not exactly sure how this code works, but it does an
out-of-bound access in some cases. Avoid that by a simple
check.
That said, I wonder if this downsampling is a good idea. A user
reports that they have logged dives marked as manually added dives.
We now load them into edit mode, which means a significant loss
of information.
Perhaps we should consider dives with more than 100 samples as
non-manual dives?
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Search the index of an item in a container. Compare by
equality or a lambda. The lack of these have annoyed me for a
long time. Return the index of the first found element or
-1 if no element found.
Currently, only supports random-access operators. Might be
trivially changed for forward iterators.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There were a number of classical "for (i = 0; i < size; ++i)"
loops. Replace them either by plain range based loops if the index
is not used or by enumerated_range() loops.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The moveInVector() function was defined in qthelper.h, even
though it has nothing to do with Qt. Therefore, move it into
its own header.
Morover, since it is a very low-level function, use snake_case.
And rename it to move_in_range(), because it does not only
work on vectors, but any range with random-access iterators.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The get_minutes() function formats a time as m:ss
and returns a static C-string. Since all callers are
C++ anyway and transform directly into QString, let us
move this to the other string formatting function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Also allow editing sensor on a cylinder with already attached sensor.
This will swap the sensor data with the cylinder that it is taking the
sensor data from, removing the need for adding an extra temporary
cylinder when swapping two sensors.
Signed-off-by: Michael Andreen <michael@andreen.dev>
One would think that calling free() on a dive structure, as the code
did in some places, would lead to a memory leak.
(Insert rant about C memory management.)
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Adds a preference setting in the "Default" settings tab to toggle whether
to display shortened names in the Map.
TODO: instead of using the generic "settingsChanged" signal, it would be much
more efficient to only update items based on the actual setting which was
changed.
Signed-off-by: Michael WERLE <micha@michaelwerle.com>
Only the last component of the Site Name is displayed, otherwise the full
name is displayed. Site Name components are separated using slash (/)
characters.
For example, if the full dive-site name is
"Japan / Izu Peninsula / Atami / Chinsen-Aft" then only "Chinsen-Aft" is
displayed on the Map.
Signed-off-by: Michael WERLE <micha@michaelwerle.com>
When computing plan variations, deco can get shorter when
staying longer when the last step is actually already at
off gasing depth. FRACTION forces unsiged, so this introduces
a sign aware version of FRACTION that returns a sign character
in addition.
Reported-by: Patrick Naujoks <p.naujoks@me.com>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Making this simply depend on Qt5 or Qt6 was short-sighted as work on QtLocation
upstream continues. Instead break this out as its own option.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The only things in display.h were profile related, so the
split between these two files is not comprehensible.
In fact profile.h includes display.h, because it needs the
struct defined therein. Let's just merge these two files.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a column to the equipment table that shows if a sensor is attached to a
tank, or which sensors would be available to attach to a tank that currently
doesn't have a pressure sensor associated with it.
Changing the sensor assignement can be undone.
This column is hidden by default as this is a somewhat unusual activity.
Signed-off-by: Michael Andreen <michael@andreen.dev>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The UI was updated before storing the dive. This had a nasty
effect: the current dive was shown in the profile and if that
was a manually added dive, the DivePlannerPointsModel was
overwritten. Thus the planned dive couldn't be saved anymore.
There is a comment why the UI switch was done beforehand.
But in my tests, this didn't seem to be valid anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Place undo commands for every change of the profile, not
only on "saving". Move the edit-mode from the mainwindow
and the maintab to the profile widget.
This is still very rough. For example, the only way to exit
the edit mode is changing the current dive.
The undo-commands are placed by the desktop-profile widget.
We might think about moving that down to the profile-view so
that this will be useable on mobile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The formatting of the tooltips describing the columns
was repeated in two functions. Infuriatingly, there were
to minor differences: "Max. CNS" vs. "Max CNS" and
one version understood "Country".
Break that out into a single function to avoid these
inconsistencies and to save a few lines of code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In general, replace "dive master" by "dive guide".
However, do not change written dive logs for now. On reading,
accept both versions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Coverity warning: divedatapoint::minimum_gas was not initialized
in DivePlannerPointsModel::addStop.
I don't know the meaning of that member variable and therefore
cannot tell if this was a real issue.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In a40b40a the cylinder-hiding functionality was changed,
which made it necessary to keep track of the number of
cylinders. Ironically, that code was removed previously,
as it was redundant. The count was not readded to the
functions called by the planner, making editing of cylinders
in the planner impossible.
I wonder more and more if the models for planner and the
equipment tab should be changed. They are too different.
Fixes#3375
Reported-by: Anton Lundin <glance@acc.umu.se>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is only one user of this - let's remove complex
interdependencies.
Note: there seem to be two independent plot_infos: in the
ProfileScene and in the DivePlotDataModel. To avoid behavioral
change, this keeps using the DivePlotDataModel's version.
In any case, this has to be unified.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To enable grouping by trip in the statistics module, split
the get_trip_title() function in a version that appends
a "(n dive(s)" string an one that doesn't. The statistics
module doesn't want that added string, since it displays
the number of dives in a different way.
Also, move the functions to string-format.h, where these
are collected. And rename them to camelCase. Yes, it's
ugly, but consistent with most other C++ code in the code
base.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When adding a cylinder, it was added at the end of the list.
This would make hidden cylinders visible as the new rule is
to only hide unused cylinders at the end of the list.
Therefore, add the cylinder after the last used cylinder,
i.e. before the first hidden cylinder.
This means that the position where the cylinder is added has
to be hidden in the undo command.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On the equipment tab, unused cylinders (automatically added,
no pressure data) could be hidden. This was implemented using
a QSortFilterProxyModel.
Apparently, it causes confusion if cylinders in the middle of
the list are hidden. Therefore, only hide cylinders at the end
of the list.
QSortFilterProxyModel seems the wrong tool for that job, so
remove it and add a flag "hideUnused" to the base model. Calculate
the number of cylinders when changing the dive.
This is rather complex, because the same model is used for
the planner (which doesn't hide cylinders) and the equipment
tab (which does). Of course, syncing core and model now becomes
harder. For instance, the caching of the number of rows was removed
in a37939889b and now has to be
readded.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is a warning when the code tries to access a non-existing
cylinder, since that indicates that something went out of sync.
However, this warning can never trigger because the bounds are
checked before. Remove the first of the two redundant checks.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The logic did not consider the WORKINGPRESS_INT and SIZE_INT
columns added in cb80ff746b.
By some unknown magic this worked by routing everything
through the CylindersModelFiltered model.
Let's fix it and explicitly ignore these columns. Put
the test whether a column should be ignored in a function
to avoid inconsistencies should new columns be added.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Fix a pair of warnings, which annoyed me for a long time:
For some reasons prefs.bottompo2 is an integer (mbar)
whereas prefs.modpO2 is a float (bar). This results
in mixed integer/floating point arithmetics when
conditionally using either of them. And ultimately
a warning, when storing a mbar value as an integer.
Fix this by an explicit cast to int after converting
modpO2 to mbar.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Air is a special gas that does not contain oxygen according
to gasmix.o2.fraction. If you want to use the fo2, you
need to use get_o2() to treat this special case correctly.
This fixes a bug when setting the MND of a gas containing
21% oxygen when o2 is considered not narcotic.
Reported-by: Christoph Gruen <gruen.christoph@gmail.com>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
This makes sure that the dive plan is updated (including the
planner notes) when parameters of the dive or the planner
change.
This fixes a bug reported by Jay Anchor.
There is a chance that by partly undoing 77a6bc6d62, this
introduces too many recalculations of the plan. But without
this patch, there are definitely not enough recalculations.
Reported-by: Jay Anchor <jay.anchor-subsurface@e257.fi>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
A change not to compute plan variations when not needed
was too aggressive and eliminated also the signal to update
the notes. Bug fixed.
Reported-by: Jay Anchor <jay.anchor-subsurface@e257.fi>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
There are two cases in this function: with and without holding
the control-key. The former deletes one point, the latter all
points starting with the selected point to the end.
The code was interlaced making it very hard to reason about.
Notably, it was buggy: with control, all points could be
deleted, leading to a crash.
Split the function in two versions, with their own bound
checking. This produces a bit of duplicate code, which
might be broken out later.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When updating the dive profile, a thread is started to calculate
plan-variations. This is done even when only editing the profile
or when variation calculation is disabled by the user. The thread
then exits if it shouldn't calculate the variations.
Turn this around: test whether variations should be calculated
before starting the thread.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
removeDeco() was called by addStop() if the recalc flag was
set. If the caller didn't want to call removeDeco() it had
to clear and restore the flag.
Instead, call removeDeco() explicitly when needed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There are no more external users of this flag, therefore clearing
that flag is a no-op.
Moreover, clear the cylinders array and the preserved_until
flag befor emitting the model-reset signal.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>