Mostly irrelevant std::move() stuff of copy-on-write Qt objects,
a few real bugs, a timestamp_t downconversion and some codingsyle
adaptation.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If prefs.show_icd is false, this function does nothing, but
the output parameter is checked by the calling function
DiveEventItem::setupToolTipString().
Let's reset the strucvture to 0.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When adjusting picture times, the offset in seconds is stored in a
32-bit int. Make it a 64-bit int. Sounds crazy, because why would
you want to move the pictures by more than 70 years?
Well, suppose it is the year 2039, for some strange reason your
camera was set to unix epoch and you want to adjust the pictures
to current time.
Ok - that's a far-fetched scenario. The real reason is that this
hopefully silences a Coverity warning and avoids integer casting.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Unfortunately Coverity doesn't understand that most Qt data
structures are copy-on-write. It's a mis-feature of Qt, but
it is the way it is. Thus, passing by value is not an issue.
Out of ca. 25 warnings only two were legit. Let's silence
the others by either std::move()ing or passing by reference,
as would be idiomatic C++, which Qt is not.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There are two enums related to the type of dive.
There is the global
enum divemode_t {OC, CCR, PSCR, FREEDIVE, NUM_DIVEMODE,
UNDEF_COMP_TYPE};
and the anonymous
enum {AIR, NITROX, TRIMIX, FREEDIVING} dive_type;
in struct plot_info.
In profile.c FREEDIVE (of divemode_t) is assigned to dive_type.
This only works because by chance(?) FREEDIVE and FREEDIVING are
the fourth element of each enum.
Fix this. C truly is a bad language when it comes to types
(very weak) and namespaces (non existing).
Contains whitespace fix.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This hasn't been used on the backend in a long time (and appears to get
stripped out on several platforms). No point in keeping it around.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
While the update to the copyright year really isn't required, it just looks
better.
By using the canonical instead of the git version in user visible strings we
are creating more consistency in how we refer to the version.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
- for now all versions start with v6.0
- CICD builds use the monolithic build number as patch level, e.g. v6.0.12345
- local builds use the following algorithm
- find the newest commit with a CICD build number that is included in the
working tree
- count the number of commits in the working tree since that commit
- if there are no commits since the last CICD build, the local build version
will be v6.0.12345-local
- if there are N commits since the last CICD build, it will be
v6.0.12345-N-local
- test builds in the CICD that don't create artifacts simply use a dummy release
in order to not incorrectly increment the build number and also not to waste
time and resources by manually checking out the nightly-build repo for each of
these builds.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Increase the precision of the setpoint that can be specified per planned
leg of the dive to 0.01 mbar.
Some rebreather models (APD Inspiration) support this precision for
setpoint setting.
Motivated-by: https://groups.google.com/g/subsurface-divelog/c/pD5gYlG5szI/m/G8_as4TyBwAJ
Signed-off-by: Michael Keller <github@ike.ch>
I ran into this a couple of times where the debug output didn't seem to
make any sense until I understood that libgit simply didn't give me
detailed error info.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is not a great way to load-balance, but it works and doesn't require
high end hardware on the backend.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If there are no gas mixes returned by libdivecomputer, we need to default to air. The previous commit would have defaulted to pure oxygen.
Signed-off-by: Micha WERLE <micha@michaelwerle.com>
During code review, an argument was made to use the bottom gas mix as
the mix to fill additional tanks with instead of the last mix reported
by the dive computer.
This change implements `get_deeper_gasmix` which compares two gas mixes
and returns the one with the lower MOD. This comparison does not perform
actual MOD calculations but only performs a relative oxygen and helium
content comparison.
Instead of saving the last gas mix and assigning it to additional tanks,
a `bottom_gas` mix is saved and assigned instead.
Signed-off-by: Micha WERLE <micha@michaelwerle.com>
Reverted "optimisation" based on code feedback.
Firstly, it's implementation-defined whether or not a stack frame is created for sub-scopes, secondly any optimisation is questionable regardless, and thirdly it was felt that it makes the code harder to understand.
Signed-off-by: Micha WERLE <micha@michaelwerle.com>
Instead of defaulting to air when we run out of gas mixes to assign to
cylinders, use the last gas mix provided by the dive computer.
If no gas mixes are provided at all, then default to air.
This prevents Subsurface from "inventing" gas mixes which are not
reported by the dive computer. It also works very nicely with a sidemount
configuration where the dive computer typically reports two cylinders but
only a single gas mix.
Signed-off-by: Micha WERLE <micha@michaelwerle.com>
The divecomputer_device_open() function tries all supported transports
one by one, and exits as soon as one is opened successfully. When the
end of the function is reached, the DC_STATUS_UNSUPPORTED error code is
returned.
The annoying side effect is that the actual error code returned by the
transport is ignored and changed into DC_STATUS_UNSUPPORTED. This is
very confusing while troubleshooting download problems.
Fixed by initializing the error code to DC_STATUS_UNSUPPORTED, in case
no transport is available for trying, and returning the last reported
error to caller.
Signed-off-by: Jef Driesen <jef@libdivecomputer.org>
Add the Aqualung i330R and Apeks DSX model numbers to the Pelagic
pattern table. These two models also use a new BLE service UUID.
Signed-off-by: Jef Driesen <jef@libdivecomputer.org>
The UUID of the Divesoft BLE service needs to be added to the list of
known services. It's a 16-bit UUID that gets detected as a standard
service and is ignored otherwise.
Signed-off-by: Jef Driesen <jef@libdivecomputer.org>
When we've already seen a trimix gas, of we after that see a nitrox gas
with less o2, it shouldn't update the mino2 state.
Signed-off-by: Anton Lundin <glance@ac2.se>
When the import from a dive computer gives you 100% as the first gas,
the get_dive_gas never finds which gas had the lowest o2 percent.
This fixes the logic to find the lowest o2 percent in any dive cylinder
list.
Signed-off-by: Anton Lundin <glance@ac2.se>
It looks kinda strange that all CCR dives have a dive gas ..100%, so
rather than showing it as the dive gas used, just ignore cylinders
with usage flagged as oxygen.
Signed-off-by: Anton Lundin <glance@ac2.se>
If enabling the notification fails, receiving data packets is not
possible. Instead of silently ignoring this fatal problem and trying to
continue, report the error back to the caller.
Signed-off-by: Jef Driesen <jef@libdivecomputer.org>
The existing logic correctly calculates the minimum (ie, ending) pressure, but not the maximum
(ie starting) pressure.
For example, 2 tanks A and B with manual pressures (same tank on subsequent dives, which were
then merged):
A: 205 - 84
B: 83 - 55
When merging the starting pressures, the call is : merge_pressure(205, 0, 83, 0, false)
The final comparison is:
if(false && 205 < 83) return 205;
else return 83;
-> So 83 is returned even though 205 should have been.
Signed-off-by: Michael Werle <micha@michaelwerle.com>
When events are hidden in the profile, only hide events with the same
name and the same severity (flags).
From discussion in https://github.com/subsurface/libdc/pull/54.
Signed-off-by: Michael Keller <github@ike.ch>
Fix how gases are marked as 'used' and kept from being deleted in the
equipment tab for CCR dives.
It does not make sense to treat the (arbitrary) first gas in the list
with a usage type of 'diluent' or 'oxygen' as 'used' and prevent the
user from deleting it. Dive computers report the initial diluent and
any other diluents used through a 'gaschange' event, so the actually
used diluents are already picked up as part of gaschange event based
logic.
Also clarify the selection of the first diluent used as a default if no
gaschange events exist.
Also fixed the test data - gases that have a pressure change should be
included in the profile if they do not have a gas change recorded
against them by other dive computers, even if they are oxygen.
A secondary problem shown by this is that the pressure change is not
applied to the profile - the pressure is currently shown as constant on
the start pressure. But this is for another pull request.
Signed-off-by: Michael Keller <github@ike.ch>
Include unused tanks in merges of multiple logs into a single dive if
the 'Show unused cylinders' preference is enabled.
Also rename the preference (in code) to `include_unused_tanks` to
reflect the fact that it is already used in more places than just the
display (exporting, cloning dives).
Simplified the cylinder model to make forced inclusion of unused tanks
dependent on use of the model in planner.
Leaving the persisted name of the preference as `display_unused_tanks`
to avoid resetting this for all users - is there a good way to migrate
preference names?
Signed-off-by: Michael Keller <github@ike.ch>
Mark gases that are reported as 'inactive' by the dive computer as 'not
used' in the Equipment tab.
Requires https://github.com/subsurface/libdc/pull/52.
Signed-off-by: Michael Keller <github@ike.ch>
The conversion between mbar and depth sometimes uses DC's salinity, sometimes user's salinity. By other hand, it uses surface pressure given by user in calculation.
This fix try to standartize this values, using them from same source.
Signed-off-by: Rafael M. Salvioni <rafael.salvioni@gmail.com>
Add a button that allows the user to hide the infobox with statistics
about the point in the dive under the mouse cursor in order to be able
to see the full dive profile unobstructed.
Signed-off-by: Michael Keller <github@ike.ch>
Add meaningful error messages when creating a libdivecomputer dump. In
particular show if creating a dump is not supported on the dive computer
that is used.
Signed-off-by: Michael Keller <github@ike.ch>
The memory management and string concatenation was hard to follow.
Since the mobile files ios.cpp and android.cpp were already
converted to C++, let's do the same for Unix, Windows and MacOS.
Simply store the default directory and filename in a function-level
static string. Thus, it will be initialized on first call and
freed on application exit. Since the std::string data is
guaranteed to be contiguous and zero-terminated, it can be used
from C code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add support for tracking the gas usage across multiple tanks to the 'bar
used' and SAC values shown for the profile ruler.
The following rules are implemented:
- a tank is considered 'used' if at least one bar has been consumed;
- only used tanks are taken into account for calculations;
- 'bar used' is only shown if all tanks used have the same (or unknown)
volume;
- SAC is only shown if all tanks used have a known volume.
Fixes#3902.
Reported-by: @pabdakine
Signed-off-by: Michael Keller <github@ike.ch>
Remove `renderSVGIcon()` and `renderSVGIconWidth()`, as QPixmaps can be
loaded directly from SVG, and support scaling.
Signed-off-by: Michael Keller <github@ike.ch>
It's possible for the first sensor to start with a pressure
significantly lower than other sensors.
Signed-off-by: Michael Andreen <michael@andreen.dev>
This has to be applied to the object, not the pointer to the object.
Fixes a double-free crash introduced in 8cd451f.
Alternatively, we could use std::swap() for C++98 charm and perhaps
better readability for people unfamiliar with C++11. Nowadays,
std::move() is more idiomatic though. Shrug.
Reported-by: Michael Keller <github@ike.ch>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add an option for users to sync the dive computer time with the PC time
every time dives are downloaded.
Obviously this will only work on dive computers that have time
synchronisation support in libdivecomputer, for other computers a notice
is logged.
The selection for this option is persisted as a preference.
Signed-off-by: Michael Keller <github@ike.ch>
The undo-code uses owning pointers based on std::unique_ptr to
manage lifetime of C-objects. Since these are generally useful,
move them from the undo-code to the core-code. In fact, this
eliminates one instance of code duplication.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
displayed_dive used to contain the currently displayed (as in
shown on the profile) dive. However, now it is only a "scratch"
dive used by the planner and initialized every time the planner
is started. There is no point in clearing this dive when clearing
the dive data. In fact, the dive should probably be cleared when
the planner finishes.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The current dc global makes no sense on mobile. Therefore,
move the logic of the currently displayed dive computer
to the profile widget and remove the dc_number global
variable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was very weird: a setSelection() call was always followed
by a selectionChanged() call, though sometimes in convoluted
ways. Notably, the formed was called by the DiveListView, the
lattern then by the MainWindow.
Let's just merge these two functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The trip selection code was an awkward layering violation.
Whereas dive selections due to dive undo-commands trickled
down via DiveTripModel-->MultiFilterSortModel-->DiveListView,
for trip editing, the DiveListView directly intercepted the
TripEdited signal.
Instead, mimic the dive-selection code. This is a bit longer
but more consistent and logical. The undo/redo of trip changes
is now also a "programmatical" change of the selection.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
After sending a selection-change signal, there follows a current
dive changed signal. Combine these two into a single signal, since
usually the current dive is changed when the selection is changed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These were not optimal, because they would recalculate the current
dive and divecomputers for every invocation.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
delete_single_dive() is one of those remnants from before the
undo-code. Now it is only called in two contexts:
1) When clearing the whole dive log.
2) When importing dives from the cloud on mobile.
In the first case, the selection is cleared before deleting
the dives.
In the second case, let's just do the same.
Thus, we can remove the last call to the deselect_dive()
function that does some complex calculations concerning
the current dive and divecomputer.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Each of these calls recalculates the current dive and divecomputer.
Instead, collect the dives to be selected/deselected and (de)select
them at once.
This needs some code refactoring in the core, because we need a
function that
1) doesn't send a signal by itself.
2) doesn't clear the trip-selection.
This contains some reorganization of the selection functions
signatures: The filter code is the only caller that keeps the
selected dive and the only caller that cares about whether the
current dive changed. So let only the function that keeps the
selected dive return whether the current dive changed.
It's all very fragile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For each selected dive that is hidden by the filter,
unselect_dive() was called, which led to a recalculation
of the current dive and divecomputer.
Instead, collect all deselected dives and deselect them
at the end. Thus, these calculations are performed
only once.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This tries to encapsulate the management of the current dive and
divecomputer in the selection code. The current dive is alreay
set by setSelection(). Add a new parameter to also set the
current divecomputer. If -1 is passed, then the current
computer number is remained. This will allow us to audit the code.
Because for now, the whole "current dive computer" thing seems
to be ill-defined.
This fixes a bug: the dive-computer number wasn't validated
when making a new dive the current dive. The new code has some
drawbacks though: when selecting a whole trip, the validation
will be called for all dives in the trip and thus the dive computer
number will depend on the dive with the lowest amount of dive
computers in the trip. This will need to be fixed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This removes a constant describing the length of the array.
The enumerated_range code had to be adapted, because the
interaction of C-type arrays with the C++ typesystem is mad.
With C-type arrays, one has to pass a reference to std::declval.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The parser API was very annoying, as a number of tables
to-be-filled were passed in as pointers. The goal of this
commit is to collect all these tables in a single struct.
This should make it (more or less) clear what is actually
written into the divelog files.
Moreover, it should now be rather easy to search for
instances, where the global logfile is accessed (and it
turns out that there are many!).
The divelog struct does not contain the tables as substructs,
but only collects pointers. The idea is that the "divelog.h"
file can be included without all the other files describing
the numerous tables.
To make it easier to use from C++ parts of the code, the
struct implements a constructor and a destructor. Sadly,
we can't use smart pointers, since the pointers are accessed
from C code. Therfore the constructor and destructor are
quite complex.
The whole commit is large, but was mostly an automatic
conversion.
One oddity of note: the divelog structure also contains
the "autogroup" flag, since that is saved in the divelog.
This actually fixes a bug: Before, when importing dives
from a different log, the autogroup flag was overwritten.
This was probably not intended and does not happen anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Some DCs only report water type, without salinity level. Subsurface
fixes most of these cases using default levels, but when the type of water
is Sea/Salt, this fix was not saved.
This causes a bit confusion, mainly if the user defines own salinity level.
Signed-off-by: Rafael M. Salvioni <rafael.salvioni@gmail.com>
Since the only caller was C++ code, this can be done in
C++ code, which removes memory-management headaches.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In order to support development of the open source firmware of the
OSTC4.
Requires changes in libdivecomputer.
Signed-off-by: Michael Keller <github@ike.ch>
Fixes a bug reported in
https://groups.google.com/g/subsurface-divelog/c/8N3cTz2Zv5E:
When planning a CCR dive with multiple segments, the textual dive plan
was showing a non-existent gas change with bogus data. The first part
of the fix is uncluttering of the message printed: Since this change is
_after_ the current diveplanpoint the data needs to come from `nextdp`
and not `dp`. The second part is that the message is not printed any
more if the current and the following segments have been manually added:
According to comments in the code the change should only be printed on
the segment _before_ the change if this segment is an ascent segment
that is followed by a manually entered segment.
Signed-off-by: Michael Keller <github@ike.ch>
The event names were registered in add_event(). However,
the undo system did not use that function, but add_event_to_dc(),
which takes an already allocated event.
That gave the following unfortunate situation:
Load a log without setpoint changes.
Add a setpoint change.
The setpoint change event type now was not registered and
therefore couldn't be hidden.
Admittedly, a subtle bug, but still a bug. Fix by registering
event names on event creation.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The eventname handling code was splattered all over the place.
Collect it in a single source file and use C++ idioms to avoid
nasty memory management. Provide a C-only interface, however.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Changed the way dive data points for OC cylinders to be added to the
dive plan are created in `createTemporaryPlan()` in
`diveplannermodel.cpp`. This now uses `plan_add_segment()` like all
other places where dive data points are added, in particular the planner
tests.
This also allowed for `create_dp()` to be made static.
Signed-off-by: Michael Keller <github@ike.ch>
Fixes a bug reported in
https://groups.google.com/g/subsurface-divelog/c/8N3cTz2Zv5E:
When planning a CCR dive with OC bailout, the diluent gas may be chosen
as the first OC bailout gas, despite being set up with a use type of
'diluent', and likely not being available for open circuit breathing.
`best_first_ascend_cylinder` is now initialised to an invalid value
(instead of the first cylinder, which may or may not be a diluent
cylinder), and its subsequent use is guarded by a validity check.
Signed-off-by: Michael Keller <github@ike.ch>
Change the values supplied in the warning to be fractions. This is what
is actually reported by libdivecomputer. The currently used thousandths
are hard to interpret for users, as they are only used internally in
Subsurface.
Signed-off-by: Michael Keller <github@ike.ch>
Fix bug introduced in #3576: On CCR dives cylinders listed as open
circuit bailout by the dive computer need to be set to `OC_GAS`.
Signed-off-by: Michael Keller <github@ike.ch>
These were two weird and clearly wrong constructs of the
type "if (iter && iter + 1)", where iter is a pointer. This
is always true at best and undefined at worst. Another
instance was removed in 096de0efd0.
The original code probably wanted to check whether the
found character was the last character in the string.
But that likewise seems to make no particular sense in
this context. Therefore, just remove the second part of
the boolean expression.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of adding all gases read from a dive computer as part of a dive
log as 'OC-gas', add gases as 'diluent' if the dive has a dive mode of
'CCR'. This creates consistency with the ppO2 for CCR dives being
tracked as sensor readings or a fixed setpoint, and not as the ppO2 of
the current gas ad depth.
A follow up question from this is whether gas use in the cylinders list
on the Equipment tab should be user editable. This seems to be
inconsistent at the moment, with gas constituent percentages downloaded
from the dive computer being editable, but gas use not.
Signed-off-by: Michael Keller <github@ike.ch>
`device_data_t data` in DeviceDetails has never been populated since it was first
added, and consequently is not used. This is confusing, especially as certain
fields inside `device_data_t` have been added directly to `DeviceDetails` in the meantime (e.g. `firmwareVersion`).
Separated from #3568 as per
https://github.com/subsurface/subsurface/pull/3568#pullrequestreview-1274995287.
Signed-off-by: Michael Keller <github@ike.ch>
When exiting the loop, stopidx is 0, which means that if there
are no stoplevels, stoplevels[stopidx + 1] generates an
out-of-bounds access. Instead, suppose a stop at 3m or 10ft.
Suggested-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When loading a git repository, dive sites where loaded into the
global dive site table, not the local table. Apparently, nobody
ever tried to import a git repository into an existing divelog
(as opposed to opening it in the application). Because that would
have probably given funky results.
Remove this access of a global variable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When collecting the data for the infobox, we have
already computed the current partial pressures of the
breathing gas taking into accoutn the divemode. Use
those rather than fractions (which for CCR mode are
those of diluent) to compute the gas density.
Reported-by: Pietro Tranquillini <p.tranquillini@gmail.com>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Most of these declared non existing functions or pointers.
One [get_gas_idx()] was only used in one source file and
doesn't have to be globally accessible
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Search the index of an item in a container. Compare by
equality or a lambda. The lack of these have annoyed me for a
long time. Return the index of the first found element or
-1 if no element found.
Currently, only supports random-access operators. Might be
trivially changed for forward iterators.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The chances that their are still users of the old thumbnail
format (i.e. all thumbnails saved in the hash file) are basically
0. If there are they will just get their thumbnails rebuilt
when opening the individual dives.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This source file was looping over descriptors in a classical
"for (int i = 0; i < size; ++i)" loop.
However, the index is not really used, except for fetching the
actual elements.
Replace by range-based for loops. This prevents the potential
error of using the wrong size.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the printing-template code, we loop through a vector and
then determine the index of the current element by searching
the vector. This irks me.
Since looping over a collection with an index is a rather
common theme, implement an enumerating iterator that can
be used as in:
for (auto [idx, item]: enumerated_range(v)) {
...
}
For now, use it for the above vexing case. Convert other
iterations of this theme later.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The moveInVector() function was defined in qthelper.h, even
though it has nothing to do with Qt. Therefore, move it into
its own header.
Morover, since it is a very low-level function, use snake_case.
And rename it to move_in_range(), because it does not only
work on vectors, but any range with random-access iterators.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For reasons of symmetry (there is a is_manually_added_dc()
function), create a make_manually_added_dc() function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This causes UI confusion. Notably we go into edit mode and
reduce the number of samples, leading to loss of information.
If someone really manually adds a dive with more than 50
samples, they should still be able to explicitly open the
dive in the planner.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
fixup_dc_sample_sensors() would make sure that any pressure sensor
indexes were in range of the cylinders by just clearing the pressure
data if the sensor index was larger than the number of cylinders in the
dive.
That certainly makes the sensor index data consistent, but at the cost
of just dropping the sensor data entirely.
Dirk had some cases of odd sensor data (probably because of an older
version of subsurface, but possibly due to removing cylinders manually
or because of oddities with the downloader for the Atomic Aquatics
Cobalt dive computer he used), and when re-saving the dive, the pressure
data would magically just get removed due to this.
So rewrite the sensor data fixup to strive very hard to avoid throwing
pressure sensor data away. The simplest way to do that is to just add
the required number of cylinders, and then people can fix up their dives
manually by remapping the sensor data.
This whole "we clear the pressure data" was at least partly hidden by
two things:
(1) in the git save format, we don't rewrite dives unless you've
changed the dive some way, so old dives stay around with old data
in the save until explicitly changed.
(2) if you had multiple dive computers, and one dive computer does not
have any pressure data but another one does, our profile will use
that "other" dive computer pressure data (because often times you
might have only one dive computer that is air integrated, but you
still want to see the tank pressure when you look at other dive
computers - or you have one dive computer give pressure data for
your deco bottle, and another for your travel gas etc).
So those two facts hid the reality that we had actually cleared the tank
sensor data for Dirk's dive with the Atomic Aquatics dive computer,
because we'd still see pressure data in the profile, and the git data
would still be the old one.
Until Dirk renumbered his dives, and the data was rewritten.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
It returned a 'uint8_t', which clashes pretty badly with NO_SENSOR being
-1, and turned it into 255. That then ended up historically working,
because before commit 0c84f369c3 ("core: use int16_t for sensor-id")
we actually did that everywhere:
#define NO_SENSOR ((uint8_t)-1)
...
uint8_t sensor[MAX_SENSORS];
but that was changed to
#define NO_SENSOR -1
...
int16_t sensor[MAX_SENSORS];
and this helper type became wrong.
Just make it return 'int', avoiding any type narrowing issues.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
A QVariant was initialized but never used.
While doing so, remove construct/assign pairs of a number of
QStrings. Directly construct the QStrings with the desired
values.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The get_minutes() function formats a time as m:ss
and returns a static C-string. Since all callers are
C++ anyway and transform directly into QString, let us
move this to the other string formatting function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The SSRF_INFO() macro is widely used, and there's a lot of confusion
about whether the newline at the end should be done by the SSRF_INFO or
be in the format string passed to it. End result: we end up doing both,
and there are empty lines in the output as a result.
Clean this up by just using our existing 'strip_mb()' to strip any
whitespace at the end of the generated string, and then adding one final
newline when logging it.
Also, make sure to log our 'report_error()' messages, which apparently
only used to be showin in the red error bar on the display.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
No reason to keep this as a macro - a function is easier to
read, type safe and easier to debug. Moreover, give it the
more appropriate name "nearly_equal()". After all, it precisely
does NOT check floating points for equality.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The FP_IS_SAME macro uses a relative precision to compare
floating points. This fails when comparing to 0. Therefore,
use an absolute precision in this case. Implement as an
inline function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For Ratio dive computers we can't tell by the Bluetooth name which model it is.
There are BT only models and BLE only models. The failure case here was a user
on iOS (BLE only) with a BLE only dive computer which we didn't recognize
because previously we returned a BT only device (which isn't supported on an
iPhone), and the lookup won't return a valid descriptor if the transport needed
isn't available.
These days BLE is far more common, so return a BLE enabled name by default, but
try a BT only name just in case.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When a dive has both real dive computers as well as at
least a planned version (which is just another dive
computer with a special name), only use the data from
real dive computers for aggregate values like maxdepth,
dive time, average depth etc in order not to have
imagined data on the dive list, statistics etc.
Macro-magic-provided-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
One would think that calling free() on a dive structure, as the code
did in some places, would lead to a memory leak.
(Insert rant about C memory management.)
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is stored as uint32_t, so no reason to use the larger time_t.
It appears to be, after all, relative to the dive start.
Coverity was complaining about the down-conversion later in the code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Adds a preference setting in the "Default" settings tab to toggle whether
to display shortened names in the Map.
TODO: instead of using the generic "settingsChanged" signal, it would be much
more efficient to only update items based on the actual setting which was
changed.
Signed-off-by: Michael WERLE <micha@michaelwerle.com>
In bc3b56a969, the import of the dive mode was simplified,
by replacing an if-else-if chain by bit manipulations.
However, the bitmask was wrong: 0b00111000 is 0x38 not 0x30,
which means that "odd" dive modes were not recognized as such.
Bug found by coverity.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The git save format is designed to be entirely line-based, where all the
dive data is on individual lines that are independent.
That is very much by design, so that you can merge these files
automatically, and not worry about what it does to the context (contrast
this to structured files like JSON or XML, where you have multiple
levels of indentation, and the context of a line matters).
So the parser can just ignore any conflict markers, and parse everything
one line at a time.
Well, almost.
We do have *one* special form of multi-line context, where flowed text
(think things like dive notes) will have one "header line" that starts
the note, and then it can continue for several lines until the final
line that ends the quote.
In such a situation, the dive merging can result in a partially merged
string note, which has the ending line from one dive, and then continues
with more string data from the other dive.
That will confuse our parser mightily, because it will have seen the end
of the string, and parsed the rest of those string comments as garbage lines.
That part in itself is fine - the garbage lines won't pass as any real
data (because they don't start with a proper keyword), but while parsing
that garbage the *next* end of the string will be seen as a start of a
new string.
And *that* then confuses the git parser to think that the line after
that is now part of the string, and so it won't correctly parse the
non-string line that follows.
To give a more concrete example, the git dive data (here indented and
abbreviated) might look like this:
suit "5mm long + 3mm hooded vest"
notes "First boat dive.
Giant-stride entry."
Saw a turtle."
cylinder vol=10.0l description="10.0ℓ" depth=66.019m
where the two notes from the two dives were
notes "First boat dive.
Giant-stride entry"
and
notes "First boat dive.
Saw a turtle."
respectively, and the merged result contained parts of both.
When we parse this, we will parse the 'notes' line as having the string
First boat dive.
Giant-stride entry
which is fine. But then the next line will be that
Saw a turtle."
and now the ending double quote character on that line will be seen as
the beginning of a new string, and the cylinder information on the next
line will then be mixed up. The resulting mess will be ignored, but in
the process the data on the "cylinder" line will basically have been
lost.
There are several ways to deal with this, but this particular fix
depends on the fact that we can recognize stale string continuation
lines: they are either empty (for an empty line), or they start with a
TAB character.
So to solve the problem with the mis-identified end quote, this
recognizes that we're in such a "stale left-over comment line" context,
and will just skip such lines entirely.
That does mean that when you have conflicts in dive note sections due to
having edited the dive concurrently on different machines, you may just
lose some of the edits.
But this way at least you shouldn't lose any other data due to the merge
conflict.
NOTE! We could try to improve on this by instead noticing that a "end of
multi-line string has a continuation entry on the next line", and just
say "ok, that wasn't a real end after all".
But that would be an independent thing anyway - this "ignore stale text
comment lines" logic would be required anyway, in case those stale text
comments ended up somewhere *else* than right after another text line.
So do this more important fix first.
Reported-by: Michael Werle
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
In utc_mkdate() we find the interesting statement
val = timestamp /= 60;
which not only calculates timestamp / 60, but also overwrites
timestamp with the new value. However, timestamp is never used
in the remainder of the function, because the whole point is to
switch to 32-bit types. Thus, replace the division-assignment
by a simple division operator to avoid head-scratching.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The liter symbol is written as 'ℓ'. To allow searching for
that, normalize unicode strings to their base letter. This
corresponds to the 'compatibility' mode.
We might also think about stripping diacritics.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The code works ok falling back to just Perdix and Petrel 2, but
it looks confusing to the user to see an incorrect name in the
connection drop down.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
It's confusing to have the same name refer to two different models.
Unfortunately, that's what Aqualung is doing by simply changing the
model number and serial number, but not the external branding.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In a sign how few people use these additional properties AND use multiple
dive computers, this took a couple of years to get noticed... but yes, we
do need to merge those properties as well.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When computing plan variations, deco can get shorter when
staying longer when the last step is actually already at
off gasing depth. FRACTION forces unsiged, so this introduces
a sign aware version of FRACTION that returns a sign character
in addition.
Reported-by: Patrick Naujoks <p.naujoks@me.com>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
This allows having 3m depth grid for metric users.
* All original properties ( named diferently ) were renamed to three_m_based_grid everywhere to be consistent.
* Plus other small changes requested during review.
Signed-off-by: Vlad A. <elf128@gmail.com>
Signed-off-by: Vlad A <elf128@gmail.com>
The Seac importer was getting samples based only on dive number,
which was causing samples from different computers but with the
same dive number to become interleaved.
To correct this, the SQL statement was updated to use the
dive_id to query for samples. The table schema uses dive_id
as a primary key, which will enforce uniqueness.
Additionally, deviceid is hashed from the the device_id string.
Reported-by: David Brebera <david.brebera@gmail.com>
Signed-off-by: Jim Wobser <james.wobser@gmail.com>
The calculation of the deco steps shown in the profile
infobox is somewhat independent of the planner. When
set to imperial units, the distance between deco stops
should be 10ft rather than 3m as 15m is only 49ft.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
The cylinder_with_sensor_sample() function only tests "do we have a mapping to
this cylinder for this sample". It also needs to test if there are any tank
pressure readings for that cylinder.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Arguably every dive should at least have one cylinder, but an imported
dive from divelogs.de might end up without one. Sadly, that breaks
assumptions that we make in the cylinder remapping.
To work around it, force at least on cylinder to be assumed in the merge
code.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
.. at least if the local repository exists and can be opened.
If the local repo cannot be directly opened, we will still try to sync
with the remote first, but this way the *common* git save situation is
that we save locally before we then try to sync with the remote.
That means that if we have network problems, the save will happen before
we possibly hang due to really really slow networking.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We had various random "free parts of the git info" left-overs from when
we passed down the git repo data ad-hoc. Get rid of it, and replace it
with just doing a 'cleanup_git_info()' that does the final cleanup of it
all.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
That function name was incomprehensible. What did it check? And what
did the return value mean?
So let's rename it to something that actually describes what it does,
and reverse the meaning of the return value while at it.
So now it's called 'remote_repo_uptodate()', and it returns true if the
remote repository branch has the same value as our 'saved_git_id'.
It's still a bit obscure, but at least within the context of the only
user, the code now makes _more_ sense than it used to:
if (remote_repo_uptodate(fileNamePrt.data(), &info)) {
appendTextToLog("Cloud sync shows local cache was current");
but maybe we could come up with even better semantics and naming, and
make it even clearer.
Requested-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We currently only have one single caller of update_local_repo(), and
instead of that caller checking whether the existing repo is a
directory, just make it open the git repository.
This avoids duplicate error handling and simplifies the code.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Because of the old connect syntax used the incorrect signal names weren't
caught at compile time. To switch to the new syntax we had to make two
functions pure virtual in the WebServices class - let's hope I got that right.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Making this simply depend on Qt5 or Qt6 was short-sighted as work on QtLocation
upstream continues. Instead break this out as its own option.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Just like the rest of the git repo related information, this is already
included in the git_info struct.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We have this nasty habit of randomly passing down all the different
things that we use to look up the local and remote git repository, and
the information associated with it.
Start collecting the data into a 'struct git_info' instead, so that it
is easier to manage, and easier and more logical to just look up
different parts of the puzzle.
This is a fairly mechanical conversion, but has moved all the basic
information collection to the 'is_git_repository()' function. That
function no longer actually opens the repository (so the 'dry_run'
argument is gone, and instead a successful 'is_git_repository()' is
followed by 'opn_git_repository()' if you actually want the old
non-dry_run semantics.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
It appears to send a first sample with a water temperature of 0 C. If the next
sample contains a more likely water temperature, overwrite the first one.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
libdivecomputer tries to be super careful in what it tells us. It only offers a
density value if that is something that the dive computer explicitly supports,
otherwise it just offers back a flag. We need to then update the density value
ourselves.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
I didn't pay attention and entered the wrong flavor of Portuguese as the
parent translation. The one for Portugal is complete and should be the
parent, back-filling the one for Brazil where needed.
Suggested-by: Christof Arnosti <charno@charno.ch>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Tweak the Lat/Long coordinate parser to allow coordinates of the form:
12.1049° N, 68.2296° W
The coordinate parser works by tokenizing coordinates one at a time.
Consequently it is invoked twice on user input to get latitude and then
longitude. Normally, after parsing the first coordinate, intervening
characters such as , or ; and any whitespace would be discarded from the
input before parsing the second coordinate. Prior to this patch, if the
coordinate format was in degrees followed by a sign (N is a sign in this
example), the parser would skip the bit of code that fast forwards past
any intervening separators and whitespace (, in this example). This
resulted in coordinates of this form not being accepted, because the
second parse would start with , 68.2296° W and reject this as an invalid
coordinate.
To rectify this, the bit of code that fast forwards past separators and
whitespace has been broken out from the tokenization loop and performed
as a final step after a single coordinate has been completely parsed and
validated. Doing it this way makes it independent of the state of the
tokenizer, so that the fast-forward code will always execute once a
coordinate has been successfully parsed.
I've also centralized the list of allowed separators into its own static
string; this is necessary as part of the patch but should also make
allowing additional separator characters between coordinates trivial in
the future, if needed.
Signed-off-by: Quentin Young <qlyoung@qlyoung.net>
Many language have country specific differences. We recognize different
flavors of English (US, UK (and South Africa)), German (Germany and
Switzerland), and Portuguese (Brazil and Portugal). For many other
flavors of the languages that we have translations for we have no
support and the way we hard-coded the fallbacks in the past was odd and
meant that in the cases where we do have two flavors, missing strings in
one weren't taken from the other (English as the default language being
the exception).
This tries to do a better job of recognizing some of those parent
languages and loading translators for them, first. Which means if we
then find a translator for the specific language (i.e., de_CH), strings
missing in that translation are next searched in the parent language
(de_DE), before finally providing the source language string (en_US).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If the current dive computer doesn't have a sensor for the cylinder then
check if another dive computer has sensor data available and use that
for the plot.
Signed-off-by: Michael Andreen <michael@andreen.dev>
We have a prevailing problem with global QObjects defined as
static global variables. These get destructed after main()
exits, which means that the QApplication object does not
exist anymore. This more often than not leads to crashes.
In a quick search I didn't find a mechanism to register
objects for deletion with QApplication. Therefore, let's
do our own list of global objects that get destructed
before destroying the QApplication.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The only things in display.h were profile related, so the
split between these two files is not comprehensible.
In fact profile.h includes display.h, because it needs the
struct defined therein. Let's just merge these two files.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The only caller misused this function to get access to the
current divecomputer. Remove it, since selection of the
current divecomputer is handled by the MainWindow.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There were only three users of that. For now do it inline, but
we may think about a separate function, which is only available
on desktop.
Moreover, add nullptr-checks, even if they are not strictly
necessary.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The dive was passed as an argument to update_event_name(), but
the divecomputer was derived from the global dc_number variable.
That makes no sense. Therefore, pass the dc_number as argument
and update the only caller (smtk-import).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
split_divecomputer() is passed a dive and a divecomputer number.
However, it accesses the currently visible dc!
This would be a nasty bug if it werent for the fact that it is
called when placing an undo command and there it is passed the
current dive and divecomputer anyway.
Nevertheless, fix this.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Previosuly they always used index 0 for the active sensor, use
add_sample_pressure instead.
Signed-off-by: Michael Andreen <michael@andreen.dev>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Add a column to the equipment table that shows if a sensor is attached to a
tank, or which sensors would be available to attach to a tank that currently
doesn't have a pressure sensor associated with it.
Changing the sensor assignement can be undone.
This column is hidden by default as this is a somewhat unusual activity.
Signed-off-by: Michael Andreen <michael@andreen.dev>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Use the explicit QBluetoothUuid instead of just QUuid and deal with new
constants and signal names.
At least with Qt6 we no longer need the ugly QOverload hack.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
QStringRef is gone in Qt6 and mostly replaced by QStringView. The one major
difference is that direct comparisons with string literals are no longer
possible.
Thanks to Thiago Macieira for helping me avoid more conditional compilation
here.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We do want the -Wfloat-conversion warnings where they point out
potential bugs. But they are very distracting when they are triggered by
floating point literals (which the standard defines as double) passed to
a function expecting float arguments.
The fact that Qt6 changes the arguments to all these functions from
double to float is... hard to explain, but it is what it is. With these
changes, for the majority of cases we create inlined helpers that
conditionally compile to do the right thing. And in a handful of other
cases we simply cast to float (and accept that on Qt5 this then gets
cast back to double... for none of these cases the potential loss in
precision makes any difference, anyway - which likely is why the Qt
community made the decision to change the type of the arguments in the
first place).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The first location we should try is one that allows us to share files.
In theory this should work on every device, but we do have a few
fall-backs, just in case.
This also moves the Android specific include to the top which seems much
more standard.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If a merge mishap creates inconsistent data for a dive in git storage,
where the dive references a dive site that no longer exists, the app
would crash when trying to open the cloud storage.
I don't think a NULL dive could ever happen, but this seems fairly cheap
insurance.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In general, replace "dive master" by "dive guide".
However, do not change written dive logs for now. On reading,
accept both versions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When the file system of the Zurich gets full, the only way to continue to
download from it, is to disconnect and reconnect the dive computer (which
resets the FAT file system that it emulates to 'empty').
This solution is rather hacky and weird because it does a hard count down in a
busy loop, but given the narrow use case, this may be acceptable.
This also adds support for the UEMIS_DIVE_OFFSET environment variable that
allows the user to skip dives on the device.
[refactored by Dirk Hohndel]
Signed-off-by: Oliver Schwaneberg <oliver.schwaneberg@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In the latest OSTC hardware, the Telit/Stollman bluetooth module has
been replaced with a u-Blox Nina B2 bluetooth module. The BLE
communication protocol remains roughly the same, except for a few minor
differences:
- New UUIDs for services and characteristics
- Only one common characteristic for Rx and Tx
- Credit based flow control is optional
- Credit value of 255 corresponds to a disconnect
[Dirk Hohndel: small edit to a comment]
Signed-off-by: Jef Driesen <jef@libdivecomputer.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Depths are pretty much universally stored using signed integers
(e.g. depth_t is signed int). For consistency, make feet_to_mm()
likewise return a signed value.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The prev_time variable was defined as unsigned and mixed
with signed variables. gcc rightfully complains with -Wextra.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since these are std::strings anyway, there seems to be no point
in using the C-lib functions. YMMV, but to me that code is
distinctly more easy to parse.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
With -Wextra, gcc/g++ complains that compound initialization
of weightsystem_t misses the auto_filled parameter. Add it.
For C++ code we might think about writing a constructor. However,
we use two versions: with and without copied string.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In pscr_o2() the result of a double calculation was implicitly
converted to int, which resulted in a gcc warning.
Part of the expression was explicitly converted to int, but then
subtracted from a double.
Instead, do all the calculations in double and cast the final
expression to int. This is probably the prudent thing to do.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This prevented calculation of the pressure data when dragging
planner handles. However, this lead to weird artifacts.
As an alternative, if this turns out to be too slow, we might
disable the plotting of the pressure curves instead.
That said, even on my super-slow fanless laptop, this performs
reasonably.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old get_maxdepth() function in profile.c was accounting for
two things:
- the partial pressure graphs
- rounding to sane value
Both are now taken care of by the profile itself. This leads to
excessive max-depths. Remove the code from profile.c.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
free_plot_info_data() frees the sample and pressure arrays
and accordingly sets the corresponding pointers to NULL.
However, it doesn't clear the element-count and thus leaves
the structure in an inconsistent state.
Clear the whole structure with memset(). I am not a fan of
doing so, but there are existing memset() calls in the
same source file, so let's keep it like that for consistency.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
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>
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>
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>
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>
To enable grouping by trip in the statistics module, split
the get_trip_title() function in a version that appends
a "(n dive(s)" string an one that doesn't. The statistics
module doesn't want that added string, since it displays
the number of dives in a different way.
Also, move the functions to string-format.h, where these
are collected. And rename them to camelCase. Yes, it's
ugly, but consistent with most other C++ code in the code
base.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When adding a cylinder, it was added at the end of the list.
This would make hidden cylinders visible as the new rule is
to only hide unused cylinders at the end of the list.
Therefore, add the cylinder after the last used cylinder,
i.e. before the first hidden cylinder.
This means that the position where the cylinder is added has
to be hidden in the undo command.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The D in MOD, EAD, END, and EADD stands for "depth" and
as such these should be mm in int rather than double.
The intermediate fn2 and fhe2, however, as intermediate
value should not be rounded to an integer.
The upshot of this is a litle more numerical stability.
It should lead to more stable values in TestProfile
when run on architectures with different floating
point precision.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
CCRs are different. It does not make sense to compute
a depth dependent SAC. You could compute the rate of O2
consumption but even that is likely wrong (as O2 in the
diluent would enter that as well), so simply don't attempt
it.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
And while doing that, have all the cases where we already include
qthelper.h simply use a define in that header file - but keep the two
other instances of the define where the C++ source don't need qthelper.h
otherwise.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Very similar structure to the XML format. Raw data is again saved as a
hex string (which implicitly provides us with its length). The rest of
components are in a more human readable format.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We always use the global fingerprint table - maybe this should just not
be a parameter of the accessor functions?
The syntax is very simple - the raw data is encoded as a hex string, the
rest of the components are hex numbers.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In order to not break existing behavior, we still store fingerprints on disk, but
we first check the data in the in-memory table, and we remember the fingerprint data
in the fingerprint table as well (which is then saved as part of the dive log data).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This just adds the basic structures and the accessor functions needed to
manage a table of fingerprint data. The table is indexed by the hash of
the model name and binary serial number as created by libdivcecomputer.
This way the data is accessible when libdivecomputer fist accesses a
dive computer (which is the point in time when we need to use the
fingerprint.
The table also contains the corresponding device id and dive id so we
can verify that the current dive table still contains that dive.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In both places in the UI where we show the date of a dive during
download we are actually pressed for space. So let's use the short
version of the date string to save some space.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Most divecomputers download data dive by dive - so we get reasonably
frequent updates during the download (as new dives are found and posted
in the progress text area). But some (like the G2) download all of the
new dives at once and only then start parsing them. As a result the
download can look like it is hung.
As a compromise this shows updates on the data received in 10kB
increments. Which for most cases should never be shown and therefore not
make the user experience any worse - but for cases like the G2 will make
a huge difference.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Qt 6 will drop support for QRegExp.
Use QRegularExpression instead.
Much of this is a simple replacement of one class with the other, but
there are some changes to the way matches are tracked and captures are
created. Also, the exactMatch now needs to be implemented via anchors in
the regular expression itself.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Qt 6 will drop support for QRegExp.
Use QRegularExpression instead.
This is a straight forward replacement without any other code changes.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Fix a pair of warnings, which annoyed me for a long time:
For some reasons prefs.bottompo2 is an integer (mbar)
whereas prefs.modpO2 is a float (bar). This results
in mixed integer/floating point arithmetics when
conditionally using either of them. And ultimately
a warning, when storing a mbar value as an integer.
Fix this by an explicit cast to int after converting
modpO2 to mbar.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Air is a special gas that does not contain oxygen according
to gasmix.o2.fraction. If you want to use the fo2, you
need to use get_o2() to treat this special case correctly.
This fixes a bug when setting the MND of a gas containing
21% oxygen when o2 is considered not narcotic.
Reported-by: Christoph Gruen <gruen.christoph@gmail.com>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
When we found an invalid sensor (referring to a non
existing cylinder) in fixup_dive() the sensor-id was
set to NO_SENSOR.
This led to invalid XML files, because the code decides
to switch into legacy mode. However, there are two
pressure readings, which is invalid in legacy mode.
Therefore, also clear the pressure data.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This tries to make our fingerprinting code work better, by avoiding
using the "deviceid" field that has always been unreliable because we've
calculated it multiple different ways, and even for the same version of
subsurface, it ends up changing in the middle (ie we calculate one value
initially, then re-calculate it when we have a proper serial number
string).
So instead, the fingerprinting code will look up and save the
fingerprint file using purely "stable" information that is available
early during the download:
- the device model name (which is a string with vendor and product name
separated by a space)
- the DC_EVENT_DEVINFO 32-bit 'serial' number (which is not necessarily
a real serial number at all, but hopefully at least a unique number
for the particular product)
but because the model name is not necessarily a good filename (think
slashes and other possibly invalid characters), we hash that model name
and use the resulting hex number in the fingerprint file name.
This way the fingerprint file is unambiguous at load and save time, and
depends purely on libdivecomputer data.
But because we also need to verify that we have the actual _dive_
associated with that fingerprint, we also need to save the final
deviceid and diveid when saving the fingerprint file, so that when we
load it again we can look up the dive and verify that we have it before
we use the fingerprint data.
To do that, the fingerprint file itself contains not just the
fingerprint data from libdivecomputer, but the last 8 bytes of the file
are the (subsurface) deviceid and the diveid of the dive that is
associated with the fingerprint.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Only used in context of acquiring GPS locations with the mobile app, which
we no longer do.
Keep the DiveAndLocation structure around as that's needed by the
ApplyGpsFixes command.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In commit 4724c88 get_plot_details_new was updated to pass an index
instead of the entry into plot_string. This means we are passing "i" to
plot_string after the final increment of the for loop, instead of
getting the entry[i] within the loop before the final increment. This
means if we are mousing over the far right of the graph, where the time
based break is not hit, we will end up passing an index equal to nr-2
instead of nr-3, which is intended to shave off the final two rows
containing data not useful to the display.
There are a handful of ways to fix this. This commit intends to be
consistent with stylistic choices made elsewhere in the project.
Signed-off-by: Josh Torres <torres.josh.j@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We want to prevent the user from accidentally deleting a
cylinder with sensor readings. Therefore, we need such a
function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Due to changes in the handling of sensor-ids, invalid XMLs were
generated. In particular, these contained duplicate attributes
in the sample tags.
Even though these files shouldn't exist, let's try to parse
them anyway. Some data will be lost, but that's better than
not opening the file.
libxml2 can be told to try to recover from such petty(?) errors
by passing the XML_PARSE_RECOVER flag.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For dives with mixed divemode, one needs to check sample.setpoint
to figure out if the segment is an OC segment and the po2 needs
to be computed from the gasmix and ambient pressure.
This fixes#3310
Signed-off-by: Robert C. Helling <helling@atdotde.de>
We no longer need the remove infrastructure, and the edit nickname function
becomes much more intuitive to use by passing in the dive computer for
which we want to create a nickname instead of the internal index into
the array of devices.
This also removes / simplifies the device list update signals in the
DiveListNotifier.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This makes it much easier to manipulate dc nickname entries. In order
for that to work we can't simply remove entries with empty nickname (but
that isn't needed, anyway, as the code that saves XML or git already
handles that case correctly).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
... it just causes problems later when we free them, since we don't do
any reference counting.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
When we save the divecomputer data, we never actually save the serial
value as a field. We used to rely on saving the very dodgy 'deviceid',
and then look up the serial number from there. And that never really
worked reliably, but we didn't really notice, because we never really
_used_ the serial number anywhere.
The only place the serial number is actually reliably displayed is in
the "Extra data" tab, which contains the key value pairs, and that's
where the original dive download code got the serial number from.
So just parse that at load time too, the same way we parsed it at dive
download time.
In fact, do the firmware version the same way, and remove the code from
the downloader, since it too can rely on 'add_extra_data()' just picking
up the information directly.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We have this odd legacy notion of a divecomputer 'device', that was
originally just basically the libdivecomputer 'EVENT_DEVINFO' report
that was associated with each dive. So it had firmware version,
deviceid, and serial number.
It had also gotten extended to do 'nickname' handling, and it was all
confusing, ugly and bad. It was particularly bad because it wasn't
actually a 'per device' thing at all: due to the firmware field, a dive
computer that got a firmware update forced a new 'device'.
To make matters worse, the 'deviceid' was also almost random, because
we've calculated it a couple of different ways, and libdivecomputer
itself has changed how the legacy 32-bit 'serial number' is expressed.
Finally, because of all these issues, we didn't even try to make the
thing unique, so it really ended up being a random snapshot of the state
of the dive computer at the time of a dive, and sometimes we'd pick one,
and sometimes another, since they weren't really well-defined.
So get rid of all this confusion.
The new rules:
- the actual random dive computer state at the time of a dive is kept
in the dive data. So if you want to know the firmware version, it
should be in the 'extra data'
- the only serial number that matters is the string one in the extra
data, because that's the one that actually matches what the dive
computer reports, and isn't some random 32-bit integer with ambiguous
formatting.
- the 'device id' - the thing we match with (together with the model
name, eg "Suunto EON Steel") is purely a hash of the real serial
number.
The device ID that libdivecomputer reports in EVENT_DEVINFO is
ignored, as is the device ID we've saved in the XML or git files. If
we have a serial number, the device ID will be uniquely associated
with that serial number, and if we don't have one, the device ID will
be zero (for 'match anything').
So now 'deviceid' is literally just a shorthand for the serial number
string, and the two are joined at the hip.
- the 'device' managament is _only_ used to track devices that have
serial numbers _and_ nicknames. So no more different device
structures just because one had a nickname and the other didn't etc.
Without a serial number, the device is 'anonymous' and fundamentally
cannot be distinguished from other devices of the same model, so a
nickname is meaningless. And without a nickname, there is no point in
creating a device data structure, since all the data is in the dive
itself and the device structure wouldn't add any value..
These rules mean that we no longer have ambiguous 'device' structures,
and we can never have duplicates that can confuse us.
This does mean that you can't give a nickname to a device that cannot be
uniquely identified with a serial number, but those are happily fairly
rare (and mostly older ones). Dirk said he'd look at what it takes to
give more dive computers proper serial numbers, and I already did it for
the Garmin Descent family yesterday.
(Honesty in advertizing: right now you can't add a nickname to a dive
computer that doesn't already have one, because such a dive computer
will not have a device structure. But that's a UI issue, and I'll sort
that out separately)
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
If we download a first dive computer and add a dive site to the dive (by
setting a location name for example), and then download from another
dive computer that provides us with GPS data, we should keep the
existing dive site information, but add the GPS data from the freshly
downloaded dive computer.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This adds a cleanup function to be called after a divelogs.de upload
finishes (successful or not) to make sure the temporary zip file is
closed and removed.
Signed-off-by: Richard Fuchs <dfx@dfx.at>
On multi-user systems with a shared directory for temporary files, using
a static file name can lead to permissions problems and subsequent
errors due to collisions. Use a random unique file name for each
generated file to avoid these problems.
Note: the temporary file generated from the divelogs.de upload is still
left behind after the upload finishes.
Signed-off-by: Richard Fuchs <dfx@dfx.at>
The intent of the code was to check that there is a string and it has at least
two characters. Since iter is the result of a strchr(iter, '|') call, we
know that if iter isn't NULL, iter[0] is '|', so we only need to check the next
character.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
try_to_xslt_open_csv() re-allocates the memory passed in (not really great as
far as design goes, maybe something that should be reimplemented). Doing
pointer arithmatic with the returned base pointer results in garbage, unless
one gets super lucky and the realloc manages to not move the memory.
It's a wonder this ever worked.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Before making the cylinder-table dynamic, dives always
had at least one cylinger. When such a dive is displayed,
the TabDiveInformation class calls per_cylinder_mean_depth().
If there are no samples, this function generates a "fake
profile" with fake_dc(). Thus, effectively dives always
had samples once the user was displaying them.
When the cylinder-table was made dynamic, dives without
cylinders were supported. This can notably happen, when
importing from CSV (this could actually be a bug).
per_cylinder_mean_depth() exits early in that case and
doesn't create a fake profile. This lead to crashes
of the profile-widget, which were fixed in 6b2e56e513.
Non-sample dives were now shown with the Subsurface-logo.
To restore the previous behavior, genarate a fake profile
for sample-less dives in fixup_dive(), which is called
anytime a dive is loaded or imported. This seems to
have been the intention anyway and this worked only
"by chance". This will make a few fake_dc() calls obsolete,
but so be it.
Since fake profiles are now generated on loading,
the parse-tests need to be fixed to account for that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When merging two dives, the higher CNS value was taken. This could
result in inconsistent CNS values if two dives were merged where
one dive's CNS was calculated from a "fake profile", i.e. a dive
without dive-computer profile. In that case, the most conservative
value (all time spent at the bottom) was assumed. The merged dive
then consisted of the dive-computer profile and the conservative
CNS estimate.
This is fixed by setting the CNS value to "0" after merging,
which means "unknown". The correct value will then be recalculated
in "fixup_dive" from the actual sample data.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The data of the membuffer is passed as a data/length pair
to xmlReadMemory(). There is no point in NUL-terminating it.
Moreover, pass the data directly to xmlReadMemory()
instead of via variables. These variables are reused
later with a different meaning, making this super-confusing.
The membuf variable is turned from "const char *" to "char *"
to signal that we own the buffer.
Amazingly, zip_source_buffer() frees the buffer, even though
a "const void *" is passed in. This API is pure madness. Add
a comment.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Thus, the membuffer data is automatically freed when going
out of scope - one thing less to worry about.
This fixes one use-after-free bug in uploadDiveLogsDE.cpp
and one extremely questionable practice in divetooltipitem.cpp:
The membuffer was a shared instance across all instances
of the DiveToolTipItem.
Remves unnecessary #include directives in files that didn't
even use membuffer.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
C-style memory management is a pain and nearly nobody seems to get
it right. Add a C++-version of membuffer that frees the buffer
when it gets out-of-scope. Originally, I was thinking about
conditionally adding a constructor/destructor pair when compiling
with C++. But then decided to create a derived class membufferpp,
because it would be extremely confusing to have behavioral change
when changing a source from from C to C++ or vice-versa.
Also add a comment about the dangers of returned pointer: They
become dangling on changes to the membuffer.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The sensor-id in the sample struct was a uint8_t, with all
the known problems of unsigned integers. In the rest of the
code cylinder ids are signed integers. To avoid confusion,
make it a signed int. int8_t should be enough (max. 127
cylinders). To allow for degenerate cases, use an int16_t.
16k cylinders should be enough for everyone.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The code will happily perform out-of-bound accesses if
pressure-sensors refer to non-existing cylinders. Therefore,
sanitize these values in fixup_dive(), which is called
everytime a dive is loaded or imported.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
By default, the parser would create samples with cylinder
ids 0 and 1. This creates out-of-bound accesses for the
common one-cylinder (or even no-cylinder) dives. These
were harmless when the cylinder-table was of a fixed size.
Since changing to a dynamic cylinder-table, these became
actual out-of-bound accesses. Don't create such samples
in the parser.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The sensor member of sample refers to a cylinder from which
the pressure was read. However, some dives don't even have
a cylinder. Therefore, introduce a special NO_SENSOR value
for these dives. Since the cylinder is given as a uint8_t,
0xff seems to be a sensible choice.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When user has selected to show unused cylinders in equipment tab,
respect this setting when exporting to divelogs.de.
Fixes#3277
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
This is adding the capability to select 'Dive number' and 'Date / Time'
in the 'Copy dive components' dialog, and then copy them into the
clipboard.
When using 'Paste dive components, these values will then be pasted into
the selected dive(s).
This is intended to help with workflows that import dive information
from two different sources, like general information from another
logging program, and CCR ppO2 sensor readings from a unit log, and then
stitch them together into one cohesive entry with all data per dive.
Copied data is also output into formatted text when pasting the
clipboard outside of the application:
```
Dive number: 401
Date / time: Sun 2 May 2021 12:00 AM
```
No translations have been added as of now - I could not find any
information on how strings are translated for this project.
Signed-off-by: Michael Keller <github@ike.ch>
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>
the last manually entered waypoint but consider the
possibility that it should first top where we are
before the next stop depth has cleared.
Reported-by: David Carron
Signed-off-by: Robert C. Helling <helling@atdotde.de>
It looks like libxml2 has some internal limitations by default that
causes parse failures in some situations. Avoid them with
XML_PARSE_HUGE.
Without this, you get errors like
test.xml:349250: parser error : internal error: Huge input lookup
όμουν τουλάχιστον αλλά +2kg και ενδεχομένως +4
^
when something in the xml file grows too large.
I don't know libxml2 internals, so I have no idea what exactly goes
wrong, but the docs say:
XML_PARSE_HUGE = 524288 : relax any hardcoded limit from the parser
and that makes us successfully parse the Greek file from Kostas.
Reported-by: Kostas Katsioulis <kostaskatsioulis@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>