Commit graph

19869 commits

Author SHA1 Message Date
Berthold Stoeger
01af4bcd00 profile: remove min/max entries from plot_data
These were the minimum and maximum of a 9-min window.
The profile now uses an adaptive peak-search, so this is not
used anymore.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
7ef0ae02a8 profile: implement adaptive depth markings
The old code used the maximum / minimum values of nine-minute
intervals to indicate maximum / minimum depths. This does not
work well when zooming, since the labels will get sparse.

Instead implement a primitive peak finding algorithm, that
searches for the deepest peak in the whole plot and then
repeats the procedure for the right and left sides, leaving
out a certain distance to the origninal peak. This is repeated
until there are no more peaks found.

Only peaks of a certain prominence are considered, which
conveniently gives us the valleys.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
efc89b9d9c profile: use dynamic distances between labels on chart
Use variable intervals for printing temperature and heart
beat labels. Obviously, so that the labels don't become
sparse on zooming, but also to make them not too crowded
on mobile / small screens.

This doesn't work for depth labels, because these labels
use data provided from the profile.c core that doesn't
know about the size of the chart.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
5c83fcd647 profile: attempt to port mobile-visibility code
There was a bunch of conditionally compiled code on mobile
that had special hiding/unhiding rules.

Try to unify that with the desktop code by introducing a
"simplified" flag. This certainly breaks and will have to
be finetuned. In particular, I can't test CCR dives, which
are treated specially on mobile.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
1a429d9b17 profile: don't plot event-icons outside of range
Do this by extending the isInteresting() function for
dive event items.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
a496ab016b profile: remove visibilityKey members of a few DiveProfileItems
There were no users.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
073059f5ab profile: clip DiveProfileItems
Avoid "overshooting" of the profile items by linearly clipping
the first and last segment to the boundaries of the time-axis.

Sadly, quite a lot of code, because every profile item is
slightly different.

In particular the pressure-segment handling was rewritten.
It now stores the begin and end of each segment to draw
the appropriate text items.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
56f6e5051f profile: fix displaying of gas pressures
Due to bit-rot the gas pressure and gas type were displayed on top
of each other. I don't understand the meaning of the old code
[log10(log10(axisRange))] (!). Therefore let's just add the height
of the label to separate the labels.

Probably needs some fine-tuning.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
85d1e1d199 profile: only plot visible range of tank info
This was a rather trivial change: simply pass in the first
and the last second to the plot function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
d97cc8d4d5 profile: remove TankItem::plotEndTime member variable
That variable was only used in a single function and
always reset at the beginning of the function. No point
in being a member variable.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
118700fd18 profile: pass [from,to] range to polygon plotting functions
Only plot the zoomed range. Currently this passes the sample
before and after the range, so it generally "overshoots" by
one sample in each direction. The plan is to do clipping
on the first and last polygon segment later on.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
c09382036f profile: don't use scene for zooming
We were using the QGraphicsScene machinery to zoom into the
plot. This not only zoomed into the dive, but into the whole
thing. In general, one couldn't see the axes anymore.

Instead, adjust the range of the time-axis according to the
zoom-level and position.

Of course, the code isn't adapted to that and the result
is comical. The chart features will have to be fixed
one-by-one. Oh joy.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
7d3e246680 profile: explicitly reset zoomLevel when plotting a new dive
Currently, the zoomLevel is reset for every plotDive() call,
because the zooming is done via the QGraphicsScene. However,
this does not work well (e.g. axes are likewise zoomed) and
in the future a change of the zoom level will cause a replot.

Thus, remove the zoom-reset in plotDive() and do it explicitly
when switching dives.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
7051bee7e1 profile: remove ProfileWidget2::zoomFactor member
This is a constant, no point in keeping it as a member variable.
Contains removal of a pointless #ifdef (guarding against mobile,
but code not compiled on mobile), a typo-fix in a comment and
replacement of Qt's idiosyncratic qreal by double.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
2f9c0c04b5 profile: replace orientation by inverted flag
There were two somewhat redundant flags for the axes: the position
(left, right, bottom) and the orientation (up-down, left-right, etc).

Replace the latter by an inverted flag: if true, the axis is
up-down or right-left, i.e. the opposite of what one would expect
for a normal graph.

Set the flag in the constructor and remove the setOrientation()
function.

Sadly, the code is a bit complex, because screen coordinates are
top-to-bottom. Who thought that would be a good idea?

Note: this also fixes the placement of the ticks of the time
axis.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
3a79f3e78a profile: set textColor in constructor of DiveCartesianAxis
There were virtual functions to calculate the label colors
based on the value of the label. However, these functions
only returned constant values. Therefore, just set these
in the constructors.

Thuse, a few virtual functions and derived classes can be
removed.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
ea59e5cf7a profile: remove DiveCartesianAxis::gridColor member variable
This was only used in the constructor to create the pen for
the grid lines. Not need to keep it around.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
7bc90b6dfe profile: set visibility of text and lines in constructor
The visibility of axis text / lines is never changed, so set
in axis constructor.

Moreover, instead of rendering the lines/text and then setting
them invisible, do not render them if invisible.

The whole thing appears superfluous, since the proper way to
not show lines/text is to just not call updateTicks on the
axis. But in the future we might want to have axes with text
but no lines, so keep for now.

Since this means breaking out the text / line rendering
into their own function, we might rename some variables to
make them (at least somewhat) more clear.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
a7a7bd182e profile: special case time axis
Rounding the axes dimensions to "nice" number may have been a
good idea, but for the time-axis it feels weird.

Therefore revert the time axis to the previous behavior:
range is set according to the data. To differentiate between
time an other axes, use the position: the time axis is the
only axis at the bottom. Yes, that's ugly but pragmatic.

Since we have that flag also use it for the special casing
of the text-display. Spares us one virtual function dispatch.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
3e11c13100 profile: use sensible tick-intervals
The integers were simply rounded to integers, which might give
ugly intervals (e.g. multiples of 3). Use the code of the
statistics tab, with one modification: take care not to
use intervals below the given precision. The statistics work
differently: there, the precision is adjusted according to
the interval size, not the other way around.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
99c4741508 profile: avoid double recalculation of tick positions
The ticks were recalculated twice per plotDive() call:
1) When updating the position of the axes in updateChangeLine()
2) After setting the bounds in plotDive() via setBounds()

Remove the first instance. updateChangeLine() is called in
only one place [from plotDive()] and therefore, the recalculation
is always redundant. Moreover, rename the function to setPosition(),
since it doesn't do any animation at all.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
b0faf2e4b1 profile: remove DiveCartesianAxis::sizeChanged() signal
This was used to animate the position of the dive event items
when the size of the axis changed. However, that doesn't work
since quite some time. The axes size are changed when
 1) switching dives
 2) resizing the drawing area
In the first case, the dive event items are fully recalculated.
In the second case, animation speed is set to instant, since
resizing of windows is done continuously on any reasonably
modern desktop anyway. It might make sense on mobile, where
size changes are discontinuous, but there we use static
profiles anyway. Moreover, I checked a few applications and
none of them had animations when switching orientation of
my tablet.

Let's just remove this disfunctional thing and replace it
later, should someone complain.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
2c4e4b1e86 profile: move setting of gasYAxis bounds to plotDive()
The partial-pressure-axis was the only DiveCartesianAxis
child that had its own code to set the bounds. The bounds
of all other axes were set in plotDive().

For consistency, do this here as well. Thus, the whole
class can be removed.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
0de40a85b7 profile: generalize tick generation
The number of ticks was generated for each axis with custom
code. This code was not aware of the size of the profile and
could result in overly dense or sparse ticks.

Generalize the generation of the ticks. For now, round tick
values to integers. In the future, try to use more "nice"
looking values as we do for the statistics tab.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
177df72d33 profile: unify formating of axis labels
Instead of a host of virtual functions, let the base class
(DiveCartesianAxis) do the formatting of the axis labels.
To do so, it needs to know how to convert the internal
representation (e.g. mm) into the displayed value (e.g. feet).
Moreover, this transformation has to be adapted when changing
the locale-setting, therefore do it for every plot() call.

The transformation itself cannot be a simple linear translation,
because we have non-absolute display units, namely °C and °F.
Thankfully affine transformations are enough though.

Only one custom formatter remains: the time axis. It might
be a good idea to remove the virtual function and do this
via a flag.

This is all done not so much for code simplification, but
because for a general layout of the axis labels, the
axis has to understand the values of the labels and not
only handle them as opaque texts.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
0e9eee0a7f core: return floating point from to_PSI() functions
Dive data are stored internally using integral types using
appropriately fine units (mm, mbar, mkelvin, etc.). These
are converted with functions defined in units.h for display
(m, bar, C, etc.). Usually floating points are returned by
these functions, to retain the necessary precision. There
is one exception: the to_PSI() and mbar_to_PSI() functions.

For consistency, make these functions likewise return floats.
This will be needed for the rework of the profile-axes.
The plan is to use the conversion functions to make the
axes aware of the displayed values. This in turn will be
necessary to place the ticks at sensible distances. However,
the conversions need to be precise, which is not the
case for the current to_PSI() functions.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
322e2baa8d profile: calculate maximum label sizes on construction
Instead of calculating the label sizes of the axes when
relayouting the chart, calculate them at construction time.

To do so, pass the digits before and after the decimal comma
to the constructor.

This is not so much an optimization thing, but rather an
first stab at more general label rendering. Time, of course,
will always be an exception. But hopefully the remaining
values can be done more generally.

Note that currently this code is a total mess. For example,
the labels for the temperature axes are not converted to
F if needed. And therefore also not shown. This will need
some major rethinking.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
f19ab2e4fd profile: set DiveCartesianAxis::fontLabelScale in constructor
This never changes, no need for the complexities of a setter
function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
4b9177c098 profile: remove DepthAxis constructor specialization
All this did was setting changed to true. Obviously an
artifact, since that is done in the constructor of the
base class anyway. Remove.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
89d9105209 profile: set minimum/maximum of axes with a single call
This is bike-shedding: Instead of two setMinimum()/setMaximum()
calls, use a single setBounds() call. A few axes (notably depth
and time) always have a 0 as lower bound. However, this will
change once there is a proper zooming functionality.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
0bef8167d2 profile: always update axis-positions when plotting dive
The placement of the axes was done independently of the
plotting, e.g. when settings changed. Presumably,
for performance reasons. However, since the axes may
depend on whether a dive has heart-rate data or not,
this simply is not viable. To make this work, one
would have to remember whether the previous dive
showed the heart-rate, etc. Not worth it - always
reposition the axes. It should not matte performance-
wise.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
a031f3444c profile: make DiveCartesian axis grayscale aware
I doubt that this is necessary, but since most of the rest
of the profile code passes "isGrayscale" to "getColor()",
do the same here for consistency.

To avoid storing the isGrayscale flag, just create the pens
at construction time and store those.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
2615ba02bb profile: remove DiveCartesianAxis::setColor() and setTextColor()
These functions had no users.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
ae1758d4cd profile: don't render mobile profile in printmode
There is no more reason to render the profile in printMode.
DPR is also supported in normal mode.

Moreover, don't scale the DPR down by fontScale. If we
have to scale down the fonts, we'll have to do this
differently without squeezing the rest of the profile
features.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
9c7974928b profile: indicate bookmark by pole of flag
The event-icons are positioned according to the top-left
corner (as is usual in computer circles). For the flag
icon it seems more natural to use the bottom of the pole.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
9740651e01 profile: save depth of event
The DivePlotDataModel was saved with every event to access the
depth. However, since the depth never changes, we can simply
save the depth instead.

Also, since we only need the model to access the plot_info,
pass the plot_info directly. As noted in a previous commit
message, I believe that Qt models are a very bad choice
for intra-application data transfer. They should only ever
be used to interface with Qt.

And since touching this code, pass duration_t instead of int
to depthAtTime() to make the callers less cluttered.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
9ddaf791ae profile: use binary search to find depth at event
Instead of looping over the whole data via the Qt model,
do a simple binary search. Yes, this is premature optimization,
but I had to.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
8d4d35ea69 profile: remove redundant timestamp lookup for DiveEventItems
When placing the event icons, the timestamp is looked up and
then, the depth is checked which repeats this operation.
Remove the first instance of this lookup, as it is completely
redundant.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
8a9ca5fcda profile: don't create "uninteresting" event icons
There is code to dynamically show/hide event icons of a certain
type. The same code is used to hide generally non-interesting/
redundant items.

Instead, don't even create these items. Yes, this is idle
premature optimization.

A loop over all created event icons to hide them can be
removed, because the icon is hidden anyway on construction
time.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
9e831c5001 core: remove DPR from IconMetrics class
There is no user of this left, because the device-pixel-ratio
is now passed directly to the profile.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
5f22de7ebe profile: remove special iOS DPR handling for event icons
On iOS there was special code to scale event icons with DPR
(device pixel ratio). However, that became redundant, when
printing started to also use DPR to scale the icons. Now,
on iOS icon sizes where multiplied twice with DPR.

Let's remove that and, if it is broken, try to fix it
at the correct place.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
1d58553864 profile: replace bookmark event icon PNG by SVG
This looks much better on print-outs. The remaining event icons
still need to be converted to SVG.

SVG created by Lubomir I. Ivanov <neolit123@gmail.com> and
made compatible with the Qt SVG renderer by BS.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
f7565c4a0f core: clear image before rendering SVGs
In renderSVGIconWidth() the image was not cleared, leading
to garbage backgrounds. This should have affected the video
icons. Apparently, nobody is using them..?

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
f82ae2be7f profile: cache pixmaps for dive event items
For better scalability, we might replace the dive event icons
by SVGs. Since rendering SVGs is potentially very slow, cache
the pixmaps when the scene is generated.

Note: this does not yet do any SVG rendering, only the caching
of pixmaps.

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
505e4e47eb profile: reimplement DivePercentageItem
The tissue percentages were realized as 16 independent polygons.
That didn't work at all with the new absolute scaling.

Reimplement the item and blast it onto a pixmap. Not only is
this artifact-free, it also should (hopefully) be quite a bit
more efficient than painting numerous lines.

In contrast to the old code, this does access the plot_info
structure directly instead of using the model. Not so much
for performance reason, but rather to make things more robust:
We have a strongly typed language. Why would we shoehorn data
through the weakly typed QVariant and mess with wierd
index-arithmetics. Makes no sense to me. Qt-model have to
be used for interfacing with Qt. They are terrible for
intra-application data transfer.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
24cf6709e3 profile: simplify get_maxtime()
This function has accumulated quite some cruft. It seems to add
additional space to make place for certain chart features
(e.g. the average depth text item).

However, it makes no sense to solve this here, as only the
profile knows how much place is needed to display these
features.

Therefore, basically revert this to the original version,
which simply returns the maximum time for long dives
and a threshhold for short dives that depends on the
zoomed_plot setting.

The result looks more reasonable to me, as there is no
(varying!) empty space to the right of the profile.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
179df1bf80 profile: remove DiveCartesianAxis::tick_size
No user of that. Also remove the setter function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
8046a05e95 profile: merge plotDive() into draw() call
Rendering resets the size, which now recalculates the axes.
Therefore, plotDive() must be called. The callers were doing
the opposite: call plotDive() first, then draw().

To make it easier for the callers, present a single interface
that handles these subtleties.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00
Berthold Stoeger
d0beae59f9 profile: start with "absolutizing" the profile layout
The chart items were laid out in relative terms with respect
to a fixed scene size (100.0, 100.0). This simply does not
cut it when resizing the chart. Why should the axes always
occupy the same fraction of the chart independent of the size.

Moreover, this led to basically unmaintainable code.

Resize the scene according to the viewport and do
absolute placement of the items. This breaks the layout,
but at least now we have a chance to fix things
somewhat reasonably.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-12-17 11:54:23 -08:00