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>
The profile must be replotted when the dive mode changes.
Weirdly, this was routed via the dive-information tab
(making it inherently non-mobile compatible). Detect
such a change directly in the profile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There was code to create a fake dc in the profile widget in
the case that there are no samples. To my understanding, this
is obsolete, as such fake data is now generated automatically
when adding dives.
If for some reason there really are no samples, quit early
and go into the empty state.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Adds fields to the advanced preferences page to modify GFLow and GFHigh for
the Buhlmann decompression model for calculating ceilings. Updated preferences
code to set the Buhlmann parameters in core/deco.c when the GF prefs are
updated.
Signed-off-by: Doug Junkins <douglas.junkins@gmail.com>
This now actually displays the calculated ceiling in the profile. There is
still an issue where if the user toggles the setting the already cached profiles
aren't recalculated - that's part of a bigger profile cleanup effort.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The profile had a static variable which prevented animation
when first showing the profile. It appears more logical to
don't show the animation when switching from the empty state.
This removes global state, as a function static variable
exists only once, even if there are multiple objects.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
Instead of accessing the global displayed_dive variable
in RulerItem, pass the dive. This is a step in making the
profile reentrant.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of accessing the global displayed_dive variable,
pass the dive to the various profile items. This is a
step in making the profile code reentrant.
This removes the last user of the displayed_dc macro,
which can now be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Don't access the global displayed_dive variable in an effort
to make the profile reentrant.
Note that this still accesses the global dc_number variable,
which will likely have to be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The in_planner() function is incompatible with a reentrant
profile, since it accesses a global variable. In
create_plot_info_new() it is essentially redundant, because
there is a planner_ds (ds = deco_state) parameter that
is used only when in the planner. Therefore use that as
the in_planner indicator: when non-null, the profile is
showing a planned dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The code tried to only replot the profile if necessary, notably
when in edit mode or the ceilings are shown.
That seems like pointless premature optimization, which only
complicates things: The profile is replot every time a
"dive handle" is moved, which means that we depend on the
replotting being reasonably fast. Why should it then not
be redrawn if the settings change?
Let's remove this, as it makes control flow easier to reason
about.
This makes the isPlotZoomed member variable redundant. Remove it.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
On each profile replot, the gas axis was implicitly reset
by calling "dataModel->emitDataChanged()", which would send
a signal recieved by the axis. To make the code less confusing
and, more importantly, make order of execution deterministic,
explicitly reset the axis.
Rename the function that resets the axis from "settingsChanged"
to "update" to reflect its usage.
Moreover, remove the "setModel()" function and pass the model
to the constructore. Make it a const reference to make clear
that it can't change during the life time of the axis.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In contrast to most other items, which are cleared in the
setEmptyState() function, the profile items are cleared
indirectly via a signal from the model. Very hard to follow
and indeed, I thought I could just remove the slot.
Do this explicitly instead for deterministic code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is no point in a separate set-axis function if we never
change the axis anyway. Make the axis a const-reference to
show that it can never be changed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This one is extremely obscure: TankItem::setData(), which is
called on every replot, was passed the DivePlotDataModel,
even though it doesn't access that model at all.
Instead, it connect()s to the model to stay informed of changes
to the data. First of all, this should obviously be done
once in the constructor, not on every replot.
But also, the setData() function is called on every replot
one lines before sending the model-changed signal.
Thus, the tankitem was always repainted twice.
Just remove the whole connect() thing and go for a more
deterministic model. Should the tankbar not be repainted
anywhere, add the appropriate calls there.
Accordingly rename the "modelDataChanged" slot to "replot".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
settingsChanged() is a virtual function, which is called
when the preferences dialog signals changes. In most derived
classes, the function does nothing.
In two classes, DiveProfileItem and DiveCalculatedTissue, it
replots the item respectively changes its visibility.
However, these two flags are *not* controlled by the preferences
dialog. Indeed, the functions are also connected to finer-grained
qPref signals. Therefore, settingsChanged() can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Collect all the created profile items in a dynamic vector.
This allows us to loop over them when adding them to the
scene, instead of addressing each item individually.
Hopefully, this will also allow for a more deterministic
repaint logic, without relying on signals.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The only thing left that this function did, was setting the Z-value
of the item. This can be done directly on construction.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function was called after creating the items. It can be
called directly to create the items. Less chance of mixups.
For this to work, the initialization of isGrayscale has to
be moved to the front, because createPPGas sets the color
according to this flag.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of typing out the same arguments again and again,
do the allocation of DiveProfileItems in a templated function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The profile items had a "setModel()" function to set
the DivePlotDataModel post creation. The model is never
changed. It does however mean that the model might be
null in a short period between construction and setting
the model.
To simplify reasoning about this code, set the model
in the constructor. To drive the point home that the
can never change and cannot be null, turn it into a
reference.
Yes, this is gratuitous bike-shedding, but it helps
me analysis the code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Recently (674c20227b), the call to ProfileWidget::clearHandlers()
was moved from PlannerWidgets::replanDive() to ProfileWidget2.
This cause a crash, because the code assumes that the number
of elements in the handles-vector the divepointplanner model
is the same.
Clearing the handles violates this assumption. It turns out
that the clearHandlers() function is broken anyway: it clear
the handles-vector, but not the gases-vector, which should
likewise have the same number of elements. It appears that
the clearHandlers() function is an artifact and it is
mysterious how this has worked so far. Remove.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On clicking the DivePictureItem "trash" icon, the item would delete
the picture it represents in the currently displayed dive. This needed
an access to the global "displayed_dive" variable, which we want
to get rid of to make the profile more flexible. For example, we
want to render the profile for printing without messing with global
state.
One solution would be to save the dive with every DivePictureItem.
This commit follows a more Qt-ish strategy by handling this via
signals: The close button emits a signal that is recast by the
DivePictureItem and ultimately handled by the ProfileWidget2,
which knows which dive it represents.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The mainwindow was connecting preferences changes to the profile.
Do this directly in the profile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These are the small dots that describe dragable points on
the profile when in the planner. It makes no sense to have
them in desktop's planner-widget code. They belong to the
profile.
Therefore, move the code there and compile on mobile.
Not everything can be compiled on mobile for now, but it
is a start.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function, which removes the handlers from the profile, was called
in setAddState() but not in setPlanState(). In the latter case it was
called explicitly by the caller.
Move the call from the caller into the function. This allows us to
make clearHandlers() private in to the profile widget.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
Instead of using the two different ways Qt supports swap, depending on the Qt
version in use, let's simply use std::swap()
Suggested-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This has been deprecated for years.
The delta() member dealt with the old style mouse wheel that is associated with
a vertical scroll - so we need the y-component.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In an effort to reduce the size of dive.h and dive.c, break out
the event related functions. Moreover event-names were handled
by the profile-code, collect that also in the new source files.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
There is a number_of_computers() function which does
the same thing with two exceptions:
1) checks for null-dive
2) returns an unsigned int
Replace calls to count_divecomputers() by calls to number_of_computers().
In one case, the return type makes a different - add a cast to int there.
Ultimately, we should probably change the dc_number to signed int
throughout the code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When plotting the profile in higher resolution for export,
increase the icon size in the same way.
This is commented out for the mobile version as that
uses printMode for profile display.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This new option allows a user to select a new destination tank for an
existing "Gas Change" event. This is useful when Subsurface's heuristics
get tanks wrong after an import from a divecomputer. The use-case arose
from sidemount divers with air-integrated transmitters as well as carrying
a deco tank.
Signed-off-by: Michael Werle <micha@michaelwerle.com>
Since the profile does not listen to DivePictureModel resets anymore,
the pictures weren't cleared when clearing the canvas. Do this
explicitly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
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>
ProfileWidget2::plotDive() had this weird interface, where passing
in NULL as dive would mean "show current_dive". However, most callers
would already pass in current_dive. Therefore, unify and always pass
in current_dive if the caller wants to draw the current dive.
This allows us to interpret NULL as "show empty profile". Thus,
passing in current_dive when there is no current_dive simply shows
an empty profile. This makes the calling code in
MainWindow::selectionChanged() simpler.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Firstly, the parameter appears conceptually wrong, as replot suggests
that the currently shown dive is replot. Secondly, the only caller that
passed a parameter was passing in current_dive, which is just what happens
if one doesn't pass a parameter. Therefore, change that caller (call
plotDive directly) and remove the parameter.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When populating the events of a profile, a pointer to the current
gasmix was passed around to properly calculate isobaric_counterdiffusion.
The DiveEventItem::setupToolTipString() function updated this gasmix
when processing gas change events.
I inadvertently broke the code when replacing gasmix-pointers by
values. We could of course simply revert this part of the commit.
However, the data flow was horrible anyway: for example is supposed
that the setup functions were called in the correct order (i.e.
DiveEventItem::setupToolTipString() is called after all other
functions using the gasmix). Not exactly easy to follow.
Therefore, keep passing around the gasmix as value to make it clear
that the functions don't modify it. Keep the gasmix up-to-date at
the caller's site in ProfileWidget2::plotDive().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The profile data was not properly cleared when not showing a
dive.
Fixes#2787
Reported-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is a bit hairy as - in theory - one gas switch can remove
other gas switch(es) at the same timestamp. However, I did not
find a way to test it. Moreover, it is not clear whether the
dive-tabs are properly updated on undo/redo.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was a trivial copy & past of the event-adding undo command
with a switch of the undo() and redo() actions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is a slight complexity here owing to the fact that the profile
works on a copy of the current dive: We get a copy of the event and
have to search for the original event in the current dive. This
could be done in the undo command. Nevertheless, here we do it in
the profile so that when in the future the profile can work on a
non-copied dive we can simply remove this function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since pointers to divecomputers may not be stable, the undo
commands take a dive + a divecomputer number. Update the
SetpointDialog accordingly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We have too many global objects. There is no reason why this dialog
should be a persistent global object.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This basically copies the bookmark code, with the addition that
the dive mode is recorded in the text of the undo command.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a DiveListNotifer::eventsChanged signal, which is emitted when
the events changed. This is very coarse, at it doesn't differentiate
between signal addition / editing / deletion. We might want to
be finer in the future.
Catch the signal in the profile-widget to replot the dive if this
is the currently displayed dive. Reuse the cylindersChanged() slot,
but rename it to the now more appropriate profileChanged().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Create a new translation unit for event-related undo commands.
Create a base class of commands that add events and one subclass
that adds a bookmark event.
Use this command in the profile-widget.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since we removed the setData() calls of the QActions in
ProfileWidget2::contextMenuEvent(), we don't have to manually
generate the QActions. We can simply use the convenience
overload of addAction() that takes a string and a functional.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The removeEvent(), hideEvents() and editName() actions need
the DiveEventItem they are applied to. This was transported
via QAction's user-data, which means casting to void and
back.
By using lambdas instead, this can be made perfectly type-safe:
First we are 100% sure that we have a DiveEventItem because
we check the result of a dynamic_cast<>. Then we can pass
it to the even using its proper type.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is not such a big gain as for addDivemodeSwitch(), but still
simpler. Therefore, let's do it for consistency.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The unhideEvents context menu action was fed with the click-position.
However, that was not used. Therefore, remove it.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The data was transported via the action in a most complicated way:
The text was backtranslated. Simply use a lambda - perhaps hard to
read, but much simpler to follow and less brittle.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In two cases we were passing the magic value 8 instead of the
symbolic SAMPLE_EVENT_BOOKMARK. Use the symbolic version instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the profile, catch cylinder-editing signals and redraw the
profile if the currently displayed dive has changed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Grammar-nazi ran
git grep -l 'indexes' | xargs sed -i '' -e 's/indexes/indices/g'
to prevent future wincing when reading the source code.
Unfortunatly, Qt itself is infected as in
QModelIndexList QItemSelection::indexes() const
Signed-off-by: Robert C. Helling <helling@atdotde.de>
The gas change context menu was filled from the CylindersModel.
This means that even before saving new cylinders, the user could
add a gas change event to these cylinders.
Instead, fill from the current dive.
Fixes#2552.
Reported-by: Doug Junkins <junkins@foghead.com>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When adding a gas change event via a context menu, the gas-id and
timestamp were passed in two distinct ways.
1) The gas id was extracted from the text of the action. This meant
doing rather complicated parsing.
2) The timestamp was passed via the "user data" of the action, which
means transporting via "QVariant".
There is a much simpler way to pass arbitrary data, that is strongly
typed: lambdas. Instead of shoehorning the data onto the action in
an archaic way, we can simply connect to a stateful lambda. That's
what they're for after all.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The tooltip's plotInfo was not cleared when clearing the profile.
With the new cylinder code, this lead to crashes, because the
displayed_dive's cylinder array is now cleared. The old code would
happily read stale data from the fixed-size cylinders array.
Clear the plotInfo explicitly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the future we might want to use undo-commands for mobile as
well (even if not implementing undo).
Therefore, move the undo-command source from desktop-widgets
to their own commands top-level folder.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of accessing the cylinder table directly, use the get_cylinder()
function. This gives less unwieldy expressions. But more importantly,
the function does bound checking. This is crucial for now as the code
hasn't be properly audited since the change to arbitrarily sized
cylinder tables. Accesses of invalid cylinder indexes may lead to
silent data-corruption that is sometimes not even noticed by
valgrind. Returning NULL instead of an invalid pointer will make
debugging much easier.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of using fixed size arrays, use a new cylinder_table structure.
The code copies the weightsystem code, but is significantly more complex
because cylinders are such an integral part of the core.
Two functions to access the cylinders were added:
get_cylinder() and get_or_create_cylinder()
The former does a simple array access and supposes that the cylinder
exists. The latter is used by the parser(s) and if a cylinder with
the given id does not exist, cylinders up to that id are generated.
One point will make C programmers cringe: the cylinder structure is
passed by value. This is due to the way the table-macros work. A
refactoring of the table macros is planned. It has to be noted that
the size of a cylinder_t is 64 bytes, i.e. 8 long words on a 64-bit
architecture, so passing on the stack is probably not even significantly
slower than passing as reference.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Some widgets copy the full plot info. Free these data on exit to
prevent monstrous valgrind reports.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Continue with replacing pointers to struct plot_data entries
by indexes. Thus the pressure data can be kept in its own
array and can by dynamically sized.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The ProfileWidget2::getEntryFromPos() function was only used
by code that was commented out. Thus comment it out as well.
Moreover, turn the accompanying FIXME comments into TODO comments
to avoid a new LGTML alert.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The ProfileWidget2::recalcCeiling() function is used in one place,
namely when an undo-command changes the mode. It recalculates
decompression data and repaints the ceilings and thus avoids a
full profile-redraw.
This is smart, but it becomes problematic when the dive is changed
and the ceiling is recalculated before the profile is redrawn.
The DivePlotDataModel then still has data from the previous dive
but cylinders of the new dive are accessed.
This kind of situation may arise if multiple dive fields are
updated, as for example when replanning a dive.
Currently, this only causes a temporary mis-calculation. When
removing MAX_CYLINDERS this will lead to crashes.
One might attempt to fix the whole data-dependency mess. This
commit goes the cheap route and simply redraws the profile when
the mode is changed. Yes, it is in a way ineffective, but we
do worse things. The ProfileWidget2::recalcCeiling() thus becomes
unused and is removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
I'm a bit confused why this enum has two extra values, NUM_DIVEMODE and
UNDEF_COMP_TYPE. I can see how this could create confusion. This may
benefit from addition review.
Found by Coverity. Fixes CID 350092.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Since requiring Qt >= 5.9.1, we can use the pointer-to-member-function
overloads of addAction (introduced in Qt 5.6). This has the advantage
of compile-time checking of the signal/slot parameters.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The create_plot_info_new() function releases old plot data. This
can only work if the plot_info structure was initialized previously.
The ProfileWidget2 did that by a memset, but other parts of the code
did not.
Therefore, introduce a init_plot_info() function and call that when
generating a plot_info struct. Constructors would make this so much
easier - but since this is called from C, we can't use them.
Fixes#2251
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Move the declarations of the "report_error()" and "set_error_cb()"
functions and the "verbose" variable to errorhelper.h.
Thus, error-reporting translation units don't have to import the
big dive.h header file.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace the INTERPOLATED_PRESSURE and SENSOR_PRESSURE macros by
inline functions. Generate a common inline function that reads
a pressure value for a dynamic sensor.
Not all SENSOR_PRESSURE macros can be replaced, because the
macro is also used to set the value and C sadly doesn't know
the concept of "return reference from a function".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The plotDive() function had a flag to plot pictures asynchronously.
This was used on export. Rename this field to "instant" and disable
animations when set. This should make sure that the axes are properly
exported.
Fixes#2170
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When exporting dive pictures we don't want animations. Therefore,
store the animation speed in the profile object to avoid nasty
hacks with the preferences.
This actually removes such a hack. Pictures and tooltips for now
still use the values stored in the preferences, because their
animations happen only on user-interactions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The goal here is to slowly make animation speed a variable of the
profile widget, not of the global preferences. Currently the code
does some trickeries with setting / unsetting the global animation
speed.
Start by not taking a bool "instant" but a speed in
DiveEventItem::recalculatePos().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
All callers of create_plot_info_new() called calculate_max_limits_new()
a line before. Thus, simply call the latter in the former.
This allows us to automatically free the plot data in create_plot_info_new().
The old code overwrote the corresponding field with NULL.
As a side-effect, this removes a bogus static variable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There was a global variable last_pi_entry_new, which stored the
recently allocated plot data. This was freed when new plot data
was generated.
A very scary proposition: You can never have two plot datas at
the same time! But exactly that happens when you export for
example subtitles.
The only reason why this didn't lead to very crazy behavior
is that at least on my Linux machine, the calloc() call would
just return the previously freed memory.
Fix this mess by removing the global variable and freeing the
data in the callers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In ProfileWidget2::splitDive() updateDiveInfo was emitted, but the
UndoCommand does this by itself.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, count_divecomputers only works on the current_dive.
Instead, let it take a pointer to an arbitrary dive. This is
in preparation for being smarter in the undo code concerning
which dive computer to show on deletion.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of the elegant solution that just modifies the dive,
keep two copies and add either the old or the new copy. This
is primitive, but it trivially keeps the dives in the right order.
The order might change on renumbering the dive computers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The whole edit logic moved from displayed_dive to current_dive
and it became more and more tedious to keep these in sync.
Therefore, simply always display current_dive. The only exceptions
are the equipment tab and the planner, as these are not yet
integrated in the undo system. Once this is done, displayed_dive
can be removed.
Moreover, remove the clear parameter from updateDiveInfo().
Instead simply clear of there is no current_dive set.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
See https://www.kdab.com/goodbye-q_foreach/
This is reduced to the places where the container is const or can be made const
without the need to always introduce an extra variable. Sadly qAsConst (Qt 5.7)
and std::as_const (C++17) are not available in all supported setups.
Also do some minor cleanups along the way.
Signed-off-by: Rolf Eike Beer <eike@sf-mail.de>
Allow splitting out a dive computer into a distinct dive. This
is realized by generating a base class from SplitDive.
This turned out to be more cumbersome than expected: we don't
know a-priori which of the split dives will come first. Since
the undo-command saves the indices where the dives will be insert,
these have to be calculated. This is an premature optimization,
which makes more pain than necessary. Let's remove it and
simply determine the insertion index when executing the command.
Original code by Linus Torvalds <torvalds@linux-foundation.org>.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Instead of passing a pointer, pass a cons reference. This is more
idiomatic and consistent with RulerNodeItem2::setPlotInfo().
Also make the reference passed to RulerNodeItem2::setPlotInfo()
const, to make clear that the argument is copied.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The pictures of the current dive were plotted on the profile.
In principle OK, as this is what the user is shown. Only on
export this results in all profiles having the same pictures.
Therefore, pass a dive argument to the picture-plotting function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The thumbnails were fetched in the background to achieve a
snappier UI. The problem with that is that on LaTeX etc.
export only placeholder thumbnails were shown.
Therefore, implement a synchronous mode. This only tries
to fetch cached thumbnails or calculate thumbnails for
images. Videos and remote files are not supported.
Fixes#1963
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
With Facebook support gone, we should offer a way to export
the profile image. This has been part of the TeX support
but this makes it explicit.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Update the dive info box when toggling the chosen DC using the
keyboard. The keyboard toggle does not generate a mouse move
event, so this data was not repainted. For this, a
sub-optimization of not repainting when not moving the mouse
had to be removed. This does not impact ant performance
as 99.9999% of the calls of the repaint are caused by mouse
movement anyway.
Fixes: #1802
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Select the proper dives after the add, remove, split and merge
dives commands on undo *and* redo. Generally, select the added
dives. For undo of add, remember the pre-addition selection.
For redo of remove, select the closest dive to the first removed
dive.
The biggest part of the commit is the signal-interface between
the dive commands and the dive-list model and dive-list view.
This is done in two steps:
1) To the DiveTripModel in batches of trips. The dive trip model
transforms the dives into indices.
2) To the DiveListView. The DiveListView has to translate the
DiveTripModel indexes to actual indexes via its QSortFilterProxy-
model.
For code-reuse, derive all divelist-changing commands from a new base-class,
which has a flag that describes whether the divelist changed. The helper
functions which add and remove dives are made members of the base class and
set the flag is a selected dive is added or removed.
To properly detect when the current dive was deleted it
became necessary to turn the current dive from an index
to a pointer, because indices are not stable.
Unfortunately, in some cases an index was expected and these
places now have to transform the dive into an index. These
should be converted in due course.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This refactors the undo-commands (which are now only "commands").
- Move everything in namespace Command. This allows shortening of
names without polluting the global namespace. Moreover, the prefix
Command:: will immediately signal that the undo-machinery is
invoked. This is more terse than UndoCommands::instance()->...
- Remove the Undo in front of the class-names. Creating an "UndoX"
object to do "X" is paradoxical.
- Create a base class for all commands that defines the Qt-translation
functions. Thus all translations end up in the "Command" context.
- Add a workToBeDone() function, which signals whether this should be
added to the UndoStack. Thus the caller doesn't have to check itself
whether this any work will be done. Note: Qt5.9 introduces "setObsolete"
which does the same.
- Split into public and internal header files. In the public header
file only export the function calls, thus hiding all implementation
details from the caller.
- Split in different translation units: One for the stubs, one for
the base classes and one for groups of commands. Currently, there
is only one class of commands: divelist-commands.
- Move the undoStack from the MainWindow class into commands_base.cpp.
If we want to implement MDI, this can easily be moved into an
appropriate Document class.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For this, the core functionality of the split_dive() and
split_dive_at_time() functions were split out into new
split_dive_dont_insert() and split_dive_at_time_dont_insert(),
which do not add the new dives to the log. Thus, the undo-command
can take ownership of these dives, without having to remove them
first.
The split-dive functionality is temporarily made desktop-only
until mobile also supports "UndoObjects".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In commit bd0c99dfb7 (display pO2 and Setpoint for CCR dives)
the choice was made: when CCR than never a temperature graph.
While this seems reasonable, there is small group of mCCR
divers that do not log their po2 digitally, so the only po2
they can display is the setpoint that is reported by the used
DC. As this is a bit of a dull flat line, most of these
divers do not display this. And this leaves room on the
small mobile display for the temperature data.
So effectively: show temperature or po2 graphs.
Suggested-by: Peter Zaal <pzaal@xs4all.nl>
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
These were pointers into the global prefs object. The user must
not use these to modify the settings, therefore make them
pointers-to-const.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add class variable tooltip_position to qPrefDisplay
Add class variable lastDir to qPrefDisplay
qPrefDisplay is updated to use new qPrefPrivate functions
Adjust test cases incl. qml tests
qPrefAnimations only has 1 variable, that really is a display variable
Merge the variable into qPrefDisplay, to simplify setup (and avoid loading
extra page in qml).
correct theme to save in correct place, and make it a static
class variable
Signed-off-by: Jan Iversen <jani@apache.org>
This is another entry in the series to make more things
"const-clean" with the ultimate goal of merge_dive() take
const pointers.
This concerns functions taking pointers to events and
the fallout from making these const.
The somewhat debatable part of this commit might be
that get_next_event() is split in a two distinct
(const and non-const) versions with different names,
since C doesn't allow overloading. The linker should
recognize that these functions are identical and remove
one of them.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In a previous commit, the get_gasmix_* functions were changed to
return by value. For consistency, also pass gasmix by value.
Note that on common 64-bit platforms struct gasmix is the size
of a pointer [2 * 32 bit vs. 64 bit] and therefore uses the
same space on the stack. On 32-bit platforms, the stack use
is probably doubled, but in return a dereference is avoided.
Supporting arbitrary gas-mixes (H2, Ar, ...) will be such an
invasive change that going back to pointers is probably the
least of our worries.
This commit is a step in const-ifying input parameters (passing
by value is the ultimate way of signaling that the input parameter
will not be changed [unless there are references to said parameter]).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There were two functions for getting gas-mixes at a certain timestamp:
- get_gasmix() for repeated queries.
- get_gas_at_time() for a single query.
Since the latter is a special case of the former, simply call
the former in the latter. Moreover, rename to get_gasmix_at_time()
for consistency.
Replace on get_gasmix() call, which was outside of a loop by the
corresponding get_gasmix_at_time() call.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, get_gasmix_from_event() and get_gasmix() return pointers
to either static or to (possibly changing) dive data. This seems like
a dangerous practice and the returned data should be used immediately.
Instead, return the gasmix by value. This is in preparation of
const-ifying input parameters of a number of core functions, which
will ultimately let the merge() function take const-arguments in
preparation of undo of dive-merging.
On common 64-bit systems gasmix (two "int"s) is the size of a pointer
and can be returned in a register.
On 32-bit systems a pointer to the struct to be filled out will be
passed.
Since get_gasmix() now returns a value, the first invocation is
tested by a NULL-initialized "struct event *". Document this in
a comment.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
remove use of SettingsObjectWrapper::
remove include of SettingsObjectWrapper.h
use qPrefFoo:: for setters and getters
replace prefs.foo with qPrefXYZ::foo() where feasible
(this expands to the same code, but gives us more control
over the variable).
Signed-off-by: Jan Iversen <jani@apache.org>
remove PartialPressureGas from SettingsObjectWrapper and reference qPrefPartialPressureGas
update files using SettingsObjectWrapper/PartialPressureGas to use qPrefPartialPressureGas
this activated qPrefPartialPressureGas and removed the similar class from
SettingsObjectWrapper.
Signed-off-by: Jan Iversen <jani@apache.org>
remove TechnicalDetails from SettingsObjectWrapper and reference qPrefTechnicalDetails
update files using SettingsObjectWrapper/TechnicalDetails to use qPrefTechnicalDetails
this activated qPrefTechnicalDetails and removed the similar class from
SettingsObjectWrapper.
Signed-off-by: Jan Iversen <jani@apache.org>
SUBSURFACE_MOBILE does not include the single function that uses the variable
add #ifndef SUBSURFACE_MOBILE to avoid warning
Signed-off-by: Jan Iversen <jani@apache.org>
Paint a rectangle on top of thumbnails indicating the run-time
of the video.
Use the z=100.0-101.0 range for painting the thumbnails, whereby
the z-value increases uniformly from first to last thumbnail
(sorted by timestamp). The duration-bars are placed at z-values
midway between those of the thumbnails.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
9efb56e2d4 introduced rather complex
logic for picture drag'n'drop events onto the profile. Among other
things, the code had to check whether the picture actually belongs
to the displayed dive.
This can be simplified by transporting the dive-id in the drag'n'drop
event structure. The flow goes like this:
DivePictureModel--(1)-->DivePictureWidget--(2)-->ProfileWidget
For (1), we can use the Qt::UserRole role. This was used to transport
the picture-offset, but this is not needed anymore since ProfileWidget
was decoupled from DivePictureModel.
For (2), we simply replace the "position" value, which was never used.
Why would the receiver care which pixel was pressed in the media-tab?
This commit also contains a minor cleanup in DivePictureWidget:
QListView::mousePressEvent(event) was called in both branches of an
if and can therefore be removed from the if. This is so trivial,
that it doesn't warrant its own commit.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
9efb56e2d4 added code to rearrange
pictures on drag'n'drop. To keep the correct repainting order (i.e.
later thumbnails are painted on top of previous thumbnails), the
z-value was set accordingly. In principle a sound idea, but it did
not work out, because on hoverEnter and hoverExit events, the z-values
were modified, thus restoring the wrong drawing order.
Instead, use the QGraphicsItem::packBefore() function. Experimentation
showed that this only works if stacking is done from the back
of the list.
Silence an erroneous compiler warning by initializing a variable to 0.0.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Gracefully handle drag & drop to the profile, which changes the
offset of the pictures. To do this, keep the pictures in the
DivePictureModel and the ProfileWidget2 sorted by offset and
re-arrange if needed to keep the list sorted. This needs some
code reshuffling.
Introduce a helper-function that moves ranges in arrays.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If pictures were deleted, the remaining thumbails where staying at
their positions. Only when switching between dives, the new positions
were recalculated. Do the recalculation immediately. More precisely:
the x-coordinate, which is determined by the timestamp, stays identical.
Only the y-coordinate is recalculated such that overlapping of thumbnails
is avoided.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
As long as ProfileWidget2 and DivePictureModel showed the same set of
pictures and any change would lead to a full recalculation of the set,
it made sense to let ProfileWidget2 use DivePictureModel's data.
Recently, keeping the two lists in sync become more and more of a
burden. Therefore, disconnect ProfileWidget2 and DivePictureModel. This
will lead to some code-duplication and perhaps a temporary drop in
UI-performance, but in the end the code is distinctly simpler and also
more flexible.
Thus, for example the DivePhotoTab could be changed to support headings
without having to touch ProfileWidget2 at all.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
PP_GRAPHS_ENABLED is only used in profilewidget2.cpp
make local to profilewidget.cpp
Signed-off-by: Jan Iversen <jani@apache.org>core/profile: move PP_GRAPHS_ENABLED from pref.h
The DivePictureModel signals were connected int the setProfileState()
function of ProfileWidget2. If this function was called repeatedly
(e.g. after adding a dive), multiple connections were made, which led
to multiply delivered signals. This in turn led to confusion, when
deleting pictures (i.e. multiple pictures were deleted).
Instead, connect once in ProfileWidget2's constructor. It is unclear
whether these signals should be disconnected temporarily if no pictures
are shown. In any case, the weren't, so this shouldn't introduce any
regression.
Fixes#1441
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Correctly use gettextFromC::instance()->tr(); instead of a simple
tr(); to translate the dive mode names.
This goes on top of 0bc9edf855
and finally makes the whole thing work.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
Enable translations for dive event name "modechange".
But clearly don't do this for the string which is used internally
but only push "modechange" to the translation system to be able to
translate it in the UI.
Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
In a recent commit, the profile widget was changed to reuse
DivePictureItems. This made toggling of picture-visibility
disfunctional, because the visibility was set in the constructor.
Only on change of dive would the setting take effect.
Therefore, move the setting of the visibility up to the
ProfileWidget2::plotPictures() call. This is more consistent
anyway, since at this level pixmap and fileUrl are set.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
helpers.h included qthelper.h and all functions declared in helpers.h
were defined in qthelper.h. Therefore fold the former into the latter,
since the split seems completely arbitrary.
While doing so, change the return-type of get_dc_nichname from
"const QString" to "QString".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The former should be translated but not those that
go to xml/git.
... and fix capitalization of pSCR.
Suggested-by: Stefan Fuchs <sfuchs@gmx.de>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Reactivate printMode true for ssrf-mobile to avoid font problems,
do not discard events if ssrf-mobile (even though printMode is true)
Signed-off-by: Jan Iversen <jani@apache.org>
On deletion of a single or multiple pictures, the whole DivePictureModel
was repopulated, which was clearly visible in the UI, owing to the
reconstructing of all images in the profile plot.
To avoid this vexing behavior, implement proper deletion routines in
DivePictureModel and ProfileWidget2. Since this needs sensible erase()
semantics the QList<PictureEntry> member of DivePictureModel was
replaced by a QVector. A QVector should be the default anyway, unless
there are very specific reasons to use a QList (which actually is
a deque, not a classical linked list).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the old code a combination of removeRows()/insertRows() was used
to signal a model reset.
Replace this by a single, modelReset signal. This saves a call to
plotPictures() and will allow us to be smarter in the future,
when removing pictures.
Reset-model and remove-items are semantically different.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In MainWindow::current_dive_changed() first plotDive() is called,
which replots all the pictures by calling plotPictures(). This
is pointess, because it plots the pictures of the previous dive.
Then, updateDiveInfo() is called, which resets the dive pictures
and automatically replots them. Thus, switching between dives
both with hundreds of pictures is way slower than necessary.
Switching the plotDive() and updateDiveInfo() calls doesn't work.
The reason is not 100% clear, but it doesn't make sense to plot
pictures of the new dive as long as the profile still shows the
old dive anyway.
As a quick-fix, add a flag to plotDive(), which tells the function
to clear the pictures list instead of redrawing it.
Ultimately, plotDive() should probably be split in two functions.
One for the callers who update the pictures themselves and one
for the others.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
...as the usuage is not anymore about a computer but
a momentary dive mode. Rename the end indicator as well.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
The dive profile context menu gets rather long with three
additional divome switches that can be selected. This is now changed
so that the additional options are only shown when in CCR
or in PSCR divemode.
Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>