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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
The profile would reload for many settings-changed signals.
It didn't listen to the deco-info-changed signal, because
that had no effect (which seems to be a bug).
Since this flag should indicate whether the deco-info is
shown and therefore a change should replot the profile,
let's listen to the corresponding signal.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The grid color is saved on construction, no need to pass a parameter.
Note that this fixes a bug where the color was passed as animation
speed. Ooops. That's what you get from weak typing.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is less hassle, than passing these around as parameters.
Note: The values are stored but not yet used ("position" has
not use yet and gridColor is still passed as parameter).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To properly layout the axes, it is necessary to specify on
which side of the chart they are located.
There is already an "Orientation" enum. However, that gives
the direction (top-to-bottom, etc.), but not the position.
It might become obsolete in the future, since the direction
can also be expressed by setting min and max accordingly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveTextItems were redrawn on every paint() call. This was
a prohibitively expensive operation (converting the text into
a path, drawing an outline, etc.), which was called numerous
times.
Instead, render the text only when changing into a QPixmap
and blit that pixmap in the paint() call.
This will make it possible to do absolutely positioned
DiveTextItems. So far they were placed relatively in
scene coordinates ranging from 0-100(!).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The text and the brush are the two properties of text items
that change dynamically. To avoid complexities concerning
redrawing, set them concurrently instead of in two separate
calls.
Since setting one of the properties requires a full redraw,
there is no performance advantage in setting them individually.
This fixes a theoretical bug: the colors of axis labels were not
updated appropriately. However, it seems like value-dependent
labels weren't used anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Alignment and scale of DiveTextItems are never changed. Therefore,
pass them at construction time. This makes things much easier
if we want to cache the rendered text [currently the text is
rerendered at every paint() event].
This also removes the "parent=0" default parameter of the
constructor, because inadvertently leaving out the last argument
led to a subtle bug.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To layout the profile we need to determine the height
of texts. Add versions for a DiveTextItem and a static
function, which is passed the scale and dpr. The latter
is used to setup items, where we do not necessarily
have a text at creation time (e.g. the tankbar).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To properly layout the profile we need to know the expected space
required by the vertical axes. In the general case, format the
the text "999". For the partial-pressure-axis, use "0.99".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The printFontScale is used to scale up fonts (and icons) when
rendering to high-DPI devices. With absolute scaling, this
will also be used to scale the size of different chart
regions, line thickness, etc. Therefore, give it an more
appropriate name. "Device pixel ratio", which is a well
established term, seems to appropriately describe the
concept.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since there (currently) is no interactive widget on mobile, there
is no point in compiling it. This was a bit more complicated than
expected, since there were other source files (divehandler.cpp
and ruleritem.cpp) which reference ProfileWidget2 and therefore
need to be removed. Otherwise, the dreadful MOC produces unresolved
references.
We could now remove all the conditional compiles in
profilewidget2.cpp, but let's keep them for now. We might have
to readd a number of them later, when making the mobile-profile
interactive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The print mode is passed on construction, not retroactively.
This function thus became unused.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of using the interactive ProfileWidget2, just
use the ProfileScene to render the profile for printing,
export and mobile. One layer (QWidget) less.
This removes all the kludges for handling DPR on mobile.
Thus, the rendering will now be off and have to be fixed
by redoing the scaling code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Setting the profile and grayscale mode of the profile via
functions is from a time when the same profile widget was
used for printing and the UI. It is simpler to set the mode
when constructing the object and not deal with changes.
To prepare for this scenario, take the flag at construction
time. This still keeps the callers as-is. These will be
adapted later.
Logically, then the printFlag also has to be set in
DiveCartesianAxis at construction time.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The cartesian axes use animSpeed to animate changes. Instead
of passing down the value to the respective functions, the
speed was stored in the ProfileScene and the axes would
access it there. Very messy. Let's just pass down the speed.
There still are back-references from the axes to the scene,
notably to place labels "outside" of the scene. Let's try
to remove them later.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This finalizes the split between interactive (ProfileWidget2)
and non-interactive (ProfileScene) parts of the profile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since the ProfileScene does the actual rendering, it needs
access to the "printMode", "isGrayScale" and "fontPrintScale"
variables. Move them down from ProfileView to ProfileScene.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The mode of the profile (profile, edit, plan) was set in
MainWindow and ProfileWidget. For consistency move the one
setProfileState() call from MainWindow to ProfileWidget.
This removes a direct access to the profile-view and
therefore improves encapsulation.
Also, clear the profile, when no dive is shown to remove
any potentially dangling references.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was moved to the desktop version. Enter the profile in
the constructor. Somewhat surprisingly, this seems to work.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The profile has an "empty state" showing the subsurface logo,
which is active when no dive is selected.
Switching to/from this mode is quite complex, because all the
chart features have to be hidden/shown, etc. Moreover, this mode
is not needed on mobile, where multiple ProfileWidgets can
be active at the same time and every dive has at least a
"faked" profile.
Therefore, implement this mode directly in the desktop
version of the widget. This makes the rescaling distinctly
less cumbersome. It is implemented using a QStackedWidget,
which switches between the profile and the logo.
This commit does not remove the empty state from the profile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since using separate profile-instances for print/export,
we never exit print mode. Therefore, the mode parameter
can be removed. This is a preparatory commit for passing
the printMode at construction time.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>