When parsing "event 123" (?) a picture is added, without
initializing the picture structure. Thus, a picture with a
random gps location is added.
Use the "empty_picture" initializer to avoid that. Fixes a
Coverity warning.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We used to round the ceilings for the individual tissues with
%.1f but the maximal (and thus effective) ceiling only with
%.0f. This makes no sense or be rounded up (to the conservative
side).
This commit shows also the maximal ceiling with higher accuracy.
Reported-by: Peter Hübner
Signed-off-by: Robert C. Helling <helling@atdotde.de>
When doing OC bailout from a CCR dive, there could still
be pO2 sensor readings but those are not valid.
This fixes a problem noticed by Justin Ashworth.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Even when diving a CCR, the pO2 cannot exceed ambient
pressure. This only makes a difference at shallow depths.
Fix this in the calculation of OTUs and CNS.
This affects some tests that now have slightly different CNS and OTU values.
Suggested-by: Justin Ashworth
Signed-off-by: Robert C. Helling <helling@atdotde.de>
We had a user request to allow for setpoint changes
at certain depths for CCR deco.
You can now enter a cylinder with name like
"SP 1.4" ('S' and 'P' and ' ' and a float) with
a switch depth and that cylinder is interpreted as
a depth dependent setpoint switch.
This user interface is a hack. But I believe that such
setpoint changes are similar enough to gas switches during
deco and should thus be handled in a simiar manner.
I would be happy to hear ideas how this could be made
less easter eggish.
Suggested-by: Justin Ashworth
Signed-off-by: Robert C. Helling <helling@atdotde.de>
The application state is a desktop-only thing. The mobile UI
also has its application state, but that is something completely
different.
The last remaining user of the application state was to flag
whether the planner is active. Since this has all been
unglobalized, the ApplicationState structure can be moved
from core to the desktop UI. And there it can be made local
to the MainWindow class.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The TemplateLayout prints different dives depending on
whether the planner is active. Instead of accessing a
global variable, pass the status down from the MainWindow.
That's all quite convoluted, since there are multiple
layers involved.
On the positive side, the in_planner() function has now
no users an can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To remove reliance on global state, pass an "in_planner" argument
to decoMode(). Thus, calls to in_planner() can be removed.
This is a more-or-less automated change. Ultimately it would
probably be better to pass the current deco-mode to the affected
functions instead of calling decoMode() with an in_planner
parameter.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To remove reliance on global state, pass an "in_planner" argument
to clear_deco(). Thus, calls to in_planner() can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To remove reliance on global state, pass an "in_planner" argument
to vpmb_next_gradient(). Thus, calls to in_planner() can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To remove reliance on global state, pass an "in_planner" argument
to add_segment(). Thus, calls to in_planner() can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The icons shown in the dive list were rendered for every single
access. Render them only once. This supposes that the
defaultIconMetrics structure does not change once the icons are
rendered!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There was the "application state", which decided what to show
in the "quadrants" and the "view state" which decided which
quadrant to show. These interacted in a hard-to-grasp way.
The "view state" is used to show the map or dive list in
full screen.
I simply couldn't get these two orthogonal states to interact
properly. Moreover the thing was buggy: If a quadrant was hidden,
the user could still show it, by dragging from the side of the
window, at least under KDE.
To solve these woes, merge the two states into a single
application state. If the widget of a quadrant is set to null,
don't show it. So the four "view states" are now "application
states" where three of the four quadrants are not shown.
This also changes the memory management of the widgets:
widgets that are not shown are now removed from the QSplitter
objects. This makes it possible that the same widget is
shown in *different* quadrants.
While writing this, I stumbled upon a Qt bug, which is known
since 2014:
https://forum.qt.io/topic/43176/qsplitter-sizes-return-0
When restoring the quadrant sizes there was a test whether
the quadrant size is 0. If that was the case, a default size
was set. This seems not to work if the widgets were recently
added. Since this test now always fails, make the quadrants
non-collapsible and thus guarantee that 0 is never saved as
a size.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Somehow three identical lines snuck into commit 0a4e37ee8b ("core/BT: simplify
detection of bluetooth names").
Reported-by: Henrik Brautaset Aronsen <subsurface@henrik.synth.no>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Instead of that super long if-else if chain, have something more
structured using a table for the common case of prefix based names.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
It would be so much nicer if we could just let libdivecomputer do this,
but the filter function there doesn't quite do things the way we need
them to be. Which is why we have our own function here.
This is a small attempt to rationalize the code that we have to make it
easier to maintain.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The goal is to enable a user experiencing crashes when applying GPS data
to their dive log to make all necessary data available to the
developers. Hopefully the clipboard is large enough to hold all the
data.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This only read accesses the dive and constructs a plot-info
structure. Make the dive parameter const.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function initializes decompression data from a dive.
The dive is not modified, therefore make it const.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We need to do this before the preferences are loaded, or the system
default size is lost. Given that our other sizes are all relative to
this value, that would be a problem.
With this we can now ensure that we always have the right font size for
smaller, regular, and larger theme settings.
Also removes some obsolete commented out code.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Adds fields to the advanced preferences page to modify GFLow and GFHigh for
the Buhlmann decompression model for calculating ceilings. Updated preferences
code to set the Buhlmann parameters in core/deco.c when the GF prefs are
updated.
Signed-off-by: Doug Junkins <douglas.junkins@gmail.com>
First, the time zone adjustment was wrong - this as written could only
ever have worked in UTC or by pure chance.
Second, the order of alerting the UI of the availability of a GPS fix
was also incorrect creating a race between the UI and our data
structures.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When setting a CCR setpoint, the profile code(!) would turn
the dive into a CCR dive. Not only should the display layer
not alter dives, this also means that the action is not
undoable.
Move that to the appropriate undo command, where it makes
more sense, but obviously also makes things more complicated.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The make_first_dc() function clones a dive with a certain dive
computer moved to the front. This is used by the
MoveDiveComputerToFront undo command.
make_first_dc() calls invalidate_dive(). However, the undo
command does that by itself on every undo/redo. Thus,
remove the call in make_first_dc().
Aside from consistency, the goal is to move invalidate_dive()
to command/* so that we can be more aggressive about the whole
topic: Store only "const dive *" pointers and thus force any
writing access to explicitly invalidate the dive cache.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveHandler shows a context menu where a cylinder can be
chosen. This indirectly accesses the global displayed_dive
variable.
Remove this in a step to make the profile reentrant.
The code was quite ominous: instead of simply generating the
list of cylinders, a global model was reset and then accessed
with Qt's cumbersome model/view API. All this trampling over
global state can be removed by simply making the function
that generates the list globally accessible.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of accessing the global displayed_dive variable
in RulerItem, pass the dive. This is a step in making the
profile reentrant.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of accessing the global displayed_dive variable,
pass the dive to the various profile items. This is a
step in making the profile code reentrant.
This removes the last user of the displayed_dc macro,
which can now be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Don't access the global displayed_dive variable in an effort
to make the profile reentrant.
Note that this still accesses the global dc_number variable,
which will likely have to be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The profile item that shows the ceilings adds a warning event
if the ceiling is violated. This is very unfortunate.
Improve this situation by adding the event up to the function
that calculates the ceiling. This is still not how it should
be - the display layer should not modify the dive that it
displays.
To make this clear, add a comment that details that this
is a contract between planner and display layer: The planner
uses a dive that can be trampled upon by the profile.
Still, this should be solved differently.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The in_planner() function is incompatible with a reentrant
profile, since it accesses a global variable. In
create_plot_info_new() it is essentially redundant, because
there is a planner_ds (ds = deco_state) parameter that
is used only when in the planner. Therefore use that as
the in_planner indicator: when non-null, the profile is
showing a planned dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
New (late 2020) iX3M hardware (refered to as 'iX3m with Sequared Buttons'
in the Ratio support section) appears to identify as iX5M, both in the
Bluetooth name and reported revision e.g.
$ ./ratio-toolbox-x86_64.AppImage info | head -n2
Model: Ratio® iX5M GPS TECH+
Firmware version: 4.1.26/016 (English)
Add a second Bluetooth name matcher for this variation, returning the same
(generic) model as is currently used.
Signed-off-by: Damian Zaremba <damian@damianzaremba.co.uk>
Add a new "statistics" application state. In the statistics state
show the statistics widget and the filter in the top quadrants.
The idea is to allow filtering and doing statistics at the same
time.
Sadly, we can't use the filter-widget in different quadrants,
because Qt's ownership model is completely broken / inflexible.
It does not support a widget having different parents and
thus a widget can only belong to one QStackedWidget.
Hiding the map in the statistics view is quite hacky:
Since the view of the quadrants is not determined by the
"ApplicationState", we have to restore the original quadrant
visibility when exiting the stats mode. Therefore, set the
original visibility-state when changing application state.
The MainWindow-quadrant code really needs to be rewritten!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Simply move the initialization of the logging function into its own method and
call that in the QMLManager constructor.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
These were declared in pref.h and defined in subsurfacestartup.c.
pref.c didn't even exist. Create it and move preferences-related
structs and functions there.
setup_system_prefs() is left in subsurfacestartup.c, since it
works with environment variables.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function is declared in core/unit.h, therefore it seems logical
to define it in the corresponding source file.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The user preferences can never end up with PASCAL pressure
units. The only place that uses these units is the XML parser.
Therefore, remove the PASCAL case in get_pressure_units().
This will remove an unused translation string.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The way I understand, the PASCAL pressure unit is used to parse
obscure dive logs. However, there is no support in the UI for
using Pa as pressure unit. Therefore remove reading / writing
this unit to git divelogs.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The get_*_unit() functions return the unit-name as set in
the preferences. Add versions with a "metric" parameter.
This will be used by the statistics code, which may in
the future allow for binning with alternative units.
All the unit-formatting functions should probably be moved
away from qthelper to their own source file.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was only used by the filter, but will also be used
by the statistics module. To avoid duplicate translation
strings, move to a common place.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The start-selection widget will need icons with a transparent
background so that the icons don't stick out like a sore thumb.
So far the icons rendered by this function were only used by
the images on the profile and were perfectly rectangular.
Therefore there was no need for this.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Create a gastype enum, which describes the type of a gas.
For now: air, nitrox, normoxic, trimix and oxygen.
This probably should be made configurable.
The gas types will be used to bin gasses in the statistics
module.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The renderIcon() function was used by the thumbnailer to
render SVG-based icons. Move it to the global qthelper.cpp
so that it can also be used by the statistics module.
Add "SVG" to the name to emphasize what it is used for.
For consistency also move the renderSVGIconWidth() function,
which renders to a fixed width, to qthelper.cpp
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Weirdly, this function was declared in dive.h and defined in
subsurface-startup.c. Let's move declaration and definition to
more appropriate places, viz. subsurface-time.h and time.c.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function was not used anywhere. Moreover, remove a few
unused includes from qthelper.h. Surprisingly, a number of users
of qthelper.h depend on these, so readd them at the appropriate
places.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Arguably, the number of filtered dives is a matter of the divefilter.
Let's move it there.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When removing dives, the UndoCommands would keep track of the
shown dives. When adding, they were calling into the filter
instead. Let's remove this asymmetry.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The shown_dives variable was reset by the dive_list code. Arguably,
the filter should keep track of the number of shown dives, so move
the resetting there. This means adding a new "reset()" member function
to the filter and call that instead of "updateAll()" when the core
data is reset.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since switching to the mobile-models and removing grantlee,
DiveObjectHelper was demoted to a thin wrapper around string
formatting functions. The last user was removed in a previous
commit.
It was never a good idea, given QML's strange memory-management.
Let's remove it.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When editing a dive, a DiveObjectHelper of the unmodified dive
was created to compare the edited with the old values. Since
the DiveObjectHelper is used here only as a pointless wrapper
around the formatting functions, call these functions directly.
However, note that the code is in principle wrong since the
change to the mobile-models, which do not use the DiveObjectHelper.
The real fix would be to reload the data from the model to prevent
going out-of-sync with respect to the formatting routines!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
With the removal of grantlee, this became pointless glue
code. Call the formatting functions directly.
Since the printing code was the only user of CylinderObjectHelper,
remove the whole thing.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
At this point (post grantlee), DiveObjectHelper is just pointless
glue code. Let's remove it from the printing code and call the
formatting functions directly. If necessary, move these functions
to core/string-format.cpp.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was a weird helper object, needed for grantlee. Instead
of storing this object, loop over cylinders and dives directly.
The actual accessor function is unchanged and now generates
a DiveObjectHelper or DiveCylinderHelper for every variable
access. Obviously, this is very inefficient. However, this
will be replaced in future commits by direct calls to formatting
functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The mobile version of the list used string formatting functions
defined in DiveObjectHelper and declared in mobilelistmodels.h.
Very confusing. Move them to a separate source file where - in
the long run - all the string-formatting functions, which
are scattered all over the place, can be collected.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Recently (d16a9f118a) the tankinfo table was made dynamic, which
means that the default tankinfos are added programatically.
Thereby, the wrong function was used for AL* type of cylinders:
metric instead of imperial. Fix those.
Reported-by: Michael Andreen <harv@ruin.nu>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
A user complained about the default cylinders list. Provide
a preferences option to turn this off.
When changing the preferences, the tank-info model will be
completely rebuilt. Currently, this is a bit crude as this
will be done for any preferences change.
Suggested-by: Adolph Weidanz <weidanz.adolph@gmail.com>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There was a tank info with an empty name. According to a comment,
this is needed for the "no cylinder" case. However, we now support
empty cylinder tables, so this is not needed anymore. Therefore,
remove it.
Make sure that the user can still enter the empty name, just in
case. But don't save the size and pressure in that case.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is obviously a pure code-hygiene thing. But with the new
dynamic tank info table, this becomes trivial, so let's do it.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The list of known tank types were kept in a fixed size table.
Instead, use a dynamic table with our horrendous table macros.
This is more flexible and sensible.
While doing this, clean up the TankInfoModel, which was leaking
memory.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
So far, the PreferencesDialog emitted a settingsChanged signal.
This meant that models that listened to that signal had to
conditionally compile out the code for mobile or the connection
had to be made in MainWindow.
Instead, introduce a global signal that does this and move
the connects to the listeners to remove inter-dependencies.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Provide supported dive computer list on the command line
and actually call the cli download. Still not functional.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
This is of course not functional at all, but it gives a first idea of
what we will need to do in this code.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Right now this doesn't do a thing, but it gives us a nice target that
has far fewer dependencies and should contain enough parts to download
stuff from a divecomputer and then sync that with cloud storage.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
in_planner() is problematic, since it is uses desktop-only
application state. Since the cylinder-model already has
an appropriate inPlanner flag, use this instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
As we switched to the qmake based build we now bundle the translations
via the Qt resource system instead of explicitly as Android assets. This
adjusts the code that opens the translations accordingly.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We don't support adding pictures and videos on mobile, so let's not
referernce the infrastrutcture that's needed for that.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
These are static functions, they cannot be used as a method on an object to
construct that object.
commit aa5f2e7c73 ("cleanup: replace deprecated sprintf()/vsprintf() calls")
introduced this bug in an ill-advised attempt to deal with a deprecation
warning.
This caused us to not print GPS coordinates in the UI.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Add a general dives-imported signal for those cases where we
want to fully rebuild models, notably, the completion models.
The divesAdded signals are too fine, because they are sent
per trip and we don't want to reload these models multiple
times per import.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When breathing pure oxygen and considering it not
narcotic, there is not maximal narcotic depth and
the formula divides by zero. So better, handle this
case separately.
Fixes#3080
Signed-off-by: Robert C. Helling <helling@atdotde.de>
The scope confusion between s (the for loop variable) and s (the function
argument) caused a crash in the s.split() on Windows.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Recently the QStrings were replaced by std::strings in device.cpp
so that they can be accessed from C-code. However, libstd being
modelled after C, constructing a std::string from a NULL pointer
leads to a crash.
Fix one case where this was overlooked.
Moreover, replace a null-pointer check by empty_string(), to
treat NULL and "" equally.
Reported-by: Salvador Cuñat <salvador.cunat@gmail.com>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Because of subsequent changes there is no clean way to just revert the changes
introduced in commit 8b36cf1051 ("desktop: offer different colors for info tab
titles"), so this manually removes the parts we don't need anymore.
This also restores a tooltip value that was inadvertantly removed in that
commit.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Add a preference option to set the color of the text on the information tab to
either MediumBlue, LightBlue or Black. The last two of these colors are meant
to enable areadable font contrast on displays with dark mode.
The choice is saved with the other preferences.
[Dirk Hohndel: this isn't really about dark mode, so changed many of the types
and variable names, changed the user visible texts, and
addressed some whitespace issues]
Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When encountering a <weight> tag, we would parse into the last
weightsystem. However, we only create weightsystems when
encountering <weightsystem> tag. Therefore, this code would
either crash or overwrite the previous weightsystem.
Instead, create a new weightsystem for each <weight> tag.
Moreover, make sure that inside a <weightsystem> tag a
weightsystem actually exists. This should be the case,
but who knows...?
Reported-by: Nihal Gabr <gabr.nihal@gmail.com>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When dives were merged on import, they were not unregistered
from their dive site and trip before being deleted. Thus, these
tables had stale pointers, which would ultimate lead to crashes.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This used to be a copy of QSysInfo. However, once the requirement
was raised to Qt5.4, this was replaced by a subclass of the original
QSysInfo - which made the whole file mostly obsolete.
Just use QSysInfo directly where needed.
Only for windows.c, which can't call directly into Qt, keep the
isWin7Or8() helper function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For multiple-choice constraints we use a bit field of type
uint64_t. This means we theoretically support up to 64 items.
Currently use at most seven.
Coverity complained (correctly) that we use the expression
"1 << x" to generate the bitfields. However 1 is a 32-bit
literal on most platforms, which makes this undefined
behavior for x >= 32. Change the integer literal to 64-bit
1ULL.
Moreover, when detecting items with an index >= 64, don't
even attempt to set the according bit, since this is
undefined behavior and the compiler is free to do as it
pleases in such a case.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If source files want to access preferences functions, they should
include pref.h themselves.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Nobody was using these return-code macros and the functions
do not exist since a long time.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These flags are not dive-related, therefore move their declaration
to the appropriate header file. Likewise, move their definition
from parse-xml.c to subsurfacehelper.c
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
unregister_dive() and delete_single_dive are defined in
divelist.c, as they take an "index" argument into the global
divelist. Therefore, move their declarations to divelist.h.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since dive.c is so huge, split out divecomputer-related functions
into divecomputer.[c|h], sample.[c|h] and extradata.[c|h].
This does not give huge compile time improvements, since
struct dive contains a struct divecomputer and therefore
dive.h has to include divecomputer.h. However, it make things
distinctly more clear.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function
1) was misnamed: it determined the time of the first selcted dive.
2) had only one caller.
3) would crash if there was no selected dive.
Let's just fold the functionality into the caller. It's a one-liner
anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In an effort to reduce the size of dive.h and dive.c, break out
the event related functions. Moreover event-names were handled
by the profile-code, collect that also in the new source files.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Desktop does not use mark_divelist_changed() anymore - all is done
via the undo machinery. Therefore move this function (and its
counterpart unsaved_changes()) to qmlmanager.cpp.
Ultimately, it probably should be removed from there as well, but
currently I don't dare to touch all the cloud-logic!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The undo machinery will need a method to remove devices based
on their index instead of their name. Add it.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add commands for deleting devices and editing device nicknames
to include the device-handling in the undo system.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Technically get_dive() could return a nullptr. The existing code made sure the
argument passed to get_dive() was one that always would result in a valid dive
pointer being returned. The new code is only slightly less efficient but allows
a static code analysis to easily see that we don't derefence NULL pointers here.
On some level this change is unnecessary. But it's also not wrong.
Fixes CID 354762
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The device nodes are created for all DCs, when importing the
dives. There is no point in creating only the device node for
the first DC in fixup_dive().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the specuial case of suunto, where we may add a device directly
instead of via dive->dc, add the device to the provided table.
The caller will then pass on the new device to the undo system.
This makes downloading finally really undoable (at least I
hope so). So far, the dives and dive sites were removed, but any
new device remained.
However, when setting the device-id via serial, we now have
to check both, the global and the downloaded list of devices.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In one weird case (suunto), the code in libdivecomputer.c
generates a device node directly instead of going the usual
way (setting the data in the dc-structure of the imported
dive). It is unclear to me whether that has to be that way,
as it depends on the chronological order of callbacks to
event_cb() and dive_cb().
Therefore add a device_table pointer to device_data_t
so that the downloader can add the device to this table. This
only adds the pointer, but does not yet use it in the
downloading code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The same structure was defined as "struct dc_user_device_t"
and typedefed as "device_data_t". Unify this. Since there
are much more of the latter, remove the former.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
So far, we added a non-global device table to the parser states.
Now, create device nodes in that table instead of in the global
table. Thus, on undo of dive-import, the new device nodes will
be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In analogy to the xml-parser add a device-table to git's parser-state.
Currently this is unused. In upcoming commits the git parser will
then be changed to add device nodes in this table instead of the
global device table. The long-term goal being to detach the
parsers from global state and to make dive-import fully undoable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function was misnamed in that it doesn't set the nickname
of a device. Instead, it adds all (unknown) devices of a
dive to the/a device-table. Let's call it appropriately.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a device_table parameters to Command::importTable() and
add_imported_dives(). The content of this table will be added
to the global device list (respectively removed on undo).
This is currently a no-op, as the parser doesn't yet fill
out the device table, but adds devices directly to the global
device table.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To include the device code in the undo system, we need functions
to check for the existence of devices and to add or remove them.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If we want to avoid the parsers to directly modify global data,
we have to provide a device_table to parse into. This adds such
a state and the corresponding function parameters. However,
for now this is unused.
Adding new parameters is very painful and this commit shows that
we urgently need a "struct divelog" collecting all those tables!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The XML-parameter code is a mess. Ownership is unclear. Allocation
and freeing of strings is in different functions. Sometimes
only every second string is free()d, because keys are not copied.
But this is done inconsistently. The caller has to know how
many parameters the callee may add.
Instead, let's add a small helper-struct that uses C++ memory
management, but exports a C-API. The array for the XML-library
is generated on the fly.
This is only the implementation, the old code is not yet replaced.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Apparently libdc gives us copies of strings. The API is very
scary, because (at least according to my reading of the code),
the key/value pair may be stored in a cache. Thus on free()ing
the string in the cache becomes invalid and we must not access
it twice. Very obscure.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Recently, the sorting of the devices was changed to be
case-insensitive for models for consistency reasons. However,
then the equality-comparison should also be case-insensitive.
Break it out into its own function, to avoid that mistake
in the future.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We used a typedef "filter_preset_table_t" for the filter preset table,
because it is a "std::vector<filter_preset>". However, that is in
contrast to all the other global tables (dives, trips, sites) that we
have.
Therefore, turn this into a standard struct, which simply inherits
from "std::vector<filter_preset>". Note that while inheriting from
std::vector<> is generally not recommended, it is not a problem
here, because we don't modify it in any shape or form.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
filter_preset_table_t was defined as "void" for C code.
However, that meant that any pointer could be passed as
such a table and such a table could be passed as any pointer,
without generating compiler warnings.
Indeed, we had a parameter-mixup that went unnoticed.
Therefore, make filter_preset_t an anonymous structure with
the name filter_preset instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The code in core/libdivecomputer.c used string insensitive
comparison for device models, before being merged into core/device.c.
Let's reinstate that behavior, since it appears to be more logical.
On would assume that two different vendors will not use the same
model with different casing (and the same device-ids), so that
should be safe.
This uses strcoll to correctly sort unicode, which will hopefully
never be needed!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To search for devices with the same model, we used find_if().
However, that was only to check whether such a thing exists,
not to actually do something with said device.
Therefore, change this to std::any_of() to make it clear what
the purpose of the statement is.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of accessing the global device table directly, add a parameter
to all device-table accessing functions. This makes all places in
the code that access the global device table grep-able, which is
necessary to include the device-table code in the undo system.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We now can loop over devices from C and check for selection.
So let's get rid of the last user of the call_for_all_devices()
callback.
Code readability improvement is not stellar, but one less
place where we shoe-horn user data through a void-pointer.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We have a callback for all devices with a twist: it can loop
over those devices that are used by a selected dive. This is
used for exporting a subset of the dive log.
Factor out the "is device used by selected dive" part of the
function and make it available to C. The goal is to make
the whole callback thing unnecessary and let C code loop
directly over the device list.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Now we can simply loop over the list of devices. In this case,
it's not much more readable, but at least we don't have that
nasty pass user-data through "void *" pattern.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was not used. Moreover, mark device::operator==() for removal.
This is used for detecting changes in the DiveComputerModel. This
can be removed once that is integrated into the undo system.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Searching the proper device for the divecomputer was done via a
callback. Very hard to follow code. Since we can now access
"struct device" from C, obtain it directly via get_device_for_dc().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function getDCExact() was used to search for a device structure
matching a divecomputer. Since C code can now access struct device,
we can export that function to C. Rename it to get_device_for_dc()
for consistency with naming of the core functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Up to now, "struct device" and "struct device_table" were C++
only, because they used C++ strings for convenience. Since we
switched from QString to std::string, we can create accessors
for these structs. For the C code, we simply declare them as
opaque structs and give the full definition only for C++.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since we converted from QString to std::string, let's also use
std::vector instead of QVector. We don't need COW semantics
and all the rigmarole. Let's try to keep Qt data structures
out of the core.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
struct device is a core data structure and therefore shouldn't use QString.
QString stores as UTF-16 (which is a very questionable choice in itself).
However, the real problem is that this puts us in lifetime-management
hell when interfacing with C code: The UTF-16 has to be converted to
UTF-8, but when returning such a string, this puts burden on the caller
who has to free it. In fact, instead of looping over devices from C-code
we had a callback that sent down temporary C-strings with qPrintable.
In contrast, std::string is guaranteed to store its data as
contiguous null-terminated and C-compatible strings. Therefore,
replace the QString by std::string. Keep the QString just in
one place that formats a hexadecimal number to avoid any
potential change.
The disadvantage of using std::string is that it will crash
when constructed with a NULL argument, consistent with C-style
functions such as strcmp, etc. Arguably, NULL is different
from the empty string even though we treat both as the same.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
empty_string() returns true for "". Thus, we can't simply overwrite
the pointer if empyt_string() returns true, but must free the string
regardless. The joys of C memory management!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The last two parameters of the parse_dan_format() function were
mixed up: sites should come before filter_presets.
This should have caused crashes, for DAN files with dive sites.
I don't understand why this didn't cause compiler warnings.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Recently (c9b8584bd2) the sort criteria of the device-table
was changed from (model/id) to (id/model). However, that
messed with the detection of duplicate device names: there,
the code searched for the first element greater or equal
to (model / 0).
With the reversal of the sort criteria, this would now
always give the first element.
Therefore, do a simple non-binary search, which is much
more robust. The binary search was a silly and pointless
premature optimization anyway - don't do such things
if not necessary!
Since only one place in the code search for existence
for a model-name, fold the corresponding function into
that place.
Moreover, change the code to do a case-insensitive compare.
This is consistent with the dc_match_serial() code in
core/libdivecomputer.c, where matching models is
case-insensitive!
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The device table is accessed by core via a callback using
call_for_each_dc(). This sorts the table by device-id. It
is unclear whether this is needed - since currently all it
does is make sure that the devices have a fixed order in XML
and git log files.
In any case, this means that the table had to be copied and
sorted in call_for_each_dc(). Since the frontend now does
its own sorting, we can just keep the core table sorted
as it needs it. This in turn will ultimately make it possible
to replace the callback by a simple loop.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This version is compile-time checked and therefore less risky with
respect to refactoring.
Since the same three signals were connect()ed for three different
threads-objects, do this in a new function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These will be recalculated from the pressures in fixup_dive()
anyway.
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When merging cylinders pressures derived from samples were taken
as maximum of the start and minimum of the end pressure, which
makes sense, since we believe that this is the same cylinder.
However, for manually entered pressures, this was not done.
Moreover, when one dive had manual pressures and the other only
pressure from samples, the manual pressure was taken. However,
that could have been the wrong one, for example if the end
pressure was manually set for the cylinder of the first part of
the dive, but not the last.
Therefore, improve merging of manuall set pressures in two ways:
1) use maximum/minimum for start/end pressure
2) if the pressure of one cylinder was manually set, but not for
the other, complete with the sample pressure (if that exists).
Fixes#2884.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was only set but never read. Therefore, remove it. Divecomputer
serial numbers are now handled via a string-based interface.
We can't remove the integer-based firmware number, because that is
still used by the OSTC firmware check in ConfigureDiveComputerDialog.
Let's not risk breaking that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This dates from 2014 - this should be obsolete: we certainly don't
support such old libdivecomputer versions. Moreover, we bundle our
own anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of just 'BT' or 'device name' (which is wrong in cases where we don't
use a device name in the first place, like USBHID), try to list the actual
transports that we will consider.
A big part of this patch is just moving code around so we don't need a forward
declaration of the static helper function.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Instead of just sending this to the user through the progress bar text, also
send things to stderr in verbose mode. That should make it easier to debug
situations where we fail to download from a dive computer.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Now, that we have this helper function that should have been
introduced long ago, we can make some more expressions
more idiomatic.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
We keep track of device, i.e. distinct dive computers with id in the core.
The corresponding code stuck out like a sore thumb. Firstly, because it
is C++. But more importantly, because it used inconsistent nameing conventions.
Notably it defined a "DiveComputerNode" when this is something very different
from "struct dive_computer", the latter being the dive-computer related
data of a single dive.
Since the whole thing is defined in "device.h" and the function to create
such an entry is called "create_device_node", call the structure "device".
Use snake_case for consistency with the other core structures.
Moreover, call the collection of devices "device_table" in analogy
with "dive_table", etc.
Overall, this should make the core code more consistent style-wise.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
core/device.c used to be a C file, which couldn't access the C++
divecomputer list directly. Therefore, instead of a simple loop,
searching for a matching DC was implemented via a callback with
void * user data parameter. Wild. Since the file is now C++, let's
just use direct access to the C++ data structures to make this
readable by mere humans.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These are used to search for device nodes and were passed model
and device id (for the exact version). However, all callers used
them to search for the node corresponding to a specific struct
divecomputer, so let's just pass that instead to make the caller
site less complex.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Remove the declaration of helper functions needed only in
core/device.cpp. To this goal, turn the member functions
into free functions.
Cosmetics: turn the DiveComputer[Node|List] "class"es into
"struct"s, since all members were public anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This adds filter constraints for numerical filtering for gas-mixes.
Currently, this does a "match any" kind of search, which means that
a dive is filtered if any of its cylinders matches.
We should also implement "all-of" and "none-of" modes for cylinder
filtering.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There were helper functions to access O2 and He component fractions.
Add another one for N2. Indeed, this can be used in three cases, where
N2 was deduced indirectly.
Moreover, add a general accessor with a gas_component argument.
This will be used by the filter code to filter for gas components.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The deco-routines used an enum to pass around the inert gas
type. Make that globally available and make it include O2.
This will be used in a future commit to generalize access
of gas fractions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
getDiveSelection() returns a vector of the selected dives.
Use that instead of looping over the dive table and checking
manually.
This removes a few lines of code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The get_trip_date_string() formatted, as the name implies, the date
of a trip. It was passed a number of parameters and had only one
caller, which would also add the location if it existed.
Therefore, move all that logic into the helper function and
name it get_trip_string().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Dirk reports that some Windows users have had odd corruption in the
commit messages in the cloud storage. They make no sense at all unless
there is some very weird Windows library bug.
The prime suspect is 'vsnprintf()' returning a negative error when the
target buffer is too small (rather than the proper "this is how much
space it would need"). That is a very traditional C library bug that I
thougth had been fixed everywhere, but there doesn't really seem to be a
lot of other likely causes.
So let's make our membuffer code be defensive against bad libraries that
return negative error numbers from vsnprintf.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Android can't scan for classic BT devices, so when BT support was first
added, we simply didn't use the discovery agent at all and relied on the
list of paired BT devices provided by Android.
This still worked fine for a lot of BLE devices that allowed 'bonding'
with the Android device - similar to pairing. But some BLE devices (like
the Shearwater Peregrine) don't support bonding and so our Android code
didn't see them at all.
With this commit we start a BLE only scan on Android to add to the list
of already paired devices.
Fixes: #2974
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We certainly should log errors and the complete list of discovered
devices.
Also, it's good practice to set a specific search time (I picked three
minutes). This way we won't constantly scan and drain resources.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We call the same helper from two spots. Once when we report the already
paired BT devices on Android, and once from the deviceDescovered signal
for the discovery agent. Let's make sure we can tell where the info came
from.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
So far we saved timestamps by their 64-bit value as decimal strings.
Change this to a user readable format. The parsing routine still
supports decimal numbers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To save datetime-based filter constraints to git or XML,
it is preferrable to use human-readable representations.
Therefore, add helper functions to format / parse timestamp_t
64-bit values in the "YYYY-MM-DD hh:mm:ss" format.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When importing a divelog, import filter presets. If there are
equal names, import only if the presets differ. In that case,
disambiguate the name. This made things a bit more complicated,
as comparison of filter presets had to be implemented.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The filter widget was caching whether the filter was active and
used that flag to calculate the "# dives shown" string. Move this
directly to the DiveFilter class to remove interdependencies and
to unify with mobile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is mostly copy and paste of other git loading code. Sadly,
it adds a lot of state to the parser-state. I wish we could pass
different parser states to the parser_* functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
On the mailing list it was decided that users might want to
move their filter presets across computers via the cloud.
Notably, in the future one might access statistics on mobile and
these might by controlled by filter presets.
The git save routines use the same string formatting as the
XML save routines. The string formatting is found in
core/filterconstraint.cpp. Thus, duplication of code and
inconsistencies should be minimized.
Each filter preset is saved into a file in the "02-Filterpresets"
folder in the root of the git repository.
Each file consists of one "name" line, zero or one "fulltext" line
and zero or more "constraint" lines.
The modes, types and the actual payload is controlled via attributes.
Thus, a preset file might look like this:
name "test"
fulltext mode="substring" query="clown"
constraint type="location" stringmode="starstwith" data="mafia"
constraint type="sac" rangemode="range" negate data="5000,10000"
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is a bit painful: since we don't want to modify the filter
presets when the user imports (as opposed to opens) a log,
we have to provide a table where the parser stores the presets.
Calling the parser is getting quite unwieldy, since many tables
are passed. We probably should introduce a structure representing
a full log-book at one point, which collects all the things that
are saved to the log.
Apart from that, this is simply the counterpart to saving to XML.
The interpretation of the string data is performed by core
functions, not the parser itself to avoid code duplication with
the git parser.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The parse_* functions should probably be declared in parse.h.
Arguably, parse_xml_init() and parse_xml_exit() should be moved
to an init.h file, however that doesn't yet exist.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Declare the function in the header file corresponding to the source
file where the function is defined.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Users might want to move their presets with there log-file. Therefore,
save the presets to the log. The alternative would be to save them
to the preferences. However, on the mailinglist it was decided that
moving the presets to a mobile device is a wanted feature.
The XML saving code has a rather reasonable interface, therefore
this turned out to be pretty easy to implement.
The filter presets are saved into a
<filterpresets>
...
</filterpresets>
block
Each individual preset is saved into a
<filterpreset name='...'>
...
</filterpreset>
Block with a unique name attribute.
Each preset contains zero or one fulltext and zero or more constraint entries.
The type and mode(s) are controlled by attributes, the "payload" is saved in
the block. Note that all the formatting is done by functions in core/filterconstraint.c
and not the parser itself.
A preset in the XML file might look like this:
<filterpreset name='test1'>
<fulltext mode='startswith'>Train</fulltext>
<constraint type='planned'>0,0</constraint>
<constraint type='sac' range_mode='range' negate='1'>5000,10000</constraint>
</filterpreset>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add undo commands to add / edit / delete filter presets.
These are styled after the other undo commands: On changes,
the UI is informed by DiveListNotifier signals. Editing is
a simple std::swap of values.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a rudimentary list of filter presets to the core. The list
is sorted by name. Access is provided via a C interface so that
the presets can be written to the git and XML logs. Internally,
the list is realized by a C++ vector for convenience (euphemism for
laziness).
Morover, a C++ interface is provided for the UI. Currently names of
the presets cannot be edited, since this would mean that the order
of the list changes. This may be implemented later if required.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Switch the mobile code to use the constraint-based filter. The one
thing that is still commented out is dive-site mode, since mobile
doesn't (yet) have a dive-site edit feature. And even if it had,
the dive list probably wouldn't be shown at the same time.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace the static filterwidget with a list of filterconstraints.
The first attempt of using a table widget failed, because Qt's
table delegates are dysfunctional. It's not that they are bad, they
just don't work at all.
Therefore, this code "simulates" a table in that on addition / deletion
of constraints it keeps track of the rows of all constraints so
that each constraint-widget can be associated with a row of the
constraint model.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a model that keeps track of a list of filter constraint and makes
them accessible from Qt. Sadly, this is mostly repetitive boiler-plate
code, but this is due to Qt's model/view-API, which is a perfect example
of how *not* to design a reasonable modern API.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Adds a filter constraint object to the core, which represents one
constraint the user can filter dives with. The plan is to write these
constraints to the XML and git logs. Therefore, this code is written
in C-style except when it comes to handling strings and dates, which
is just too painful in plain C.
There is one pointer to QStringList in the class, though when compiled
with C, this is simply transformed into a pointer to void. Granted,
that smells of an ugly hack. However it's more pragmatic than
self-flaggelation with C string and list handling.
A filter constraint is supposed to be a very general thing, which can
filter for strings, multiple-choice lists, numerical ranges and date
ranges.
Range constraints have a range mode: less-or-equal, greater-or-equal
or in-range. Text constraints have a string mode: startswith, substring
or exact.
All the data are accessed via setter and getter functions for
at least basic levels of isolation, despite being written with
a C-interface in mind.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
So far, the fulltext-query structure only saves an canonicalized
upper-cased version of the query. However, if we want to save the
fulltext query to the log (filter presets) or want to restore an old
fulltext query, we have to store the original query. We don't want
to confront the user with the mangled upper-cased version.
Therefore, also save the original version.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To support the new filter code, add helper functions that turn timestamps
into year and day-of-week to core/time.c.
Internally, these functions simply call utc_mktime() to break down the
timestamp and then extract the wanted value. This may appear inefficient,
but testing shows that modern compilers are quite effective in throwing
away the unneeded calculations. FWIW in this respect clang10 outperformed
gcc10.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The cylinder model is used both in the planner and the
equipment tab. We have three preferences for the pO2 that
is used to compute MOD: In the planner, there is one for
the bottom part of the dive and another one for deco.
Those are set in the planenr UI. There is another value,
controlled in the Tec Prefernces. That one should be
used in the equipment tab rather than the one from
the planner.
Fixes#2984
Signed-off-by: Robert C. Helling <helling@atdotde.de>
I think we only have one dive computer that supports GPS data right now:
the Garmin Descent Mk1. It reports the dive coordinates as "GPS1" and
"GPS2" for the entry point and exit point respectively.
Often GPS1 is missing, because the dive computer may not have gotten a
GPS lock before the diver jumped into the water, so when that happens
we'll use GPS2 for the dive site location. But when GPS1 exists, we
should prefer that.
And that's what we already did in logic in dc_get_gps_location(), but
for the initial dive site created at download time, we just picked any
divecomputer reported string that started with "GPS". And since GPS2 is
reported after GPS1 by the Garmin Descent, it would end up overwriting
the entry point that we _should_ have preferred.
Add the same kind of "explicitly prefer GPS1" logic to the initial dive
download case as we already had elsewhere.
Reported-by: @brysconsulting
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
gcc complained about two constructs of the kind
remote_id && SSRF_INFO("...");
And while I am not a fan of excessive warnings, I must say
it has a point here. That's just code obfuscation. In fact,
it appears that the condition was wrong - the SSRF_INFO
should probably be invoked if remote_id is NULL. The way
it was written it would be invoked if it was *not* NULL.
Change both instances to unfancy if statements.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The water type strings were static and therefore passed through
gettextFromC::tr() before main(). One would hope to get a warning
in such a case, but this is not the case.
Therefore, use the QT_TRANSLATE_NOOP macro to register the strings
in Qt's translation system and translate the list when needed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The clock is only valid in ascent. In each cycle of the
'critial volume algorithm' it re-initialized to the
bottom time at the beginning of deco. So the time spent
on bailout should be added to this bottom time.
Thanks to Coverty for spotting this.
Coverity-scan: CID-362079
Signed-off-by: Robert C. Helling <helling@atdotde.de>
When an undo command selected invisible dives, a current dive outside
of the list of selected dives was chosen. This could have the very
unfortunate effect that the current dive was set, though not selected.
From an UI point of view this meant that the dive was displayed, but
edits would not be registered.
Change the setClosestCurrentDive function to select the current dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For Android the Qt Bluetooth code seems to work just fine. And for macOS
nothing appears to work right now, but at least the Qt implementation compiles
and links.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The Qt based implementation apparently got broken at some point and now fails
to connect to rfcomm dive computers like the Shearwater Petrel.
This uses the libdivecomputer rfcomm backend. Tested to work with bluez on
Linux as well as with the native Windows implementation.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
At least Shearwater Cloud seems to use multiple formats for sample time
recorded in the database. Sometimes the time is in seconds, sometimes in
milliseconds, and sometime it is something I have no idea about. Thus
switching to calculating the sample id myself and using sample interval
to calculate the actual sample time. Seems to be more reliable than
trying to guess what format Shearwater is using for this specific dive.
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
ExifTools (and probably other meta-data editors) modifies the
mvhd creation date, but leaves the individual creation dates
in the tracks unchanged. Therefore, use the mvhd atom.
Reported-by: Eric Tanguy <erictanguy2@orange.fr>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This extends the uuid matching to the low-level characteristics too, so
that we can ignore the McLean Extreme characteristics that aren't
interesting.
It also renames the uuid matching to be about a "uuid_list" rather than
being about the service we're matching, since we're now using it for
other uuid's than just services.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Silly typo with a missing 'i' in 'uuid' that happened when I wrote this
code originally, and that compiled fine thanks to the error being
duplicated with cut-and-paste to all relevant places.
Fix it now, since I'll extend the uuid matching to the actual
characteristics for the McLean Extreme.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
It turns out that contrary to what the documentation states, a few languages
are still only using the 'qt' translation. But those exist for all languages,
so we need to first search for the 'qtbase' translations, and only if that
fails do we try to load the 'qt' translations.
And even that will fail for languages in which Qt simply isn't localized (like
Dutch).
To make the code more readable, the check for 'US English' was moved earlier as
there is no point to look for a Qt translation for that (simply doesn't exist).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We were still using the 'qt' translations instead of 'qtbase' as we should have
been using since forever - it's a little unclear from reading the documentation
when in the Qt5 life cycle this happened, but definitely several years ago.
These are the strings used in situations where Qt already provides us with text
(e.g., the entries in the 'Subsurface' menu on Mac, or the button labels in
many dialogs).
Additionally we didn't try hard enough to find those translations in cases
where they are bundled with the app; so basically all scenarios except for
Linux distro specific packages or 'build from source' on macOS or Linux were
not going to work, even after addressing the qt->qtbase conversion.
But of course the developers pretty much all fall into those last two
categories. Still, I cannot believe we never fixed this in all those years...
To make it more obvious if we still aren't finding the Qt translations this
commit also makes that warning be shown in all cases, not just when running in
verbose mode.
Fixes#2954
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The logic to retrieve gas changes from Shearwater cloud database is
detecting only when the O2/He chnages. This change will grab the initial
gas. (Problem was only shown when there was a gas changee in the log, so
cingle cylinder dives were working fine.)
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Gas change is done to the cylinder we just found and not the last
cylinder. Also switching the variable name to index as we are actually
using that value outside the loop.
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
Shearwater apparently stores correct pressures nowadays, so getting rid
of a hack to import double pressures.
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
This will ignore the gas changes that would be caused by Shearwater
cloud saving rows with 0 values in them.
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
A sample log I received contains a lot of rows with 0 values in it. This
will ignore the obviously bogus ones. (However, we might miss the first
sample if that is recorded at time 0.)
Signed-off-by: Miika Turkia <miika.turkia@gmail.com>
core/device.h was declaring a number of functions that were related
to divecomputers (dcs): creating a fake dc for manually entered dives
and registering / accessing dc nicknames. On could argue whether
these should be lumped together, but it is what it is.
However, part of that was implemented in C++/Qt code in a separate
core/divecomputer.cpp file. Some function therein where only
accessible to C++ and declared in core/divecomputer.h.
All in all, a big mess. Let's simply combine the files and
conditionally compile the C++-only functions depending on
the __cplusplus define.
Yes, that means turning device.c into device.cpp. A brave soul
might turn the C++/Qt code into C code if they whish later on.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The functions matchDC() and matchModel() were never implemented.
Remove their declarations.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function *looks* like it is a dive function. However, in reality
it implicitly works on the global device list. Therefore, it is
thematically more aptly located in device.h with the other device
functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The SAC factor is only used for minimal gas calculations which
don't make sense in the CCR context.
Additionally, make bailout stop for at least minimum switch
time or problem solving time.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
In a previous commit, auto-filling of weight based on type was
changed to be only performed if the user hadn't already set a
weight, by testing for weight=0.
However, when the user edited the type and tabbed back and forth,
that counted as an edit and therefore the weight would not
change anymore.
To refine this, introduce an "auto_filled" flag to the weightsystem,
which is set if the weight is automatically filled and cleared if
the weight is edited. Update the weight if it was zero *or* auto-filled.
The flag is not saved to disk, but that should be acceptable. If the
user saves and reloads, we can assume that they meant the weight
to be set to the default value.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The function was called on a freshly copied dive, which has its git cache
invalidated automatically in copy_dive().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
delete_divecomputer had legacy code, which
1) invalidated the git dive cache
2) made sure that the dive computer was not displayed anymore
However, both callers called on a freshly copied dive, which
has its dive cache invalidated in copy_dive() and can't be
the currently displayed dive. Therefore, this code is dead
code and can be removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is a number_of_computers() function which does
the same thing with two exceptions:
1) checks for null-dive
2) returns an unsigned int
Replace calls to count_divecomputers() by calls to number_of_computers().
In one case, the return type makes a different - add a cast to int there.
Ultimately, we should probably change the dc_number to signed int
throughout the code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This helper function is not used outside taxonomy.c anymore.
Let's hide this implementation detail.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of getting the index and using that to access values, use
the taxonomy_get_value() helper function. Two places are affected:
1) reverse geo-lookup
2) location filter delegate
The behavior of reverse geo-lookup is changed slightly: now an
empty string is likewise recognized as missing "TC_ADMIN_L3".
Before, only a missing category was interpreted as such.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is the counter-part to taxonomy_set_value(). Let taxonomy_get_country() be the
first user of the function. If a category doesn't exist, return NULL.
Small addition: make taxonomy_get_countr() take a const argument.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
get_dive_country() was essentially a reimplementation of taxonomy_get_country().
Let's just use the already existing function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of recoding the "search for category" loop, reuse the already
existing functionality.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The alloc_taxonomy()/free_taxonomy() interface was exceedingly strange.
The former gave a "struct taxonomy", the latter took a "struct taxonomy_data".
To make things worse, is appears as if the names "taxonomy" and "taxonoma_data"
are reversed: the latter contains the former.
In any case, the alloc_taxonomy() call is not needed anymore from outside
taxonomy.c, as these memory-management details are now hidden in accessor
functions. Therefore, make the function local to taxonomy.c. Moreover,
rename it to "alloc_taxonomy_table()" and let it take a "taxonomy_data"
structure for symmetry with "free_taxonomy()".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of manipulating the taxonomy structures directly, use the
taxonomy_set_category() function. This improves encapsulation and
gives us the possibility to improve the taxonomy data structures.
This concerns three places:
1) git parser
2) XML parser
3) reverse geo-lookup
This improves the XML parser code slightly: The parser assumes that
the value-attribute comes last (after origin and category). While
it still does that, it now at least generates a warning if it encounters
a value-attribute without origin- or category-attribute.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These functions were taking a const char *, yet taking ownership
of the value. Moreover, taking ownership of strings is rather
unusual in C-style APIs. Let's copy the string instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Setting a taxonomy category was cumbersome: the caller had to
make sure that the category-table was allocated. Introduce
a helper function to make that simpler.
Make taxonomy_set_country() the first caller of the new function,
since it is just a special case with category = TC_COUNTRY.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When overwriting a country, the old string was not freed. Fix this.
Contains an unrelated coding-style fix: use braces if code block
contains more than one line.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This adds a common macro to convert salinity (which is
given as a density in terms of g per 10l) to a specific
weight with units of mbar / mm = bar / m that is used
to translate between pressures and depths.
The weired factor of 10 (from the unusual unit of salinity)
is included in the macro. It is there for historical reasons,
as it goes back to 05b55542c8 from 2012 where it was introduced
in code for downloading from Uemis dive computers.
Now, salinity appears in too many places to easily remove
this unconventional factor of 10 everywhere without breaking
to many things (including various dive computer downloads).
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Some remote dive sites have no populated places (towns, cities)
nearby. For such sites, we now fall back to looking up
unpopulated place names, such as the reef or island name.
Also some code refactorisation:
the actual network access is now encapsulated in its own
function removing some duplicated code handling in the
reverseGeoLookup function and making it more readable.
Furthermore, reverseGeoLookup() was completely refactored as
most of its functionality was due to legacy requirements; the
current code-base only calls this function from a single
location and only with an empty taxonomy_data object. This
makes the function more focussed and much simpler and more
readable.
Finally, a resource leak in reverseGeocde introduced in
4f3b26f9b6 was fixed.
Signed-off-by: Michael Werle <micha@michaelwerle.com>
Dives for the seac action computer are imported by the seacsync
program into two tables in an sqlite3 database.
The dive information is read from the headers_dive table.
The dive_data table is then queried for each dive to get samples.
The seac action computer is the only current supported computer
by the seacsync program. It only supports two gas mixes, so the
parser will toggle between two cylinders whenever it detects a
change in the active O2 mix.
Dive start time is stored in UTC with a timezone offset.
A helper function to read this was added to qthelper.
Default cases have been added to some switch statements
to assist in future development for other dive types and
salinity.
Example database has been added to ./dives/TestDiveSeacSync.db
Signed-off-by: James Wobser <james.wobser@gmail.com>
We don't really expect to get Nº of dives greater than the biggest
integer value.
Signed-off-by: Salvador Cuñat <salvador,cunat@gmail.com>
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
WLog is a Win32 based ancient shareware program whose target was:
1) fully support divelogs coming from DataTrak (DOS or Win)
2) fill some meaningful data which wasn't supported by Uwatec software
3) have a more user-friendly GUI than Datatrak had
The problem achieving goals 1) and 2) at the same time was solved by
adding a complementary file with .add extension and - mandatory - same
base name than .log file (including directory tree).
This .add file has a fixed structure composed of a 12 bytes header,
including file type check and Nº of dives following; then a fixed 850
bytes size for each dive in the log file. Data fields size and position
are fixed inside these blocks and heavily zero padded, so they are easy
to parse.
A serious restriction imposed to the WLog user was *Do not edit the logs
with other software than Wlog*; this was due the order of dives in .log
file being the same than the order of dives in .add file. Thought you
could show a WLog divelog in Datatrak, editing it resulted in mixing all
extended data for dives following the edited one.
Thus, we have to trust files are correct and is to the user ensure this
is so. If extended data are mangled, they are mangled in WLog too and we
are not trying to fix the mess, just importing.
On the technical side, we try to be smart about tank names as neither
DataTrak nor WLog record them. So we just take the first tank in users
list matching the volume recorded in WLog.
For weights we add a translatable "unknown" string as an empty string
results in weight not being shown in subsurface-mobile (which could be a
reportable issue, BTW).
Signed-off-by: Salvador Cuñat <salvador.cunat@gmail.com>
When the dive has no explicity salinity, our conversion
between pressure and depth assumed salt water. Make this
explicity by using the corresponding macro.
When the planner starts and no salinity is set explicity,
set the water type chooser to salt water to reflect
our default assumption.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
While this code was added as I was trying to work through issues with a BLE
stack that turned out to be broken, the failure behavior of that device showed
that Qt doesn't like it when we start discovering the details of
characteristics while it is still busy discovering services.
So instead of handling the services as we find them, let's instead wait until
we are done discovering services and then discover the details for all those
services.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
There is no need to continue to look, and at least with the Shearwater
Peregrine having the scan run while we are trying to discover characteristics
appeared to cause issues.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
I can no longer reproduce the case where this rescan was necessary.
So let's remove it as it causes additional wait time for BT/BLE users on macOS.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
get_cylinder(d, i) is more readable than d->cylinders.cylinders[i].
Moreover, it does bound checking and is more flexible with respect to
changing the core data structures. Most places already used this accessor,
but some still accessed the cylinders directly.
This patch unifies the accesses by consistently switching to get_cylinder().
The affected code is in C++ and accesses the cylinder as reference or
object, whereas the get_cylinder() function is C and returns a pointer.
This results in funky looking "*get_cylinder(d, i)" expressions.
Arguably still better than the original.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The libdivecomputer internals changed for USB devices, and now we need
to scan the USB devices before calling libdivecomputer. That's the same
pattern as for USBHID and IRDA, so let's just regularize this all.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
getFormattedCylinder() is a helper function to format a list
of cylinders. It had that weird logic that it would skip
cylinders without description unless it is the first, which
would instead be written as "unkown".
The reason was the old statically sized cylinder array,
where it wasn't clear if a cylinder was actually in use.
This became obsolete when switching to a variable size
cylinder array. Firstly, all cylinders in the array were added
by the user. Secondly, we now also support dives without
cylinders, i.e. the first cylinder is not any different from
the rest.
Thus, remove the logic and format any cylinder without
description as being of type "unknown".
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This adds the Oceanic Veo 4.0 & Pro Plus 4, the Sherwood Wisdom 4 and the
Tecdiving DiveComputer.eu to our list of known names.
The Oceanic Pro Plus X detection is simply moved to have the other names
in a more logical order.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
0249e12 split up the dive import logic in multiple steps. Thereby,
the one of the conditions for renumbering the imported dives (is
the last old dive numbered) got messed up: The first number of the
new dive was compared to the total number of old dives, which makes
no sense.
- Simply check for the number of the last existing dive (if any).
- Don't remember the number of old dives - the original table is
not modified anyway.
Fixes#2731
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We are usually showing pressures with localized group separator. And we made a
total mess out of things when then re-parsing those values. This caused us to
ignore start and end pressures in Subsurface-mobile when those were entered in
psi and included a group separator:
2,900psi was turned into 2.900psi which we then rounded to 0 mbar.
This fixes the problem by asking Qt to do the right thing instead of doing
stupid separator magic.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The merge_events() function was subtly and not-so-subtly broken in a
couple of ways:
- in commit 8c2383b49 ("Undo: don't modify source-dives on merge"), we
stopped walking the event list after we merged the first event from a
dive when the other dive computer had run out of events.
In particular, this meant that when merging consecutive dives, the
second dive only had the first event copied over to the merged dive.
This happened because the original code just moved the whole old list
over when there was nothing left from the other dive, so the old code
didn't need to iterate over the event list. The new code didn't
realize that the pointer movement used to copy the whole rest of the
list, and also stopped iterating.
In all fairness, the new code did get the time offset right, which
the old code didn't. So this was always buggy.
- similarly, the "avoid redundant gas changes" case was not handled for
the "we ran out of events for the other dive computer" case.
This fixes both issues.
Cc: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
gettimezoneoffset() returns incorrect values when called with a time_t.
Since we only accept the value here if it is within 5 minutes of 'now',
using the current timezone offset is a fair approximation.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For some reason we suddenly started logging the GPS fixes in UTC instead
of local time. Which caused the matching algorithm to fail (unless you
happened to be diving in UTC). Unclear what broke this, but this seems
like an easy enough fix, since the GPS fix being reported is by
definition "right around now". So using gettimezoneoffset() with the
current time seems "good enough".
I don't know when gettimezoneoffset() with an argument got broken, TBH.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
A while ago, we introduced a preference whether O2 should
be considered narcotic. We used this when computing
best mix or when entering the He content via MND. But
we forgot to make the displayed MND depend on this
preference. This patch add this.
Fixes#2895
Signed-off-by: Robert C. Helling <helling@atdotde.de>
When removing the MAX_CYLINDERS restriction, the layout of the
pressure readings was changed from a (cylinder,sample) to a
(sample,cylinder) scheme. I.e. previously there were one cylinder
block for each sample, then one sample block for one cylinder.
However, after populating the samples, the array size was reduced
to the actual number of used samples. With the new layout this
breaks indexing. Therefore, restore the old layout.
Fixes#2887
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We did something really horribly wrong when merging cylinders. It's
been broken since commit 7c9f46a ("Core: remove MAX_CYLINDERS
restriction"), and used some really strange logic.
This rewrites the logic to be (I think) a bit more easy to understand.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This updates libdivecomputer to support the Oceans S1 and McLean Extreme
divecomputers.
It also adds the Oceans S1 to the list of dive computers we reconize by
bluetooth name.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Having the full list of all members in the exact order should be enough to get
g++ to accept the named initializers.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The last time those changed, we forgot to update serial_ftdi. In that change
set_latency had been removed from libdivecomputer and poll and ioctl had been
added. This caused the callbacks to no longer be aligned correctly and the
functions were called with the wrong arguments through the wrong function
pointers, leading to crashes.
Instead of the fragile assumptions about order and type of function pointers,
use named initializers. And while we are at it, fix that for the bluetooth
implementation as well.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For unknown reasons, the dive site and trip to be parsed into were
passed as pointers to pointers. A simple pointer seems to be enough,
since the object is not allocated by the function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This may seem like a bit heavy handed as it adds more global state, but given
the number of ways in which attempts to sync with the cloud can fail it seems
much more reliable to claim success in the spots where we actually know that we
have successfully synced with the remote server. Transporting that information
back through the various call chains turned out to be very disruptive and ugly,
so I went with global state instead.
Whenever we access cloud storage (or any git repo), we always first check if it
actually is a git repo by calling is_git_repository() - so this is the perfect
spot to initialize the variable to false.
And there are only two spots where we either clone the remote repo
(create_local_repo()) or update the remote with the (potentially merged) local
changes (check_remote_status()). So those are the two places where we set the
variable to true.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In many cases we did not log the issues the code ran into to stderr which made
remote debugging user problems much harder. This hopefully will help with that.
Since I was looking at the code, I also made the existing messages more
consistent.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Apparently libdivecomputer can return DC_GASMIX_UNKNOWN when
fetching tank info with
dc_parser_get_field(parser, DC_FIELD_TANK, i, &tank);
This caused emission of a warning, which was annoying users.
Disable the warning in that case.
Fixes#2866
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The last caller was removed in 7eb422d988.
Since this is the only caller of dive_within_time_range(), remove that
function as well.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In analogy to the timestamp -> QDateTime conversion, create a
common function.
1) For symmetry with the opposite conversion.
2) To remove numerous inconsistencies.
3) To remove use of the deprecated QDateTime::toTime_t() function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Move this function from maintab.cpp to qthelper.cpp. Since the
functionality was used in numerous places, use the helper function
there as well. This removes a number of inconsistencies. For example,
sometime setTimeSpec(Qt::UTC) was called, even though the
QDateTime object was already created with that time spec.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The short and long date formats where initialized in a common if-branch.
However, inside the if-branch the code rechecked which of the two should
be initialized. This could make sense if there was some common code between
the two, but there wasn't. Therefore, make this two independent branches
to avoid one nesting-level.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a couple of known services (Scubapro G2 and Shearwater), and update
the names of others that turn out to be used for multiple dive
computers. Also add another Broadcom upgrade service UUID.
While at it, sort the services numerically to make it easier to see that
a UUID already exists, since these service numbers do get used across
multiple different devices.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We've tried to do this "automagic" service discovery, and it mostly
works, but then occasionally it doesn't.
Making things worse, I think different platforms end up enumerating
services differently, so our "pick the first service that looks like it
might be a serial service" ends up working on some platforms, but not
necessarily on others. Because "first" might be different.
So start a list of known good/bad services - and fall back to the old
logic when you can't decide reliably.
This fills in juat a few cases that I can easily check myself, and the
"details" field for them may be incomplete. For example, I know Nordic
Semiconductor has their vendor-specific UUIDs, and they can be found in
different devices, so calling them "Nordic UART" and "Nordic Flash"
services makes sense.
But the "Scubapro i770R" service? It might indeed be specific to the
Scubapro i770R. Or it might be a general service UUID that Pelagic
uses. Or it might be the service UUID of a particular chip, and found
in dive computers from other designs too (and not necessarily in all
i770R's either).
So this is a preliminary first stab at this, and I'm sure we'll extend
the list and possibly improve on the explanations.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
The old code used get_taglist_string() and split the resulting
string at commas to get the list of tags. This was wrong for two
reasons:
1) It was buggy. Every tag but the first would start with a leading
space and thus not be found.
2) It was inefficient. The tag list was concatenated, just to be split
again.
Turn the tag list directly into a QStringList and remove whitespace
for good measure.
Fixes#2842.
Reported-by: Hartley Horwitz <hhrwtz@gmail.com>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We don't order the list of addresses alphabetically, but we want to ensure
that devices that offer us a name are listed before those that don't. This
should only be relevant if the user selects the option to show all BT/BLE
devices, not just recognized dive computer, because if we recognize a computer
we always have the product name prepended to the address.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If the user asks to have all BT/BLE devices shown, we should behave
consistently to the case of a recognized dive computer and always show the
device name. In almost all cases the BT/BLE address (and even worse on
iOS/macOS the weird uuids) are completely meaningless.
If there isn't a name, don't add a leading space in order to make it easy to
detect if we have an address without a name (which almost certainly isn't a
dive computer, so it should be towards the end of the list of addresses - which
will be handled in a later commit).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This fixes a rather subtle bug.
In btdiscovery.cpp we are detecting dive computers based on their BT name and
are setting up product+vendor as the key for that lookup. QMap always uses case
sensitive comparisons and a tiny inconsistency snuck into our code.
libdivecomputer names for the Aqualung dive computers i200C / i300C / i550C end
in an upper case C (as matches the official branding), but in btdiscovery.cpp
we have those names with lower case c. And therefore didn't recognize these
dive computers.
Obviously this is easy to fix by fixing those three strings, but I decided that
it was silly to set ourselves up for similar oversights in the future. So
instead I switched the matching of the descriptor to simply be allways all
lower case.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We do _not_ read them back, since they are calculated values, although I
guess we could aim to do that too at some point in case we have an
import from somewhere else that has these values but not the profile (or
gas use) to actually calculate them.
Fix test-cases that are checked by TestParse (but nothing else) to match.
Requested-by: Miika Turkia <miika.turkia@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This warning is unnecessarily scary - we had a problem with parsing
multiple strings on the same line, but it should be all solved, and
while it does mean that people may have old incorrect git save files
with empty strings, scaring users about it isn't going to help.
And with the warning removed, we can just remove the whole test for an
empty string, because the normal code sequence handles that case just
fine.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
To reset the core data structures, the mobile and desktop UIs
were calling into the dive-list models, which then reset the
core data structures, themselves and the unrelated
locationinformation model. The UI code then reset various other
things, such as the TankInformation model or the map. . This was
unsatisfying from a control-flow perspective, as the models should
display the core data, not act on it. Moreover, this meant lots
of intricate intermodule-dependencies.
Thus, straighten up the control flow: give the C core the
possibility to send a "all data reset" event. And do that
in those functions that reset the core data structures.
Let each module react to this event by itself. This removes
inter-module dependencies. For example, the MainWindow now
doesn't have to reset the TankInfoModel or the MapWidget.
Then, to reset the core data structures, let the UI code
simply directly call the respective core functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This one is a bit hairy, because two things might happen if the
picture has a geo location:
- A dive gets a newly generated dive site set.
- The dive site of a dive is edited.
Therefore the undo command has to store keep track of that.
Oh my.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Move the two functions create_picture() and picture_check_valid_time()
from dive.c to picture.c.
This might be somewhat questionable, as these functions are not purely
picture related, but check the nearest selected dives, etc. However,
dive.c is so huge, that slimming it down can't hurt. Moreover,
getting the nearest selected dive is more divelist- than dive
functionality anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If we want to make addition of pictures undoable, then create_picture()
must not add directly to the dive. Instead, return the dive to which the
picture should be added and let the caller perform the addition.
This means that the picture-test has to be adapted.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We can do the same with get_picture_idx(). Yes, it is a bit more
unwieldy. However a full reimplementation seems not worth it.
We could make this a one-liner helper function though.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The code is rather complex. Firstly, we have different representations
of pictures throughout the code. Secondly, this tries to do add the
pictures in batches to the divepicture model and that is always rather
tricky.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
By using a std::string instead of a C-string, memory management
becomes so much simpler! This class will be used for keeping track
of deleted/added pictures in the undo system.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Even though the functionality is seemingly trivial, this is a bit
invasive, as the code has to be split into two distinct parts:
1) Post undo command
2) React to changes to the divelist
Don't compile that code on mobile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This needs a slight change to the macro, because here we sort by
value type. Yes, from a C-programming point of view this is horrible,
however a decent compiler should just inline everything and not
pass around value types.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
A function that gets the index of a picture in a picture table
given its filename. Since we are going to identify pictures by
their filename, we will need this function in the undo code.
Use the function in the remove_picture() function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For consistency with equipment, use our table macros for pictures.
Generally tables (arrays) are preferred over linked lists, because
they allow random access.
This is mostly copy & paste of the equipment code.
Sadly, our table macros are quite messy and need some revamping.
Therefore, the resulting code is likewise somewhat messy.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since this doesn't touch struct dive, dive.c is not an appropriate
place for this function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The Bühlmann factors were cached in a thread-safe hashmap. It seemed
somewhat dubious that entering a critical section and doing a hash-lookup
would be significantly faster than a simple exp() call.
Indeed, in a very cache friendly test (16 entries, tight loop) calling the
factor() function 32 000 000 times from a different translation units we get:
- with cache: 604 ms
- without cache: 266 ms
Therefore, remove the cache. Given that 32 000 000 calls take only 266 ms,
it appears not sensible to try to optimize this function anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
It was suggested in a review of a previous patchset that we should
capitalize the use of "use dc" to "Use DC" - but if we were going
to do that we should do it everywhere, not just in the one place.
This is the followup to do that.
Signed-off-by: Monty Taylor <mordred@inaugust.com>
In the code, the difference between SALTYWATER and SALTWATER is hard
to see. More importantly, in the UI - Brackish is the word for water
that has more salt that freshwater but less salt that seawater. The
docs already use the word to clarify what is meant.
These can be useful in a printed divelog, especially if the
log entry is also showing weight and exposure suit.
Signed-off-by: Monty Taylor <mordred@inaugust.com>
The DiveListView had a singleSelectedTrip function that
returns the selected trip if exactly one trip is selected.
This could be very slow if numerous non-trip items were
selected, because all the selection indices were back-
translated by the proxy model.
This could make selection changes very slow, because the
MainTab used said function to determine whether it should
show trip or dive data.. Indeed, with a 3500 dive test log,
when selecting all dives in tree mode, the updating of the
TabWidgets is sped up from 130 ms to 5 ms this commit.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The DiveListView would touch the selection-innards directly.
Let's encapsulate that. Moreover, take care to reset the trip
selection when resetting the core data.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In analogy to dives add a selection flag for trips. The reason
being that search for a selected trip can be painfully slow when
we do it through Qt's proxy model.
Make sure to deselect trips when they are removed from the core.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
No point in slurping in all of dive.h for translation units that only
want to do some time manipulation without ever touching a dive.
Don't call the header "time.h", because we don't want to end up in a
confusion with the system header of the same name.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This included QFile, which is fatter and not needed here. Include
QFile only in the actual translation unit.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There appears to be no reason to slurp in all dive.h when compiling
membuffer.c. units.h might not seem like the perfect place, but it
is the most fitting I found.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For consistency: declare enumerate_dives as extern, since we do that
for all other C-functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
No external caller of this function exists. Moreover, turn the return
type to void, as it only returned the passed-in plot_info and no
caller used that.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
It make debugging much easier if the function signature tells you
that a parameter is not altered.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When plotting profiles with surface segments, there were strange
artifacts. As we found out with Robert, these were due to the fact
that the calculated maxtime was set to the last event which is just one
second inside the surface segment. This terribly confused the profile
code. For example, it didn't properly allocate samples for the surface
segment.
Thus, when calculating maxtime, consider the last sample beyond the
last event.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When we had fixed-sized cylinder arrays, the planner used the last
empty cylinder for "surface air". This was not recognized by the UI
as a separate cylinder, because "empty cylinder" was the sentinel for
the end of the table. The conversion to dynamically sized cylinder
tables broke this code: everytime the surface segment is changed,
a new dummy cylinder is added, which is visible in the UI.
As a very temporary stop-gap fix, emulate the old code by creating
a cylinder and then setting the end-of-table to before that cylinder.
This means that we have to loosen the out-of-bound checks.
That's all very scary and should be removed as soon as possible.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This will be temporarilly used by the planner to mark consumption of
air at the surface. Do this by creating a new function add_cylinder,
which replaces add_to_cylinder_table() and takes care of always adding
a dummy cylinder at the end of the table. Make the original
add_to_cylinder_table() local, so that it cannot be accessed anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was used by the divelist to check wether a selection change is
programmatical or user-initiated. However, since there is only one
entry point for programmatical selection changes, this is not needed
anymore. Remove it - this removes an inter-module dependency.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We no longer use libusb to access USB devices on Android, therefore
there's no point including libusb in our build. Also, we have never even
attempted to run the tests on Android, so let's not even pretend to
support building them.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Move this to the core so that desktop and mobile don't have
to call this explicitly. Matter of fact, mobile didn't call
this. It is unclear, whether that was even used on mobile,
though.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
It makes no sense to keep the device nodes if all the other data
is cleared. Let's do this automatically and not explicitly.
This ensures that the function is also called on mobile.
Currently it was only called on desktop.
Weirdly, the parser-tests were expecting that the device nodes
were not reset by clear_dive_file_data() and therefore divecomputers
were accumulating in the test results. Thus, the additional
computers had to be removed from the expected test results.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The filter sets the maximum date to now. This is so confusing when
you manually add a dive and it isn't shown, because it is slightly
in the future. Add seven days, that should help.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This only checks the first divecomputer as the semantics for
multiple dive computers with different dive modes are not
clear. Should we check them all?
The implementation is a bit hackish: the indexes [0...n] of the
combobox are mapped onto [-1...n-1], where -1 means don't filter
and n-1 is the last valid dive mode.
Implements #2329
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Arguably, returning 0 for a dive with no cylinders is wrong, since the
0 is a valid cylinder id, however that cylinder doesn't exist. Instead,
return -1. All callers of explicit_first_cylinder() return early anyway
for dives with no cylinders.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since we removed MAX_CYLINDERS, we have the possibility of dives
with no cylinders. In such a case, setup_gas_sensor_pressure()
would do invalid read- and write-accesses. Therefore, return
early in such a case.
Reported-by: Chirana Gheorghita Eugeniu Theodor <office@adaptcom.ro>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Turns out that at least on Android libgit2 sometimes rejects valid
certificates. And I cannot quite figure out when and why. But since we
actually already checked the validity of the certificate when we called
canReachCloudServer() (and the Qt code handles certificates correctly),
we'll simply ignore this here and override the check to always return
true for our cloud server.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
I would have bet money that Android used to send stderr to the logcat
log, but apparently it doesn't (anymore?). So in order to be able to
have a chance to debug weird cloud storage issues on Android, let's do
some wholesale replacement of fprintf(stderr,...) with our own version
of the INFO macro that we long ago borrowed from libdivecomputer (and
rename it to ensure we don't have a conflict there).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
free_plot_info_data() freed the pressure-data, but didn't set the
value to NULL. Thus, when the plot_info was reused, a double-free()
could ensue.
Crash condition: export the profiles of multiple dives with pressure
data.
Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This will be used by the test to clean up test branches that are created
on the server. Since we aren't testing that functionality (it's not
something that Subsurface itself ever does) the helper prints out errors
it encounters, but doesn't report them back to the caller.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If you had one of the unfortunate local git caches with a local HEAD
just pointing to 'master', this will make note of that and then fix it
up to use the proper branch name in the cache repository.
[Dirk Hohndel: demoted from error to fprintf as most users won't care]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In create_and_push_remote(), we set up the remote tracking etc to use
the proper branch name, but never actually set up the initial local
branch for the new cache repository at all. So the repository would end
up with the default 'master' branch, instead of the branch name it
should have.
This went unnoticed, because most setups start by initializing the git
caches by cloning from the cloud, and that worked fine.
Debugged-by: Dirk Hohndel <dirk@hohndel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This fixes a crash: when the undo commands removed a dive from
the list, the fulltext cache was not cleared. If now the divelist
is reset and then the undo-command deleted, deletion of the owned
dive tries to remove it's fulltext cache, which doesn't exist
anymore.
For reasons of symmetry, when readding the dive, its fulltext
has to be registered.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When initializing the fulltext-cache and the dive-list, every
100 dives a notification was shown. I had a feeling that this
made startup significantly slower, but that could have been
purely psychological.
Therefore I measured and indeed, removing the fine-grained
notification, it becomes *significantly* faster. For a 3500
dives test log with mobile-on-desktop:
Initialization of the fulltext: 1350 ms -> 730 ms (-46%)
Initialization of the divelistmodel: 689 ms -> 113 ms (-83%)
Let's remove the fine-grained notification. There *is* a visual
indication of work-in-progress anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The compiler complained about this and it seems the
function does not need it.
Additional-test-suggested-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Robert C. Helling <helling@atdotde.de>
The planner does not know about events except gas
changes. But if the dive comes from the log, we
should preserve the dive computer events. At least
those that happend before we started to delete
waypoints to let the planner take over.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
This fixes a bug: when deleting a picture when multiple dives
were selected, possibly the wrong dive was invalidated.
Thus, the dive wouldn't have been saved to the git repository.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This isn't really a useful performance improvement, but it's still better,
IMHO, because we don't have a less specific match later on potentially change
an already executed match.
Because of our coding style the comment covering multiple cases of Pelagic dive
computers now is associated just with the first of those entries. I don't see a
way to do this differently without being in violation of our coding style, so
I'll just keep it like this.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Both Shearwater Petrel and Petrel 2 identify as 'Petrel' as their BT and BLE
names. But only the Petrel 2 supports BLE, thus only the Petrel 2 shows up in
the list of known dive computers on iOS (which supports only BLE but not
BT-only). By switching this around to always pick Petrel 2 we now correctly
detect such a dive computer on iOS.
Fixes#2739
Reported-by: Rick Holcombe <wrh@nc.rr.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Qt hates empty ranges, and even for a non-empty range, this is better
implemented as a reset than a remove.
This fixes a crash that I have been able to create on iOS by rescanning
for devices on the download page.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
There is the free_picture() function with the same functionality.
The compiler/linker should recognize that and remove the duplicate
code, but still...
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This never made sense and I think I just forgot to complete this code
when I first worked on it. Now we can see which version of Subsurface or
Subsurface-mobile created a merge.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
While having the local user information in the repo on Linux seemed
clever when we implemented it, it's inconsistent with all the other
platforms. Let's just not do that unless the user has indeed set
a global name/email pair for git.
Instead indicate if this was Subsurface or Subsurface-mobile.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This function was not meant to be called with already existing data.
However, if it was, it cleared the words without clearing the fulltext
caches of the dives. This lead to crashes.
Be more resilient by not clearing the words: Already existing dives
are unregistered during the process of populating anyway. So this
now *should* work if new dives are added to the dive list and then
this function is called.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function was named improperly: it was only used on freshly
loaded data. Indeed, attempts to use it to actually reload lead
to crashes.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
parse_file() refused to load from a git repository if we already
had that repository and there were no changes. However, this only
checked the global divelist_changed flag, which does not track
undo-commands. Thus, after editing dives the user couldn't reload
from git.
Remove this check. It is somewhat questionable that the io layer
refuses to load from a repository anyway. Let the caller decide.
There appears to be a check_git_sha function for that purpose(?).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Don't overwrite the full cylinder when editing a single field.
Implement three "modes": editing of type, pressure and gasmix.
Don't consider individual fields, because some of them are
related. E.g. you can change the gasmix by setting the MOD.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Use the user-editable MOD-pO2 preferences value when creating
a default cylinder. It is not clear to me, when that even has
a consequence, but it looks like the right thing to do.
Reported-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Apparently this was used to hide events in pre-Qt times. However,
that has already been reimplemented in different ways. Let's remove
that commented-out code.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
For undo, we want to create gas change events without adding them
immediately to the dive computer.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since all the other event-functions are also defined there.
Ultimately, we should probably move them to their own
event.c translation unit.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is a slight complexity here owing to the fact that the profile
works on a copy of the current dive: We get a copy of the event and
have to search for the original event in the current dive. This
could be done in the undo command. Nevertheless, here we do it in
the profile so that when in the future the profile can work on a
non-copied dive we can simply remove this function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Add a DiveListNotifer::eventsChanged signal, which is emitted when
the events changed. This is very coarse, at it doesn't differentiate
between signal addition / editing / deletion. We might want to
be finer in the future.
Catch the signal in the profile-widget to replot the dive if this
is the currently displayed dive. Reuse the cylindersChanged() slot,
but rename it to the now more appropriate profileChanged().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We have a remove_event() function that
1) frees the event
2) works on the current divecomputer
3) compares the events because the profile has copies of events
However, for undo commands
1) we want to keep the event so that we can readd it later
2) we have to work on arbitrary divecomputers
3) we don't work with copies of events
Therefore, create a new remove_event_from_dc() function that
does all that. Moreover, make the event argument to remove_event()
const to (slightly) point out the difference in the API.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
add_event() creates and adds an event from the given parameters.
For undo, we want to do these separately, therefore split this
function in two parts: create_event() and add_event_to_dc().
Keep the add_event() function for convenience. Moreover, keep
the remember_event() call in there, so that undo-commands can
call remember_event() once, not on every undo/redo action.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In two cases we were passing the magic value 8 instead of the
symbolic SAMPLE_EVENT_BOOKMARK. Use the symbolic version instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The cylinders in the events must be reordered if we remove
a cylinder. To avoid duplication of code, move the reordering
function into qthelper.cpp, though it might not be ideal
there.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Do a simple copy & paste followed by a simple search & replace
to generate cylinder undo commands from weight undo commands.
Obviously, this is still missing the necessary code to keep
the dive-data consistent after cylinder editing.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Moreover, move the declaration from dive.h to equipment.h.
The result is a) more consistent and b) more logical.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Turn the code in CylindersModel that creates a new cylinder for
addition into its own function to avoid code duplication. This
will be used from the undo commands.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We have a set_weightsystem() function. For symmetry, introduce
a set_cylinder() function so that we can more-or-less copy&paste
the weightsystem undo code for cylinder undo.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The cylinder undo commands will keep a copy of a cylinder
and therefore need the ability to free a cylinder object.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We have a clone_weightsystem function. For symmetry, introduce
a clone_cylinder() function so that we can more-or-less copy&paste
the weightsystem undo code for cylinder undo.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Especially on slower devices with a large dive list the startup time has
become really long. This callback allows us to give the user an idea of
what the app is doing during that time.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In an attempt to reduce the number of global variables, don't use
a local buffer to store the currently loaded git-id. The git-id
itself is still a global variable, which in the future can hopefully
be encapsulated in a "struct File" or similar.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is pointless bike-shedding: instead of allocating the QTranslators
on the heap an assigning them to a variable at translation-unit scope,
we can simply generate them as static objects.
That makes
1) two fewer lines of code
2) the translator-resources are properly released when the application
closes.
Not that either of these points would make *any* difference.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The prefs.locale.lang_locale field was overwritten without
free()ing the old value. Not that the function would be called
numerous times, but as a matter of principle...
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The uiLanguage() function was used for two purposes: to initialize
the language related preferences and to read the current language.
To make things more easy to follow, split this function in two:
one for initializing, one for getting the current language.
Moreover, don't return the current locale in an out-parameter
as there is already a function to do that [getLocale()].
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In uiLanguage() the preferences fields are initialized and there
is fixup for a MacOS indiosyncrasy. For some reason the uncorrected
value is written to the preferences. Let's store the corrected
value instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
uiLanguage() initializes the language fields from the preferences
values. It is unclear why this function is called in qPref::loadSync()
*before* the fields are loaded from disk. It can only initialize to
the default values anyway. After qPref::loadSync() uiLanguage()
is called again so that everything can be initialized with the
correct perferences values.
Remove the first call. If things break, let's fix them in a sensible
way.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This reverts commit 573a4a5e2d.
The commit broke setting the language in the desktop preferences:
Instead of setting the locale in the prefs struct, the locale
is set via qPrefLanguage. However, that saves the default language
(extracted from the system) to disk. Now when the language is
read from the preferences, we get that default value.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Adding dives uses the number of the last dive to create a new
dive number. Ignore invalid dives.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The git parser loads into the global dive table, even if it
is called indirectly via parse_file(). However, parse_file()
may be given a different table. Fix this by extending the
git parser state.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When editing a dive on mobile we might have to create a new
dive site. That site is added to the global dive site table
in the undo command. However, the code in QMLManager created
the dive site with create_dive_site*() functions, which already
adds it to the table. The undo command then added the dive
site again leading to a hang of the application.
To solve this problem, create new alloc_dive_site*()
functions that do the same as create_dive_site*()
but do not add it to the table.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The pop_cstring() function is used by the git parser to
duplicate a quoted string. On error, it returns an empty
string literal. Since the caller expects a copied string
and takes ownership of that string, it will ultimately
be freed.
Concrete example: a log with erroneous cylinder data was opened
getting such an empty string literal as description. On closing or
syncing with the cloud, the dive is freed, leading to a free
of the string literal -> crash.
Return a copy of the empty string instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of relying on the std::vector staying unchanged and not freeing
its members, instead keep a copy of the object in our DCDeviceData class.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If the user tries to download from a device that he hasn't given the app
permission to read from, Android will pop up a dialogue asking for that
permission. With this after giving the permission we continue (well,
technically, restart) the download which is likely the expected behavior.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This finally allows us to download from not just the first device, but specifically
the device that the user picks.
Passing the object through a void pointer is not nice - but since this traverses
C code other solutions (like passing an index into the list) seemed even worse.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Instead of creating a string with all the object information, simply pass
the actual object to the C++ code.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We now always create a list of usb devices that doesn't list a driver
for known devices, and adds multiple entries with each of the drivers
for devices that are unknown to us.
This removes some debugging output in the ..._open() function as well.
This could be combined with Christof's earlier commit.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For a small number of dive computers we can actually figure out the
real information which we can then later show to the user.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
As discussed in issue #2657, there are now more fields about the usb
device information in android_usb_serial_device_descriptor.
Additionally, the user-facing string now makes more sense:
"vendor [<bus# as integer>:<dev# as integer>]"
Where vendor is as reported by android, but shortened to 16 characters.
Examples:
FTDI [1:2]
Silicon Labs [1:4]
Signed-off-by: Christof Arnosti <charno@charno.ch>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit contains the serial_android_usb part of the changes proposed
in issue #2657.
What's implemented:
- A data structure that contains all the data that can be used to
describe an usb device (including user-facing string).
- A function to get a list of all attached usb devices (optionally with
selectable driver class).
- Changes in the serial_android_usb_open-function and in the Java part
to use the information about the usb device and optionally selected
driver when connecting.
This commit keeps compatibility with the current UI-Code in the case
that only one USB-Device is connected. If two devices are connected,
only the first one is tried.
There are still some small things to do:
- Change the user-facing string to something more descriptive.
- Parts which aren't uesd anymore when the UI-Part is implemented are
simply marked as obsolete (to keep compatibility for now).
But generally it seems to work.
[Dirk Hohndel: some white space / coding style adjustments]
Signed-off-by: Christof Arnosti <charno@charno.ch>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is the exact same case as the previous commit, just for the writing
side.
Once again, it's the subsurface rfcomm iostream code that can return
DC_STATUS_SUCCESS with a byte count of zero when something goes wrong
with the write.
And once again, our libdivecomputer iostream code didn't try to be
robust and protect itself from that case.
The fix is equivalent, although slightly simpler, since the write side
doesn't have the whole timeout issue.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
We had two independent bugs here, both of which needed to fire for this
to cause a problem. This fixes both of them.
The first bug was that our rfcomm code would return DC_STATUS_SUCCESS
with a zero-sized read when a timeout happened, or when the rfcomm
socket had disconnected. That makes absolutely no sense. We should
return DC_STATUS_TIMEOUT on timeout, and DC_STATUS_IO if the socket has
disconnected without any data.
The fix to this is to make the whole rfcomm iostream read logic much
simpler: there's no need to loop at all for partial results, because the
libdivecomputer iostream side will do the loop for us (and handle
partial results much better: it knows if the target backend can handle
those partial results or not).
The second bug was in our libdivecomputer iostream read() function,
which reacted very badly to this bad return value. This updates our
libdivecomputer branch to one that is more careful about things.
Reported-by: linuxcrash <albin@mrty.ch>
Debugged-by: Jef Driesen <jef@libdivecomputer.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
The diveListNotifier.divesSelected() signal is used to inform the
models of a selection change. It sent the current dive as a second
parameter. This is redundant, because the only sender of the signal
sets current_dive just before sending the signal. Remove the
parameter, which appears to be an artifact.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Grammar-nazi ran
git grep -l 'indexes' | xargs sed -i '' -e 's/indexes/indices/g'
to prevent future wincing when reading the source code.
Unfortunatly, Qt itself is infected as in
QModelIndexList QItemSelection::indexes() const
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Since I learned while trying to implement this that getting sub-second
resolution time in portable C99 is hard (especially for someone who is
used to the comfort of std::chrono and Howard Hinnants date library) the
timer-implemetation from libdivecomputer is now copied to the subsurface
source.
Signed-off-by: Christof Arnosti <charno@charno.ch>
Thanks to the new USB serial implementation also that complex special-casing
is no longer needed. This should do the right thing now.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Create a C string (which the caller needs to free) with the executed commands
in this session.
The detour via the callback allows us to not make the corelib depend on the
commands, which is nice for tests, export-html, and smtk2ssrf.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In the QML code we pass ids around. I had assumed that there already was a reverse
lookup function, but I wasn't able to find it. So I added it.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Use the undo-command for importing dives also on mobile. This should make the
whole disconnect-model shenigans unnecessary.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The goal is to send the signal for the correct dives / divesites
and thus not having to reload the whole model.
Right now the mobile UI does not yet catch the diveSiteChanged signals.
[Dirk Hohndel: small fix to ensure that we trigger a save to storage]
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This finishes the spliting of the GPS fix application:
One function for collecting the fixes, one for application.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Not that this would make any noticeable difference, but out of
principle, let's use Qt's string-literal macro for string-literals.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Make the application of the GPS fixes in two runs: first
collect dives and fixes, then apply the fixes. This will
simplify turning the application of GPS fixes into an
undo-command.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We know that we cannot support native USB, USB HID, IRDA, and USB
storage on Android.
On the flip side, don't try to force the long broken FTDI download.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Since the Android USB stack and subsequently the usb-serial-for-android
driver have problems with read-timeouts, the read-timeout is now
implemented in AndroidSerial.java. Also, DC_STATUS_TIMEOUT is returned
if there are less bytes returned than expected.
Different chipsets seem to behave differently with
usb-serial-for-android. On CP210x the read blocks until there is some
data here, but on FTDI the chip seems to return whatever is currently in
the buffer (so 0 bytes if the buffer is empty). This different behaviour
should be mitigated by the changes by this commit.
Signed-off-by: Christof Arnosti <charno@charno.ch>
Implement the libdivecomputer API in Java and create C/JNI translation
layer.
[Dirk Hohndel: whitespace harmonization - yes, some of this is Java,
this still makes it much easier to read for me;
also changed the FTDI conditional compilation to make
sure we can still use that for mobile-on-desktop if
necessary]
Signed-off-by: Christof Arnosti <charno@charno.ch>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This is a quick hack to reduce the noise in the log file when chasing other
bugs. Maybe this should not be enabled on release builds, but right now I don't
think the harm that having this in would do.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For reasons which I don't yet understand, when plotting a dive
whose first cylinder is not cylinder 0 and then plotting a dive
with only one cylinder, it can happen that for the latter
explicit_first_cylinder() returns an erroneous value.
This is due to the way in which we copy the dive to be plotted
to displayed_dive.
For now, make sure that no invalid cylinder is returned to avoid
crashes. This will have to be changed anyway, since this is very
fundamentally not thread-safe and inefficient.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The version_printed variable is used to print version information
only once. It was a global variable, but never used outside of
its function. Therefore, move it into the function and make it
static. Since this is a plain old datatype (POD), it makes no
no difference whatsoever whether the static variable is in block
scope or not. Indeed, it is initialized in the data segment). Well,
we are in C mode and therefore everything has to be POD by definition.
I tested this on gcc and clang.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>