This does the right thing even when removing a nickname by setting it to
an empty string. The oddly named DiveListNotifier handles the need to
redraw the profile when the name changes.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is just a quick first implementation - it will need to use the undo
code in the future, but for now this is a reasonable first step.
It's also missing the code to redraw the profile with the updated DC
name.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This adds the menu item to rename a dive computer (ie create a nickname
for it) when right-clicking on the dive computer name of a dive computer
that has a serial number (indicated by having a non-zero ->deviceid).
It is nonfunctional because it's really just the skeleton code: it needs
the UI to actually ask for a new nickname, and then it needs to actually
do the proper "create_device_node(model,serial,nickname)" to set it (or
remove the nickname if empty).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
If the last displayed dive had events, those DiveEventItems had slots connected
that would update those icons if things changed. When closing the dive log and
switching to a different one, those slots were still called and would then access
freed memory (the event structure from that old dive that is long gone by then).
This code explicitly deletes those DiveEventItems which also removes those signal
slot connections.
Fixes#3305
Sugested-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The DiveCalculatedCeiling had a back-pointer to the profileWidget.
This was used for weird control-flow shenanigans, which were
removed in 975c123a30.
Remove this now useless member variable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The shouldCalcluateMaxTime and shouldCalculateMaxDepth member
variables of ProfileWidget2 are set to false during drag-mode to
avoid strange shrinking of the graph. They always adopt the
same value. Therefore, replace by a single shouldCalculateMax
boolean.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
It appears that this well intended change in commit 52aa7d83b6 ("Increase event
icon size in print mode") actually causes the scaling of the event icons to be
generally wrong. This removes the hard 4* scaling and also adds some debugging
output in verbose mode.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When printing with low DPI, the dive event items become comically
large, because they are not resized like the fonts. Therefore,
scale using the fontPrintScale.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This occurs upon importing dives for example via CSV.
Make sure the profile display is cleared when selecting
such a dive rather than showing a different dive.
Allow editing the profile for such a dive.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
The ADD state is not used for adding dives since adding dives
was made undoable. Therefore, rename it to EDIT state, since
that is what it is used for.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The axes of the profile are setup when switching into
the "ProfileState" and also when the preferences are
changed. The same code existed twice for both cases.
Let's factor it out into a single function to avoid
future divergence and confusion.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveEventItem had an internal copy of the event. It passed
that copy to the undo-machinery, which of course didn't work.
Simply keep a pointer to the event. All changes to a dive no
pass via the undo-machinery, which causes a reload of the profile,
so this should be safe.
Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Firstly, there is no point in supporting DiveEventItems without
model and axis. Secondly, this avoid pointless position-
recalculations.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is no point in having a dive event without an event.
Let's pass the event at construction time to avoid having
to handle "invalid" events.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The color was misnamed, since it has only been used for the
duration line for quite some time (since 893bea700c to be
exact).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When creating the context menu, a special menu is created for
the dive computer name.
This was checked in a loop, that set a flag and exited early.
This can all be simplified by moving the loop into its own
function. No more flag, less indentation. Overall better.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When creating the context menu on the profile, the code has
to check whether the context menu is activated on the
dive computer name to show a special menu (delete / split
dive computer).
This was done by setting a special property on the item
and then checking for that property on the item that
the menu is invoked on or its parents.
The reason the code didn't simply check the pointer was
probably that DiveTextItem uses multiple inheritance:
It derives from QObject and QGraphicsItem. It has to derive
from QObject first, because (the ridiculously broken) MOC
needs it that way. The object added to the scene is a
QGraphicsItem. Thus, we get a pointer _into_ the DiveTextItem
object.
However, that's all completely unnecessary. We can simply
compare the pointers, as the compiler will understand that
QGraphicsItem is only the second base class of DiveTextItem.
Magic!
Let's remove the cruft and simply compare the pointers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These became unnecessary along the way. "qthelper.hpp" was
included twice and <QtWidget> was to broad and was replaced
by <QMimeData>.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When printing, the animation speed was set to 0 by the
caller and later reset to the original value. Instead of
modifying global state, set it internally (in the profile-code)
to zero when in print mode.
This is another small step in making the printing independent
from the shown profile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When showing the "empty-state", the profile toolbar was
disabled. This was done via a "reverse" signal from the
profile to the MainWindow. Instead control the toolbar
in the MainWindow directly. Break out the plot-dive
functionality into a member function and there test
whether a dive is shown or not.
The signal makes no sense in the context of mobile
or printing.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When switching to the "plan" or "add" (which should rather be
called "edit", by the way) mode of the profile, the "shortcuts"
for copy&paste, undo&redo, etc. are disabled. When switching
to "profile" mode, they are reenabled.
This was done in a most convoluted way:
- The MainWindow calls the set*State() function of the profile.
- The Profile emits [disable|enable]Shortcuts() signals.
- The MainWindow catches these signals and does the enabling
or disabling.
Not only is this very hard to reason about, it is also in
contradiction to the profile being part of the display layer.
Moreover, in editCurrentDive() the MainWindow disabled the
shortcuts itself, so this was all redundant.
For the sake of sanity, let's just move this logic to the
MainWindow, unslotify the [disable|enable]Shortcuts() functions
and make them private.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
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>
The dive handlers are only updated by signals. This means that
switching into edit-mode has to be done in steps:
1) initialize the DivePointsPlannerModel
2) switch profile mode
3) load dive into DivePointsPlannerModel
2) and 3) cannot be exchanged, or the dive handlers are not
initialized.
To avoid this sandwitching of profile- and model-initialization,
populate the dive handlers when switching the profile mode.
Thus, the profile can be switched into edit/plan mode when
the DivePointsPlannerModel is fully initialized.
This will be important in upcoming commits, when the initialization
of the dive is moved from the profile to the DivePointsPlannerModel.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
When moving "dive handlers" with the cursor keys, the
profile was replot twice:
- First the recalculation of the planner model was suspended.
- The "stop" was moved.
- This led to a replot by a signal from the planner model.
However, the old profile was shown, since the recalculation
was suspended.
- The recalculation was reenabled.
- The profile war replot, resulting now in the correct profile.
A classical case of bit rot.
Instead, don't suspend calculation in the first place. This
shows the correct profile on the first replot and the second
replot can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The ItemPos structure describes the position of various chart
elements on the scene. It had two problems:
- The identifiers were starting with an underscore followed
by a capital letter. This is reserved to the compiler.
- The global object was initialized in the ProfileWidget's
constructor. This means that if there are multiple
ProfileWidgets, the structure is reinitialized even though
it is constant.
Remove the underscores (what was the point anyway?) and
initialize the structure in its own constructor. Moreover,
make the object const to drive the point home.
If this ever needs to be variable, each ProfileWidget
should get its own copy of the object.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
When moving a planner point with the cursor, nothing
is wrong with extending the dive time by stepping
beyond the current maximum. Same for depth.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The code took care to not delete planner-points when no
points are selected. However, it assumed that all selected
objects are planner-points. But then it checked whether
the selected object actually is a planner-point. So which
is it?
Remove the outter check for an empty selection. This makes
things more logical and more robust, should there ever
be other objects that can be selected.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
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>
When moving the handle with the mouse, the old code tried
to be smart about changing the active handle when crossing
handles.
To me this always felt weird and it was inconsistent with
mouse-move. Theregore, simply do nothing special at all. The
user should hopefully get an intiutive grasp of what's going
on when moving one handler across another.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This model is only needed when in plan mode. To enable multiple
profilewidgets at the same time (e.g. for the mobile app or
for printing), make the pointer to DivePlannerPointsModel a
member variable that is initialized at construction time.
Moreover, allow passing null as the DivePlannerPointsModel,
in which case planning will be disabled. This will be useful
for simple printing.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The connection to the DivePointsPlannerModel was done in two
distinct functions: setAddState() and setPlanState(), which
means that these could easily get out-of-sync. Factor this out
into a single function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
The ProfileWidget2 slots, which reacted to model changes were
broken. They did not add / remove items at the changed positions,
but arbitrarily at the end. Moreover, they assumed that only
a single item was added / removed and thus violated the model/view
API.
This worked because the handles are completely reset after each
operation and the model only ever touched single items.
Nevertheless, this has to be fixed if we ever want finer grained
undo.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of manually deleting them (and the gases). Currently
there is only one point where these are deleted, but if
we implement proper Qt model/view semantics, this makes things
less headachy.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To remove reliance on global state, pass an "in_planner" argument
to AbstractProfilePolygonItem::replot(). Thus, calls to in_planner()
can be removed.
This is a bit sad, since the in_planner argument is now passed
to numerous replot() reimplementations of classes derived
from AbstractProfilePolygonItem. However, it is only needed
for one, viz. DiveGasPressureItem. Well, perhaps in the future
more features will depend on the planner mode...
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>