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>
Prior to this change, we had two different cylinder lists as models for
drop down boxes - one that prepends the "no default cylinder" entry
(which we need for setting up no default cylinder to be used in the
app), and another one that only includes actual cylinders.
The problem occured if a dive is created before the first time we edit
an existing dive: in this case we are applying indices across the two
models, but the indices are of course off by one; this results in
actually picking the wrong cylinder. So each time we try to edit a dive,
we end up with the previous cylinder in the list.
This commit simplifies the code by having only one place where we create
list of cylinder names (which is then used as the model for the combo
box). It also uses more logical names for the two 'flavors' of this list
to make it clear which one is supposed to be used (the regular list when
editing or adding dives, the one with the "no default cylinder" entry
prependet for the Settings page).
Reported-by: Brian Fransen
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
- add string serial numbers for Suunto Vyper and Mares IconHD type dive computers
- add support for Cressi Neon
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
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>
When strings in dive details wrap, the line spacing is too tight
in some circumstances. While not perfect, this change improves
the situation somewhat.
See #3263
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We already showed the tags, but we didn't allow the user to edit them.
This tries hard not to create inconsistent or illogical tags by trimming
white space and being careful with how the tags are added.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In the mobile version we should always allow a little more wait time for
the cloud server - there just seem to be more issues with response times
on mobile devices, especially when in places with poor data reception
(which isn't uncommon for dive sites).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
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>
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>
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>
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>
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>
The TabDiveComputer model won't work in the new world order, where you
can't even insert a new device entry without a nickname to be edited.
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 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>
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>
Commit e42fc1a1e9 introduced a
crash condition. Apparently the code attempts to test whether
the clicked-on item is a top-level dive. The "Collapse others"
menu item should not be shown in that case. It does this by
testing "d->divetrip". However, "d" might quite logically be
null if clicking on an unexpanded trip header.
Therefore, check explicitly for the trip header case (which
should show the menu item) and for good measure prevent
the nullpointer access (that should be caught by testing
for trip, but who knows).
Fixes#3301.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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 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>
I thought that explicitly requesting Qt5 should be enough, but we have a report
from a user who tried to build against Qt6 and cmake happily let them proceed.
So let's fail this explicitly.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
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>
Otherwise we end up with nonsensical values which lead to a division by zero,
which in return leads to different results, depending on platform.
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>
There is a function to format QString with C-format strings. Let's
use it instead of doing a detour via membuffer.
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 changes in commit 4daf687876 ("profile: remove [disable|enable]Shortcuts()
signals") resulted in us no longer enabling the shortcuts on the desktop (at
least on macOS where I debugged this). This placement of the call feels like a
bit of overkill, but at least it shouldn't be wrong.
Fixes#3293
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>