Commit graph

1118 commits

Author SHA1 Message Date
Michael Keller
1e3d378ad9 Cylindermodel: Improve editing of tank use
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>
2023-02-07 14:20:29 +01:00
Berthold Stoeger
687f65bf77 planner: avoid out-of-bound access when initializing the planner
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>
2023-01-19 14:26:00 +01:00
Berthold Stoeger
691d9e86de cleanup: implement index_of() and index_of_if() generics
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>
2022-10-31 19:35:15 +01:00
Berthold Stoeger
b63073e203 cleanup: use range based loops in model
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>
2022-10-30 22:06:17 +01:00
Berthold Stoeger
94641c510f core: create range.h header for range manupulation functions
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>
2022-10-30 21:16:00 +01:00
Berthold Stoeger
4a7ee872f3 cleanup: move minute formating to format-string.cpp
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>
2022-09-03 13:49:02 -07:00
Michael Andreen
a39e69c497 Use combo box for moving sensor data
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>
2022-09-03 13:38:34 -07:00
Berthold Stoeger
70fbce46c7 cleanup: fix typos in comments
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2022-08-28 13:34:13 -07:00
Berthold Stoeger
1c00f9f233 core: use free_dive() to free dive
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>
2022-08-22 09:34:25 -07:00
Michael Werle
881a9cac4e cleanup: fix compiler warnings in recently edited files.
Replace NULL -> nullptr
Remove spurious semicolon

Signed-off-by: Michael WERLE <micha@michaelwerle.com>
2022-08-21 18:53:35 -07:00
Michael Werle
efb1832db8 Map Short Names - add preference setting
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>
2022-08-21 18:53:35 -07:00
Michael Werle
3dbba5ae69 Map Short Names - display shortened names on the map.
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>
2022-08-21 18:53:35 -07:00
Robert C. Helling
0f2cdd16dc Deal with negative variation times
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>
2022-06-04 14:19:05 -07:00
Dirk Hohndel
2241a28499 build-system: make map support its own thing
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>
2022-04-18 07:24:38 +02:00
Dirk Hohndel
6354f97321 fix merge problem
I guess I get what I deserve.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2022-03-13 16:59:32 -07:00
Berthold Stoeger
f9b9582a64 core: fold display.h into profile.h
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>
2022-03-13 15:07:33 -07:00
Michael Andreen
9b4263aa87 Allow editing sensors through equipment tab
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>
2022-03-12 11:24:50 -08:00
Berthold Stoeger
357e115121 planner: update UI after having saved the dive
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>
2022-03-12 18:33:34 +01:00
Berthold Stoeger
fce48367cd undo: more fine-grained undo of profile editing
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>
2022-03-12 18:32:22 +01:00
Dirk Hohndel
3321904434 Qt6: deal with changed QtConcurrent::run API
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2022-03-12 08:28:32 -08:00
Dirk Hohndel
ce254bee57 build-system: update cmake to allow Qt5 and Qt6
Qt6 builds of course still fail, but now they are at least possible.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2022-03-12 08:28:32 -08:00
Berthold Stoeger
1ce42158f1 model: unify tooltip formating in DiveTripModel
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>
2022-02-15 09:37:16 -08:00
Berthold Stoeger
b3c58e7172 models: export dive guide in DiveTripModel
We might want to display that in the dive list.

Fixes #3382.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2022-02-15 09:37:16 -08:00
Berthold Stoeger
9e0712d5dc core: replace dive master by dive guide
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>
2022-02-15 09:35:43 -08:00
Berthold Stoeger
af0b061266 cleanup: fix uninitialized member issue
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>
2022-02-15 09:30:43 -08:00
Berthold Stoeger
1af4032dad planner: properly keep track of cylinder count in model
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>
2022-01-17 13:08:46 -08:00
Berthold Stoeger
564cbc797c profile: remove DivePlotDataModel
All accesses to the plot data are now directly to the core
structures.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
e0f44237cc profile: move max_gas() from DivePlotDataModel to ProfileScene
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>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
1df1f3d0b5 profile: remove DivePlotDataModel::dcShown()
The last user was removed in 2789bb05b1.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
9e20cb5a49 profile: remove PERCENTAGE_* data from DivePlotDataModel
The profile now reads these percentages directly from the
plot info structure.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
d1b8f1ca3d formatting: move get_trip_title to string-format.h and split it
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>
2021-12-17 10:36:13 -08:00
Berthold Stoeger
1af67512a1 cylinders: add cylinder before hidden cylinders
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>
2021-12-13 11:54:24 -08:00
Berthold Stoeger
a40b40ae7a cylinders: only hide cylinders at the end of the list
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>
2021-12-13 11:54:24 -08:00
Berthold Stoeger
3466d0c44d cylinders: remove redundant index check in the model
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>
2021-12-13 11:54:24 -08:00
Berthold Stoeger
c6f0fcbb0b cylinder: fix hidden-column logic in cylinder tab
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>
2021-12-13 11:54:24 -08:00
Dirk Hohndel
bb5866f49e cleanup: replace QRegExp with QRegularExpression
Qt 6 will drop support for QRegExp.
Use QRegularExpression instead.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-10-27 12:36:49 -07:00
Berthold Stoeger
540e4437d5 cleanup: fix conversion warning
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>
2021-10-16 15:32:56 -07:00
Tim Segers
f3a02d7049 Ignore invalid dives in subsurface-mobile dive summary
Match subsurface-desktop's invalid dive behavior

Signed-off-by: Tim Segers <tsegers@pm.me>
2021-10-11 20:20:20 +03:00
Robert C. Helling
41258647d2 Don't access gasmix.o2.fraction
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>
2021-10-01 08:50:36 -07:00
Dirk Hohndel
bea552bf0d mobile: remove GpsListModel
This is only needed to show the list of GPS fixes obtained with
the now removed location service.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-09-13 11:21:34 -07:00
Linus Torvalds
2da7e9e5ad Remove the divecomputermodel code
This is no longer reachable, since the divecomputer tab is gone.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2021-08-18 13:22:02 -07:00
Robert C. Helling
5dfc183517 Planner: Update plan when deco parameters change
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>
2021-05-12 10:02:47 +02:00
Berthold Stoeger
a7002f4089 profile: remove DiveAmbPressureItem
This was replaced by the tissue map in 893bea700c.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-05-08 13:40:24 +02:00
Berthold Stoeger
8b0db14f64 profile: remove DiveGFLineItem
This was replaced by the tissue map in 893bea700c.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-05-08 13:40:24 +02:00
Robert C. Helling
312b760c5b Planner: Update notes when not computing variations
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>
2021-05-07 11:20:30 -07:00
Berthold Stoeger
11c54b85f6 planner: split DivePlannerPointsModel::remove() in two
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>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
a0f6b4d0b4 planner: avoid starting unneeded variation thread
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>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
0f8560276d planner: remove DivePlannerPointsModel::recalc flag
There was no user of that flag left.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
f0f3b4a13c planner: call removeDeco() explicitly
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>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
c7dcd7fbf0 planner: don't clear recalc in DivePlannerPointsModel::clear()
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>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
601861ef5e planner: split DivePlannerPointsModel::removePoints() in two
Split the function in one external version, that updates the
dive profile and cylinders and one internal version, that
does no recalculations. In the latter case, the caller is
responsible for updating the dive.

Thus, the recalculation flag-clearing can be removed from
removeDeco().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
cbee716316 planner: don't export recalc flag of DivePlannerPointsModel
This is not queried anymore, so remove the accessor function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
77a6bc6d62 profile/planner: don't update dive in ProfileWidget2::plotDive()
In planner or profile-edit mode, the plotDive() function takes
the current plan and turns it into a dive profile. Not only
is this a layering violation (the display layer modifying the
dive), it is also fundamentally flawed. The control-flow is
out of control, if you wish. There are numerous reasons why
the profile needs to be replot, many of which do not need
a recalculated dive profile.

Move the code that updates the dive-profile to the
DivePlannerPointsModel. Thus, the profile recalculations
and replots can be pooled. This will break the planner, since
there now might be missing calls to the profile recalculation.
But it already has some positive effects: when removing
multiple points, the profile is only recalculated once.

This will need much more work, but it is a start.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
337d9318ad planner: split addStop() into external and internal versions
The DivePlannerPointsModel::addStop() function is called by
the profile to add a planner-stop. It is also used internally
to create profiles.

If we ever want to include this in the undo system, we have
to split these into to versions. One will ultimately place
an undo command and update the profile, the other one doesn't.

For now, this makes the external interface simpler, as some
parameters are redundant.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
51b16a43c4 cleanup: make DivePlannerPointsModel::removeDeco() private
No outside users.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
7c398973fd cleanup: remove unused function DivePlannerPointsModel::size()
This is not a virtual function and does not seem to be called
anywhere..?

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
93ec9f11e8 cleanup: remove unused member DivePlannerPointsModel::addingDeco
This was never used.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
4b801f1f50 planner: split createTemporaryPlan() function.
The DivePlannerPointsModel::createTemporaryPlan() function had
two distinct and independent parts:
 1) create the data points.
 2) create the dive sample and calculate variations.
The second part was only exectuted if the recalc flag was set.
Out of the two callers, one was explicitly disabling and setting
the recalc flag to avoid the second part.

The much more logical thing is to simply split the function in
two and only call the first part.

To avoid any functional change, the second caller (the profile)
still tests for the recalc flag. However, if it shouldn't replot
a new plan, why calculate it in the first place!? And why does
the display function change the plan at all? This appears all
very ill-thought out and should be changed in due course.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
7b9c8e344a cleanup: unify whitespace in switch statement
The way the blocks in DivePlannerPointsModel::setData()'s
switch statement were demarked messed with my mind.
There were at least three variants. Let's try to be consistent.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
4009d4c87f planner: remove DivePlannerPointsModel::setRecalc()
The only external user of setRecalc() was turning recalculation
on. In fact, this happened when constructing the planner-widget.
However, for example editing of the profile only works when
the recalc flag is on.

This is all very confusing, let's just turn the flag on by
default and remove the accessor. Internally, the planner can
simply use the std::exchange function to set and reset the
recalc flag.

Perhaps the setting/resetting can be replaced by simple
        recalc = true;
        ...
        recalc = false;
pairs. It is unclear whether there is need for recursion.
Something to be investigated.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
2789bb05b1 profile: display arbitrary dive
So far the profile operated on the global displayed_dive. Instead,
take the dive to be displayed as a parameter to the plotDive()
functions.

This is necessary if we want to have multiple concurrent
profile objects. Think for example for printing or for mobile
where multiple dive objects are active at the same time.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
1ec0790d50 planner: remove displayed_dive from DivePlannerModel
To remove global state, make the dive that DivePlannerModel
works on a member variable. Pass the dive in createSimpleDive()
and loadFromDive(). Moreover, this should pave the way to more
fine-grained undo in the planner. Ultimately, the planner
should not be modal.

Attention: for now, the dive must still be displayed_dive,
because of the convoluted way in which the profile and the
planner work on the same dive.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
e419ebf55a planner: move clearing of model into loadFromDive() function
Both loadFromDive() callers were clearing the model before
calling loadFromDive(). Move the clearing into that function
since it makes no sense to load into a non-cleared model.

Apparently this changes the way that no-cylinder dives are
treated and the code in ProfileWidget2::repositionDiveHandlers()
must now explicitly check for that condition.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
02ef58a48b cleanup: remove pointless cylinder model update
In DivePlannerPointsModel::clear(), the cylinder model is
updated before it is cleared. This must be an artifact.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
891839d254 planner: move same-time check to DivePlannerPointsModel
There must not be two dive planner points at the same time
stamp, as this violates the laws of physics (and internal
assumptions).

The corresponding test was done in the profile code at
two different places with floating point arithmetics.
This is a bad idea, because
1) code duplication
2) danger of rounding issues

Instead, do this in one central point in the planner model
and use integer arithmetics. Simply add a few seconds until
a unique timestamp is obtained.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
dee1fea683 planner: implement move semantics in DivePlannerPointsModel
When reordering the points, the DivePlannerPointsModel would
not emit the appropriate move signals, but simply a data-changed
signal over all elements. This obviously violates Qt's
model/view API, though it is probably harmless. Let's do
the right thing so that the frontend knows that the selected
item changed place.

Also, emit dataChanged only on the actually changed element,
not all elements.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
1b14a211f0 planner: fix removal of points from DivePlannerPointsModel
The beginRemoveRows() function was fed erroneous values. It
is a mystery why this didn't crash. In any case, deletion
of multiple points did not work properly. Instead of trying
to be fancy, remove each point one-by-one.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
35c5ec09b7 planner: insert point at correct position
Instead of inserting the point at the calculated
position, the DivePlannerPointsModel would append it
at the end and then resort the vector. That's just
silly.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
1e525244e6 cleanup: use proper model/view semantics in DivePlannerModel
When clearing the model, use "beginResetModel/endResetModel"
instead of "beginRemoveRows/endRemoveRows".

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
d68c3d8ab5 cleanup: add DivePlannerPointsModel::addDefaultStop() function
When clicking on "+" in the planner, a default stop point was
added using a signal/slot connection. This used the archaic
string-based connect syntax, because it was realized with
default parameters passed to "addStop()". Instead, add a
"addDefaultStop()" slot, which passes the default parameters.
Since all other callers do not use callbacks, unslotify
"addStop()". The slot was the only user of the default parameters,
so they can be removed alltogether.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
5196ea6149 cleanup: constify DivePlannerPoints model accessor functions
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
216a910f56 planner: unslotify two functions in DivePlannerPointsModel
There are a few more candidates, but these conceptually really
shouldn't be slots. getSurfacePressure() is an accessor and
loadFromDive() initializes the model with a dive.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02 13:53:23 -07:00
Berthold Stoeger
a988e3c135 core: initialize dive selection after resetting the data
The dive selection was initialized during data-reset. However,
this emitted a signal before all data-reset routines were run.
Ultimately, this led to access-after-free in the statistics code.

Instead, move the select_newest_visible_dive() signal from the
divelist-model to the process_loaded_dives() function. There
is no point in initializing the selection if the dive data
is cleared after all.

This change broke closing of the log, because the UI-selection
was not reset. Therefore, when clearing the data, clear the
selection before proceeding with clearing.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-03-31 13:54:23 +02:00
Berthold Stoeger
642d9c80b3 planner: pass in_planner argument to decoMode()
To remove reliance on global state, pass an "in_planner" argument
to decoMode(). Thus, calls to in_planner() can be removed.

This is a more-or-less automated change. Ultimately it would
probably be better to pass the current deco-mode to the affected
functions instead of calling decoMode() with an in_planner
parameter.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-17 07:26:55 -08:00
Berthold Stoeger
b3e4c9c8da desktop: cache photo and geo icons
The icons shown in the dive list were rendered for every single
access. Render them only once. This supposes that the
defaultIconMetrics structure does not change once the icons are
rendered!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-10 14:33:15 -08:00
Berthold Stoeger
e79ac9c7ed cleanup: make a few DivePlannerModel functions private
It simplifies reasoning about control flow a lot if it is known
that functions can't be invoked from a different part of the code
base.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20 10:01:50 -08:00
Berthold Stoeger
5e1dcb0655 cleanup: remove dive parameter from DivePlotDataModel::setDive()
This was not used, probably an artifact from days long gone.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20 10:01:50 -08:00
Berthold Stoeger
764aa6c512 planner: remove DivePlannerPointsModel::startTimeChanged signal
The way the starting time of a new plan was set was bonkers:

1) PlannerWidgets::planDive() invokes DivePlannerPointsModel::
   createSimpleDive().

2) createSimpleDive() calls DivePlannerPointsModel::
   setupStartTime()

3) setupStartTime() emits a signal startTimeChanged()

4) startTimeChanged is caught by PlannerWidget and sets
   the UI field

5) change of the UI field emits a timeChanged() signal which
   is connected to DivePlannerPointsModel::setStartTime()

6) setStartTime() sets the time of the plan and displayed_dive
   and emits dataChanged()

7) dataChanged() replots the dive()

8) Back in DivePlannerPointsModel::createSimpleDive() the diveplan
   start time is overwritten with displayed_dive (the value are
   equal owing to 6)

Wow!

But it gets worse:

9) The initial dive plan is set up in createSimpleDive().

Since the profile is drawn in 7) after clearing the displayed_dive
and before constructing the initial plan, the profile is shown
on a dive without samples. It therefore generates a dummy profile.

To make this somewhat less insane, remove the startTimeChanged()
signal in 3), explicitly set the start time of plan and dive to
the one calculated by setupStartTime() and explicitly set the UI
filed in the plannerWidget.

This still indirectly draws the profile via signals in a convoluted
way, but at it straightens out things somewhat. Most importantly,
the profile doesn't have to generate a fake DC.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20 10:01:50 -08:00
Dirk Hohndel
4c5997bcbe mobile/cleanup: reduce the noise in our logs
There are two sets of messages that tend to dominate the logs
- the RSSI updates from the Qt BLE stack
- the warnings about deprecated signal use in Kirigami

Neither of them provide any value to us when trying to find bugs; and
often they end up hiding the things that we really care about. So let's
just not log them - which is easy as we have our own message handler.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-13 16:16:31 -08:00
Berthold Stoeger
235146a95f profile: pass dive to DiveHandler
The DiveHandler shows a context menu where a cylinder can be
chosen. This indirectly accesses the global displayed_dive
variable.

Remove this in a step to make the profile reentrant.

The code was quite ominous: instead of simply generating the
list of cylinders, a global model was reset and then accessed
with Qt's cumbersome model/view API. All this trampling over
global state can be removed by simply making the function
that generates the list globally accessible.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
0104b0a915 profile: explicitly update profile items
Instead of listening to the dive-data-model changed and
axis changed signals, update the profile items explicitly
once per plot() call. This avoids double replotting of the
dive items.

The old code had at least two replots per plot() call:
one after profileYAxis()->setMaximum() and one after
dataModel->emitDataChanged().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
f4103e4998 cleanup: const-ify DivePlotDataModel::*max() functions
These functions return the maximum partial pressures in the
given dive. Obviously, being pure accessors, they should be
const.

This commit also replaces the macro generating these functions
by a call to a function taking a pointer-to-member. Arguably,
C++'s pointer-to-member syntax is just as horrible as macros,
but at least it doesn't mess with syntax highlighting of
my editor and should be better to debug.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Berthold Stoeger
975c123a30 profile: remove redundant code in DiveCalculatedCeiling
The DiveCalculatedCeiling profile-item has a recalc()
function, which calls "dataModel->calculateDecompression()".
This is a questionable reversal of control-flow: The
profile-item should paint the model-data not change it.

The code was supposed to be called under two conditions:

1) The value of the calcceiling3m preferences flag changed.
   This code was buggy for two reasons: Firstly, the cached
   value was always initialized to false, which means that
   sometimes the first call was missed. Secondly, the
   settingsChanged() functions was only called when closing
   the preferences window, not when changing the flag in the
   profile widgets.

2) The datetime of the dive changed. The whole control-flow is
   pretty absurd (due to "bit rot"):
     - The replan-dive command sends a date-time changed signal.
     - The main tab changes the date-time and informs the profile.
     - The profile sends a signal to the item.
     - The item instructs the model to recalculate the
       decompression.
     - The model causes the profile to be redrawn.

In any case, the whole thing is moot, because the decompression
is recalculated for *every* profile plot in create_plot_info_new().

Let's remove the code from the DiveCalculatedCeiling profile-item
and the calculateDecompression() function, which is now not
used anymore.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10 15:57:39 -08:00
Dirk Hohndel
2a579987c2 fix potential crash in GPS code
If we don't have a GpsLocation instance, we shouldn't dereference it.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-01 12:38:50 -08:00
Berthold Stoeger
bbbd4c8818 cleanup: remove getDivesInTrip() in qthelper.cpp
This function was not used anywhere. Moreover, remove a few
unused includes from qthelper.h. Surprisingly, a number of users
of qthelper.h depend on these, so readd them at the appropriate
places.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-29 08:34:09 -08:00
Berthold Stoeger
c53bab8965 filter: internalize shown_dives in DiveFilter class
one piece of global state removed!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-29 08:34:09 -08:00
Berthold Stoeger
51d0c42a5c filter: move shown_dive from divelist.c to divefilter.cpp
Arguably, the number of filtered dives is a matter of the divefilter.
Let's move it there.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-29 08:34:09 -08:00
Berthold Stoeger
e80c0d2c60 filter: reset shown_dives in filter
The shown_dives variable was reset by the dive_list code. Arguably,
the filter should keep track of the number of shown dives, so move
the resetting there. This means adding a new "reset()" member function
to the filter and call that instead of "updateAll()" when the core
data is reset.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-29 08:34:09 -08:00
Berthold Stoeger
1037c15b98 mobile: remove DiveObjectHelper code
When editing a dive, a DiveObjectHelper of the unmodified dive
was created to compare the edited with the old values. Since
the DiveObjectHelper is used here only as a pointless wrapper
around the formatting functions, call these functions directly.

However, note that the code is in principle wrong since the
change to the mobile-models, which do not use the DiveObjectHelper.
The real fix would be to reload the data from the model to prevent
going out-of-sync with respect to the formatting routines!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17 13:03:56 -08:00
Berthold Stoeger
ae182c386b printing: remove DiveObjectHelper from printing code
At this point (post grantlee), DiveObjectHelper is just pointless
glue code. Let's remove it from the printing code and call the
formatting functions directly. If necessary, move these functions
to core/string-format.cpp.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17 13:03:56 -08:00
Berthold Stoeger
bf8261c001 core: create string-format.cpp source file
The mobile version of the list used string formatting functions
defined in DiveObjectHelper and declared in mobilelistmodels.h.
Very confusing. Move them to a separate source file where - in
the long run - all the string-formatting functions, which
are scattered all over the place, can be collected.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-12-17 13:03:56 -08:00
Berthold Stoeger
50b11024d6 core: keep tank infos in a dynamic table
The list of known tank types were kept in a fixed size table.
Instead, use a dynamic table with our horrendous table macros.
This is more flexible and sensible.

While doing this, clean up the TankInfoModel, which was leaking
memory.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-13 11:49:59 -08:00
Berthold Stoeger
2d7be7a0e3 preferences: create global settingsChanged signal
So far, the PreferencesDialog emitted a settingsChanged signal.
This meant that models that listened to that signal had to
conditionally compile out the code for mobile or the connection
had to be made in MainWindow.

Instead, introduce a global signal that does this and move
the connects to the listeners to remove inter-dependencies.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-12 15:52:40 -08:00
Robert C. Helling
40311362f3 downloader: save downloaded dives
Signed-off-by: Robert C. Helling <helling@atdotde.de>
2020-12-03 13:26:55 -08:00
Robert C. Helling
5e34531e32 downloader: wait for download thread
Signed-off-by: Robert C. Helling <helling@atdotde.de>
2020-12-03 13:26:55 -08:00
Dirk Hohndel
5a8db97819 build-system: add models and shared backends to the downloader
We'll need this in order to be able to actually open dive files and
download things from a dive computer.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-12-03 13:26:55 -08:00
Berthold Stoeger
b36178a00a cylindermodel: remove in_planner() use
in_planner() is problematic, since it is uses desktop-only
application state. Since the cylinder-model already has
an appropriate inPlanner flag, use this instead.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-11-24 10:54:10 +01:00
Berthold Stoeger
e47b812fd0 diveplannermodel: replace in_planner() by isPlanner()
The in_planner() function is problematic, because it depends
on the application state that is only available on desktop.
If we ever want to port the planner to mobile, we have to get
rid of it. Luckily, the DivePlannerModel already has an
appropriate flag that can be used instead.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-11-24 10:54:10 +01:00
Berthold Stoeger
38a784f5af desktop: automatically reload completion-models
Instead of programatically reload the completion models, listen
to the relevant signals in the models. To that goal, derive all
the models from a base class.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-11-14 10:01:50 -08:00
Berthold Stoeger
67d956b44c cleanup: remove macros from qt-models/completionmodels.cpp
There were macros to auto-generate functions to reload the models.
One was only used once and therefore is pointless. The other can
be replaced by a function with a pointer-to-member-variable argument.

While doing this, adapt the coding style.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-11-14 10:01:50 -08:00
Berthold Stoeger
396598430b desktop: fix saving of column-widths of device and site tables
Qt's memory management scheme is completely broken and messes
with common expectations.

QObjects are organized as a tree. The children are destroyed
in the destructor of QObject. This means that they are destructed
after the destructor of the parent object has run and its
sub-object were destructed. Obviously, this makes no sense as
the child objects should be able to access their parent at
any time.

To restore the commonly expected deterministic order of
construction and destruction, one might simply do away with
Qt's silly object tree and organise things using classical
subobjects. However, that breaks with the Qt-generated UI
classes: The objects generated by these classes are *not*
destructed with the UI class. Instead, they are attached
to the widget's QObject tree. Thus these are again destructed
*after* the widget! Who comes up with such a scheme?

In our case this means that we cannot have models used for
TableViews as subobjects, because the TableView needs the
model to save the column widths in the destructor. Which,
as detailed above is called *after* the desctructor of the
widget! Thus, turn these models into heap-allocated objects
and add them to the QObject tree.

Funilly, this exposes another insanity of Qt's QObject tree:
Children are destructed in order of construction! One would
expect that if objects are constructed in the sequence
A, B, C one can expect that C can, at any time, access B and A.
Not so in Qt: The destruction order is likewise A, B, C!

Thus, take care to init the widgets before the model. Jeez.

Finally, print a warning in the column-saving code of
TableWidget, so that these kind of subtleties are caught
in the future.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-11-07 11:37:51 -08:00
Dirk Hohndel
ffecc00f42 cleanup: SkipEmptyParts syntax has changed
Sadly, the new enum has only been available since Qt 5.14, so this is a rather
ugly replacement.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-10-26 19:27:03 -07:00
Berthold Stoeger
0e196310f9 cleanup: split out divecomputer functions from dive.c
Since dive.c is so huge, split out divecomputer-related functions
into divecomputer.[c|h], sample.[c|h] and extradata.[c|h].

This does not give huge compile time improvements, since
struct dive contains a struct divecomputer and therefore
dive.h has to include divecomputer.h. However, it make things
distinctly more clear.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25 13:59:52 -07:00
Berthold Stoeger
d82a7b8b73 cleanup: remove DiveComputerModel::remove
This was used by the DiveComputerDialog, which does not exist
anymore. The new tab uses the function in the corresponding
sorted model.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25 13:59:04 -07:00
Berthold Stoeger
c6188bbe47 devices: connect DiveComputerModel to undo-command
Instead of modifying the device table directly, call the undo
commands. Moreover, don't keep our own copy in the mode - show
the original version. Connect to the appropriate signals.

This means that the calls from the DiveComputerManagement
dialog have to be removed, since this mode of editing is
not supported. The whole dialog will be removed in a future
commit.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25 13:59:04 -07:00
Berthold Stoeger
4467477389 models: update DiveComputerModel when core data is reset
To implement undo-semantics, we want a longer-lived dive-computer-model
(currently, it is regenerated when the dialog is opened). Therefore, it
must be reloaded when the core data is reset. Do this like for other
models: listen to the dataReset() signal of DiveListNotifier.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25 13:59:04 -07:00
Berthold Stoeger
fa7dfa3710 desktop: add tab-widget for dive computer names
If we want to include dive computer names in the undo system,
there should be visual feedback on undo/redo.

This would mean opening the divecomputer dialog, which would
appear quite strange. Therefore, add a tab. This is not ideal,
but consistent with the dive site tab, which probably shouldn't
be there either. In the future, the UI needs some rethinking.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25 13:59:04 -07:00
Dirk Hohndel
e30ba8a8e0 cleanup: fix over-eager Coverity warnings
Technically get_dive(i) could return a nullptr. But given the range for i that
can never happen. Still, the test is extremely cheap and doesn't hurt.

Fixes CID 354768
Fixes CID 354766

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-10-25 13:58:03 -07:00
Berthold Stoeger
2bcb3d88a0 divecomputer: add device_table pointer to device_data_t
In one weird case (suunto), the code in libdivecomputer.c
generates a device node directly instead of going the usual
way (setting the data in the dc-structure of the imported
dive). It is unclear to me whether that has to be that way,
as it depends on the chronological order of callbacks to
event_cb() and dive_cb().

Therefore add a device_table pointer to device_data_t
so that the downloader can add the device to this table. This
only adds the pointer, but does not yet use it in the
downloading code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-24 09:51:37 -07:00
Berthold Stoeger
39a4090c0a devices: add devices in Command::importTable()
Add a device_table parameters to Command::importTable() and
add_imported_dives(). The content of this table will be added
to the global device list (respectively removed on undo).

This is currently a no-op, as the parser doesn't yet fill
out the device table, but adds devices directly to the global
device table.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-24 09:51:37 -07:00
Berthold Stoeger
4a50badb57 cleanup: use std::vector in struct device_table
Since we converted from QString to std::string, let's also use
std::vector instead of QVector. We don't need COW semantics
and all the rigmarole. Let's try to keep Qt data structures
out of the core.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-16 14:26:37 -07:00
Berthold Stoeger
fd8bd9d5c7 cleanup: use std::string in struct device
struct device is a core data structure and therefore shouldn't use QString.
QString stores as UTF-16 (which is a very questionable choice in itself).
However, the real problem is that this puts us in lifetime-management
hell when interfacing with C code: The UTF-16 has to be converted to
UTF-8, but when returning such a string, this puts burden on the caller
who has to free it. In fact, instead of looping over devices from C-code
we had a callback that sent down temporary C-strings with qPrintable.

In contrast, std::string is guaranteed to store its data as
contiguous null-terminated and C-compatible strings. Therefore,
replace the QString by std::string. Keep the QString just in
one place that formats a hexadecimal number to avoid any
potential change.

The disadvantage of using std::string is that it will crash
when constructed with a NULL argument, consistent with C-style
functions such as strcmp, etc. Arguably, NULL is different
from the empty string even though we treat both as the same.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-16 14:26:37 -07:00
Berthold Stoeger
215e5a4544 desktop: make divecomputer table sortable
Add a small proxy-model on top of DiveComputerModel so that clicking
on table headers makes the table sortable.

The UI feature here is not as important as the fact that the UI does
its own sorting and we can keep the device-table in the core sorted
differently.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-11 08:35:20 -07:00
Berthold Stoeger
5bc6f5d36c cleanup: make device code more consistent with core
We keep track of device, i.e. distinct dive computers with id in the core.
The corresponding code stuck out like a sore thumb. Firstly, because it
is C++. But more importantly, because it used inconsistent nameing conventions.

Notably it defined a "DiveComputerNode" when this is something very different
from "struct dive_computer", the latter being the dive-computer related
data of a single dive.

Since the whole thing is defined in "device.h" and the function to create
such an entry is called "create_device_node", call the structure "device".
Use snake_case for consistency with the other core structures.

Moreover, call the collection of devices "device_table" in analogy
with "dive_table", etc.

Overall, this should make the core code more consistent style-wise.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-03 10:53:26 -07:00
Berthold Stoeger
cd22b86bf8 dive list: when moving dives, delete first and add later
When moving dives between trips, the core moves the dives internally
and sends a signal to the model. The model adds and removes the dives
accordingly. However, when adding the new dive, the old trip hasn't
changed its position, so the ordering is wrong leading to an inconsistent
state.

Therefore, remove the dives first and then readd them. There could
still be pathological cases where this fails. However, in the short
term this is an improvement. Note that in similar cases, the dives were
indeed removed then added, so this case here seems to be an oversight.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-03 10:01:13 -07:00
Berthold Stoeger
00abc04913 cleanup: use getDiveSelection() to loop over selected dives
getDiveSelection() returns a vector of the selected dives.
Use that instead of looping over the dive table and checking
manually.

This removes a few lines of code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-03 10:01:13 -07:00
Berthold Stoeger
f4ee893424 cleanup: replace get_trip_date_string() by get_trip_string()
The get_trip_date_string() formatted, as the name implies, the date
of a trip. It was passed a number of parameters and had only one
caller, which would also add the location if it existed.
Therefore, move all that logic into the helper function and
name it get_trip_string().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-03 10:01:13 -07:00
Berthold Stoeger
f9721fce4b filter: implement importing of filter presets
When importing a divelog, import filter presets. If there are
equal names, import only if the presets differ. In that case,
disambiguate the name. This made things a bit more complicated,
as comparison of filter presets had to be implemented.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-29 16:13:03 -07:00
Berthold Stoeger
51959d0feb filter: connect DiveListNotifier signals to filter preset model
Thus, the model is kept up to date if filter presets are changed
by undo commands.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-29 16:13:03 -07:00
Berthold Stoeger
536fc05dd6 filter: add (very primitive) filterpresetmodel
Implement a trivial model to provide the filter preset names
to the UI. Sadly, for now this features the QWidget/QML
column / name dichotomy. However, in this simple case that
shouldn't be too much of an issue.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-29 16:13:03 -07:00
Berthold Stoeger
af9d379a41 filter: add filter constraint model
Add a model that keeps track of a list of filter constraint and makes
them accessible from Qt. Sadly, this is mostly repetitive boiler-plate
code, but this is due to Qt's model/view-API, which is a perfect example
of how *not* to design a reasonable modern API.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-29 16:13:03 -07:00
Robert C. Helling
efdc875aa3 Use correct pO2 when computing MOD in equipment tab
The cylinder model is used both in the planner and the
equipment tab. We have three preferences for the pO2 that
is used to compute MOD: In the planner, there is one for
the bottom part of the dive and another one for deco.
Those are set in the planenr UI. There is another value,
controlled in the Tec Prefernces. That one should be
used in the equipment tab rather than the one from
the planner.

Fixes #2984

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2020-09-29 15:46:55 -07:00
Dirk Hohndel
a469dfa348 mobile/dive-list: correctly update view when changing dive date
If the dive timestamp changes, the dive could move in the dive list. But the
current dive actually doesn't change (it's still the same dive, right?). Yet
we need to update the dive list as well as the shown dive (especially if this
is after adding a dive, which is first inserted with the current time and then
updated with whatever the user enters).

Fixes: #2971

Suggested-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-09-27 14:16:18 -07:00
Berthold Stoeger
43390d4a9a dive list: on reload update filter status
At some time, when introducing the global reset signal the filter
stopped being reloaded when loading a new log. This leads to very
strange UI behavior: dives disappear when editing fields unrelated
to the filter.

Therefore, when reloading the model, reset the filter. One might
argue whether this is the correct place. On the other hand, we
might even make the filter a sub-object of the dive-list model.
Let's think about this.

Partially solves #2961

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-20 18:21:56 -07:00
Berthold Stoeger
a01ab81713 cleanup: fold core/divecomputer.cpp into core/device.c
core/device.h was declaring a number of functions that were related
to divecomputers (dcs): creating a fake dc for manually entered dives
and registering / accessing dc nicknames. On could argue whether
these should be lumped together, but it is what it is.

However, part of that was implemented in C++/Qt code in a separate
core/divecomputer.cpp file. Some function therein where only
accessible to C++ and declared in core/divecomputer.h.

All in all, a big mess. Let's simply combine the files and
conditionally compile the C++-only functions depending on
the __cplusplus define.

Yes, that means turning device.c into device.cpp. A brave soul
might turn the C++/Qt code into C code if they whish later on.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-13 13:54:59 -07:00
Berthold Stoeger
e6145b5498 cleanup: remove DiveComputerModel::numRows
This member variable was unused.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-13 13:54:59 -07:00
Berthold Stoeger
6ea0cc62b8 desktop: refine auto-fill of weights
In a previous commit, auto-filling of weight based on type was
changed to be only performed if the user hadn't already set a
weight, by testing for weight=0.

However, when the user edited the type and tabbed back and forth,
that counted as an edit and therefore the weight would not
change anymore.

To refine this, introduce an "auto_filled" flag to the weightsystem,
which is set if the weight is automatically filled and cleared if
the weight is edited. Update the weight if it was zero *or* auto-filled.

The flag is not saved to disk, but that should be acceptable. If the
user saves and reloads, we can assume that they meant the weight
to be set to the default value.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-12 10:36:36 -07:00
Berthold Stoeger
72312bec2f desktop: on weight type change, don't overwrite weight if already set
When importing from other software, it happens that weights are imported
without their type. When the user changes the type, the imported weight
is overwritten, which is not exactly a friendly behavior.

On the other hand, when changing the type after creation of a weight
entry, it is preferrable to set a default weight. This is convenient
for people who commonly use the same weight.

As a compromise, set the default weight only if it was unset. We
recognize this by a weight value of 0 g.

Fixes #2938

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-12 10:36:36 -07:00
Robert C. Helling
e946ce98fe Planner: enforce minimal segement duration
You cannot be at two depths at the same time (and it confuses
the planner). So give yourself at least 10 seconds.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-08-24 08:31:40 -07:00
Robert C. Helling
62d87e9d25 Planner: handle zero length segments when replanning
When setting up a dive for replanning, we ignored zero length segments as those
tend to be generated by gas changes. But it is possible to enter those in the
planner and the replanning should not ignore those. So be
more clever about gas changes. Let's add 10 seconds so we are not at two depths
at the same time and help since add_stop also does not like zero length
segments (it thinks we are trying to replace a waypoint).

Fixes #2901

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-08-24 08:30:00 -07:00
Berthold Stoeger
fe3021b88a cleanup: consistently use get_cylinder() accessor
get_cylinder(d, i) is more readable than d->cylinders.cylinders[i].
Moreover, it does bound checking and is more flexible with respect to
changing the core data structures. Most places already used this accessor,
but some still accessed the cylinders directly.

This patch unifies the accesses by consistently switching to get_cylinder().
The affected code is in C++ and accesses the cylinder as reference or
object, whereas the get_cylinder() function is C and returns a pointer.
This results in funky looking "*get_cylinder(d, i)" expressions.
Arguably still better than the original.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-08-21 08:48:22 -07:00
Robert C. Helling
912e1faaf2 Make MND display depend on O2 narcotic preference
A while ago, we introduced a preference whether O2 should
be considered narcotic. We used this when computing
best mix or when entering the He content via MND. But
we forgot to make the displayed MND depend on this
preference. This patch add this.

Fixes #2895

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2020-07-11 10:37:49 -07:00
Berthold Stoeger
8f80129bac cleanup: create common QDateTime -> timestamp conversion function
In analogy to the timestamp -> QDateTime conversion, create a
common function.
1) For symmetry with the opposite conversion.
2) To remove numerous inconsistencies.
3) To remove use of the deprecated QDateTime::toTime_t() function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-22 12:31:06 -07:00
Berthold Stoeger
f63485b444 cleanup: move timestampToDateTime() to qthelper.cpp
Move this function from maintab.cpp to qthelper.cpp. Since the
functionality was used in numerous places, use the helper function
there as well. This removes a number of inconsistencies. For example,
sometime setTimeSpec(Qt::UTC) was called, even though the
QDateTime object was already created with that time spec.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-22 12:31:06 -07:00
Berthold Stoeger
d30b773365 cleanup: remove redundant model source files in CMakeLists.txt
The divetripmodel.cpp, models.cpp and tankinfomodel.cpp source
files as well as the corresponding headers were listed as "general"
and as "desktop" models, i.e. twice. Remove the redundant entries in
the desktop list. This should have no consequence whatsoever.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-15 14:19:21 -07:00
Berthold Stoeger
7533f4490b cleanup: replace to "dive.h" includes by more specific includes
The weightsystem- and cylinder-model headers were including "dive.h".
Inclusion of "equipment.h" is sufficient though.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-15 14:19:21 -07:00
Dirk Hohndel
4db79c8db9 mobile/models: add access to tags string
We already allow filtering by tags, but don't even show them on mobile.
That seems rather inconsistent.
First step is to make the tags available to the QML layer.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-05-14 12:57:08 -07:00
Berthold Stoeger
7a443423bc cleanup: generalize ExtraDataModel to display data of any dc
The goal here is to remove a dependency on displayed_dive.
While doing so, make the model more general and display any dc.
Pass in the dc of the current dive instead of displayed dive,
since all other tabs are already converted to show data of
the current dive. The QStrings are cached since we generate
them anyway, so we may just keep them. Thus, there is no
danger of the dc becoming invalid.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-07 08:46:15 -07:00
Berthold Stoeger
2ff459c356 cleanup: return directly in ExtraDataModel::data()
Instead of assigning to a ret variable and returning at the
end of the function, return directly from the various switch
branches. This is more idiomatic and consistent with the other
models.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-07 08:46:15 -07:00
Berthold Stoeger
6790e07a4c cleanup: use begin/endResetModel in ExtraDataModel
As we do in most other models, use begin/endResetModel() to
reset the model. This is distinctly less errorprone than
the add/removeRows() version as we don't have to check for
empty ranges, etc.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-07 08:46:15 -07:00
Berthold Stoeger
fb6210a99a cleanup: invert control-flow when resetting the core structures
To reset the core data structures, the mobile and desktop UIs
were calling into the dive-list models, which then reset the
core data structures, themselves and the unrelated
locationinformation model. The UI code then reset various other
things, such as the TankInformation model or the map. . This was
unsatisfying from a control-flow perspective, as the models should
display the core data, not act on it. Moreover, this meant lots
of intricate intermodule-dependencies.

Thus, straighten up the control flow: give the C core the
possibility to send a "all data reset" event. And do that
in those functions that reset the core data structures.
Let each module react to this event by itself. This removes
inter-module dependencies. For example, the MainWindow now
doesn't have to reset the TankInfoModel or the MapWidget.

Then, to reset the core data structures, let the UI code
simply directly call the respective core functions.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-07 08:43:27 -07:00
Berthold Stoeger
d62e60277c dive list: update dive list entry if pictures changed
We show an icon whether there are pictures and whether they are
before or after the dive. Thus, the list models must emit the
proper signals when the pictures of a dive change.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
434644b381 undo: make picture (media) deletion undoable
The code is rather complex. Firstly, we have different representations
of pictures throughout the code. Secondly, this tries to do add the
pictures in batches to the divepicture model and that is always rather
tricky.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
9962d47b56 media: turn DivePictureModel::pictures into std::vector
QVector doesn't have a function to insert a range of pictures,
which we will need for undo of image adding/deletion.

Moreover, std::vector gives us stronger guarantees. For example,
if capacity is large enough, it guarantees that there will be
no reallocation and thus iterators stay valid. I have not found
such a guarantee in the Qt docs.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
bd960ea088 media: store dive instead of dive-id in DivePictureModel
dive-pointers are stable and the dive picture model is reset
if a selected dive is removed, so there is no risk in keeping
pointers.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
0d06eb83d8 media: don't send dive-id in drag&drop event
The profile-widget doesn't use that information anymore.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
e61641c79c undo: implement undo of setting a picture time by drag&drop
Even though the functionality is seemingly trivial, this is a bit
invasive, as the code has to be split into two distinct parts:
1) Post undo command
2) React to changes to the divelist

Don't compile that code on mobile.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
989d6a3f96 media: use table instead of linked list for media
For consistency with equipment, use our table macros for pictures.
Generally tables (arrays) are preferred over linked lists, because
they allow random access.

This is mostly copy & paste of the equipment code.

Sadly, our table macros are quite messy and need some revamping.
Therefore, the resulting code is likewise somewhat messy.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
4d407dc666 pictures: turn QString into std::string for filenames
For undo of picture manipulation, it will be crucial that the
model and the core have the same order of pictures. The first
sort criterion will be time, the second filename in the case
that two pictures have, for whatever reason, the same timestamp.

However in the core we us C-strings and thus sort byte-wise
using strcmp. In the Qt-part we use QStrings, which sort according
to unicode encoding. To enable consistent sorting, change the
Qt-part to std::string, which uses a C-style 0-terminated string
as its backing store.

One might argue that in general filenames should use system-encoding
and therefore use std::string instead of QString. However, a
broader conversion to std::string turned out to be very painful,
since Qt is (deliberately?) difficult to use with std::string.
Notable all the file-manipulation functions don't take std::string
by default. Thus, this commit only converts the internal data
of DivePictureModel, but continues to use QString for the Qt-facing
interface.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
30133946e0 models: emit dive changed signal when cylinders edited
To display changed SAC values it is necessary that the models
emit changed signals when cylinders are edited. An alternative
might be that the undo commands emit dive-changed signals themselves.

Fixes #2814.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 11:44:22 -07:00