Commit graph

717 commits

Author SHA1 Message Date
Berthold Stoeger
cd4f66014f Cleanup: Make cylinder formatting functions const-clean
In qt-models/cylindermodel.cpp the various formatting functions
can take a pointer-to-const cylinder. Thus, the data() function
can likewise treat the cylinder as const - as it should.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
4e86d99714 Cleanup: free plot data on exit
Some widgets copy the full plot info. Free these data on exit to
prevent monstrous valgrind reports.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
00289cd222 Profile: dynamically allocate plot pressure data
All accesses to the pressure data were converted to use functions.
Therefore it is now rather trivial to dynamically allocate the
pressure array and just change the functions.

The only thing to take care of is the idiosyncratic memory
management. Make sure to free and copy the buffer in the
appropriate places.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
bef1eac7fa Profile: use pressure data functions in DivePlotDataModel
The model was accessing the pressure data directly. Instead,
use the accessor functions so that the core structure can
be changed more easily.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
3025e0630d Cleanup: implement proper Qt-model semantics in DivePlotData model
User beginResetModel()/endResetModel() pairs to reset the model.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
ff653f721c Cylinders: dynamically allocate cylinder arrays
When keeping track of cylinder related data, the code was using
static arrays of MAX_CYLINDERS length. If we want to use dynamically
sized cylinder arrays, these have to be dynamically allocated.
In C++ code, this is trivial: simply replace the C-style arrays
by std::vector<>. Don't use QVector, as no reference counting or
COW semantics are needed here. These are purely local and unshared
arrays.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Berthold Stoeger
11467fa326 Core: dynamically allocate the result of get_gas_used()
get_gas_used() returns the volume of used gases. Currently,
an array with MAX_CYLINDERS is passed in. If we want to make the
number of cylinders dynamic, the function must use an arbitrarilly
sized array.

Therefore, return a dynamically allocated array and free it
in the caller.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09 19:19:04 +01:00
Dirk Hohndel
2c11544d93 Mobile: correctly update filter text and update all three models
This is even harder because setActiveTrip is called from an action slot from
QML. If the C++ code called from that slot causes the object to which this slot
belongs to be destroyed, we get very strange crashes. The only workaround I
could come up with was to update the filter asynchronously.

This all seems very ugly and fragile.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-11-08 20:50:05 +01:00
Dirk Hohndel
2c9bf775b7 Mobile: ensure the sort order is always set
This shouldn't be necessary every time we replace the sort model,
but it can't hurt, either (famous last words?).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-11-08 20:50:05 +01:00
Dirk Hohndel
6095a5f04f Mobile: add second filter proxy model for dive list
This one significantly reduces the number of dives that are handed to the
ListView in QML. For every trip that isn't expanded (only zero or one trips are
expanded at any time, so almost all the others are collapsed), send only first
dive to the View to allow creation of the section. Hide the rest so we don't
have all these invisible, zero height entries for the vertical dive list.

A big part of this commit is moving a few functions from the DiveListSortModel
to the CollapsedDiveListSortModel. Those are the ones that are needed for the
trip header.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-11-08 20:50:05 +01:00
Robert C. Helling
9c8fbe494d Planner: Add option to treat O2 as narcotic
When computing the best mix for a target depth, for helium, one
can either require that the partial pressure of N2 is the same
as at the target depth or the partial pressure of N2 plus O2.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2019-10-31 00:30:38 -07:00
Dirk Hohndel
130946fcf4 Cleanup: NULL check pointer before dereferencing
I we have no dive, whatever this is shouldn't be shown.

Found by Coverity. Fixes CID 350093

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-10-27 07:35:46 -07:00
Dirk Hohndel
08fcda60ac Cleanup: add missing break statements
The current code of course works just fine. But there's a risk someone might
add something to one of these cases and not realize that there is an implicit
fall through going on. This is cleaner.

Found by Coverity. Fixes CID 350079

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-10-27 07:35:46 -07:00
Dirk Hohndel
c9a39bb08e Cleanup: avoid resource leak in dive planner model
Found by Coverity. Fixes CID 350121

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-10-26 19:17:53 -07:00
Dirk Hohndel
4f9783ff60 Cleanup: avoid out of bounds access
This is extremely unlikely to ever happen since we reserve space for a
hundred weight models, but hey, doing this right is quite easy, so let's
fix it.

Found by Coverity. Fixes CID #350117

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-10-26 19:17:53 -07:00
Berthold Stoeger
c479c5ca36 Desktop: use undo command when replanning dive
Instead of copying the displayed dive, generate an undo command.
This makes the replanning an undoable action and fixes a bug
where the dive details have not been updated correctly.

Fixes #2280

Reported-by: Stefan Fuchs <sfuchs@gmx.de>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-26 11:36:23 -07:00
Dirk Hohndel
158a2ec159 Mobile: remove remaining accesses to DiveObjectHelper from QML
Add a couple more roles and remove the dive role that allows accesss to
the DiveObjectHelper in the first place.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-10-20 16:08:55 -04:00
Dirk Hohndel
613a3112d2 Mobile: get dive details directly from the model
By getting a DiveObjectHelper and then dereferencing that we ended up
creating hundres and hundreds of these objects, only to immediately
destroy them after using a tiny part of the data.

Instead make those data available directly from the model, without
having to create a DiveObjectHelper forst.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-10-20 16:08:55 -04:00
Berthold Stoeger
769403a4b2 Planner: copy deco state before passing it to worker thread
The planner has a computeVariations() function that can be run
in a worker thread. The code was not thread safe: a deco_state
object allocated on the stack of the caller was passed down to
the worker thread. It's well possible that the object would go
out of scope before the thread run.

Therefore, when running in the background, copy the object first
and free it in the worker thread.

Side note: Qt makes proper memory management again as difficult
as possible: You can't pass a std::unique_ptr<> to QtConcurrent::run,
because move-only objects are not supported. Not very friendly!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-20 16:20:58 +02:00
Berthold Stoeger
1e1f33c0f5 Cleanup: Make constructor of singletons private
This guarantees that they are actually singletons: there can
only be one application-wide instantiation of these objects.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-04 09:19:10 -07:00
Berthold Stoeger
3db50aedea Cleanup: Turn DiveListSortModel into classical singleton
To make this class available from QMLManager, the run_ui()
function would create the object and then set a pointer in
QMLManager. It works, but is inconsistent with the rest of
the code. Therefore, make it a classical singleton class,
which is generated on demand.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-04 09:19:10 -07:00
Berthold Stoeger
2a9a3dda20 Cleanup: turn GpsListModel into standard singleton
GpsListModel was one of those "special" singletons that could
be created explicitly with new. This would make sense if a
parameter were passed to the constructor. We only passed null,
so one might as well turn that into a classical singleton with
default constructor.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-04 09:19:10 -07:00
Berthold Stoeger
36d42a6a57 Cleanup: turn DiveListModel into standard singleton
DiveListModel was one of those "special" singletons that could
be created explicitly with new. This would make sense if a
parameter were passed to the constructor. We only passed null,
so one might as well turn that into a classical singleton with
default constructor.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-04 09:19:10 -07:00
Berthold Stoeger
2560734624 Cleanup: initialize DiveListSortModel in constructor
The model was initialized in the global run_ui() function.
Move that into the constructor of the class.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-04 09:19:10 -07:00
Berthold Stoeger
4d5acc8461 Import: remove DiveImportedModel::lastIndex
This is redundant, as the actual size is stored in the dive table.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-02 08:04:49 -07:00
Berthold Stoeger
a33f381dc6 Cleanup: remove DiveImportedModel::firstIndex
This index was never set to anything else than 0. Might as
well remove it.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-02 08:04:49 -07:00
Berthold Stoeger
5037fcdbdc Import: avoid model inconsistency in DiveImportedModel::recordDives()
DiveImportedModel::recordDives() called add_imported_dives(). But that
actually consumes the dive and dive-site tables. Which in turn will
lead to an inconsistent model.

Properly reset the model by using the consumeTables() function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-02 08:04:49 -07:00
Berthold Stoeger
087a80194a Import: keep dive and dive site tables in DiveImportedModel
The DiveImportedModel and DownloadThread used the same table
of dives and dive sites. This made it very hard to keep the
model consistent: Every modification of the download thread
would make the model inconsistent and could lead to memory
corruption owing to dangling pointers.

Therefore, keep a copy in the model. When updating the model,
use move-semantics, i.e. move the data and reset the tables
of the thread to zero elements.

Since the DiveImportedModel and the DownloadThread are very
tightly integrated, remove the accessor-functions of the
dive and dive-site tables. They fulfilled no purpose
whatsoever as they gave the same access-rights as a public
field.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-02 08:04:49 -07:00
Berthold Stoeger
81268adfd3 Import: extract number of dives from model not from thread
The plan is to make the model the authoritative source of
the imported dives. Therefore, access the number of
downloaded dives from there.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-02 08:04:49 -07:00
Berthold Stoeger
8f3c85f58d Import: get tables from DiveImportedModel not DownloadThread
When importing dives, consume the tables from DiveImportedModel
and not the DownloadThread. This appears more logical and avoids
an inconsistent state of the DiveImportedModel: On import the
tables would be reset, but the DiveImportedModel wasn't
informed of that.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-02 08:04:49 -07:00
Berthold Stoeger
30b384cebd Import: keep model state consistent when deleting unselected dives
In DiveImportedModel::deleteDeselected(), unselected dives were
deleted from the dive-table. But this left the model in an
inconsistent state and the frontend was not informed of the
missing dives.

Fix this by invoking the appropriate beginRemoveRows()/
endRemoveRows() pairs. Move the functionality into its
own function so that it can be reused by the desktop version.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-02 08:04:49 -07:00
Berthold Stoeger
ad7ffa0af0 Import: Make DownloadThread a subobject of DiveImportedModel
Currently, desktop and mobile are accessing the DownloadThread
and the DiveImportedModel concurrently. This makes a big data
flow mess. To achieve a more hierarchical data flow, start
by making the DownloadThread a subobject of DiveImportedModel.

Start the download by calling a function in DiveImportedModel.

Route the finished signal through DiveImportedModel. Thus,
the model can reload itself with the new data.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-02 08:04:49 -07:00
Berthold Stoeger
eecca6aab0 Mobile: replace model-reset by row-addition in DiveListModel::reload()
Owing to apparent QML breakage, a model-reset leads to the DiveDetail
page being reloaded for every dive in the list(!). Therefore, add
rows instead.

This leads to extremely subtle code, as it is now imperative that
the model has been properly cleared beforehand. Nevertheless, for
now we have to do this to fix a severe performance regression.

Fixes #2295

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-27 16:33:37 -07:00
Berthold Stoeger
649ac1f83a Mobile: clear dive data via model
Clearing the dive data directly in the core leaves us with an
inconsistent model. Therefore, clear via the model.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-27 16:33:37 -07:00
Dirk Hohndel
9ae7040a91 Revert the singleton PR
It turns out that this isn't working the way it was intended to.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-09-27 16:26:58 -07:00
Berthold Stoeger
4d3686edec Cleanup: Pass gpsTrackers directly to GpsListModel::update()
Instead of using the GpsLocation singleton in GpsListModel::update()
to extract the gpsTrackers, pass the gpsTrackers as function argument.

The caller has direct access to the GpsLocation object anyway and this
make things less entangled.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-25 13:35:30 -07:00
Berthold Stoeger
05200f9266 Cleanup: unify idiosyncratic singletons
The way we handle singletons in QML, QML insists on allocating the
objects. This leads to a very idiosyncratic way of handling
singletons: The global instance pointer is set in the constructor.

Unify all these by implementing a "SillySingleton" template. All
of the weird singleton-classes can derive from this template and
don't have to bother with reimplementing the instance() function
with all the safety-checks, etc.

This serves firstly as documentation but also improves debugging
as we will now see wanted and unwanted creation and destruction
of these weird singletons.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-25 13:35:30 -07:00
Berthold Stoeger
9322c54b6a Mobile: pass section directly to tripTitle() and tripShortDate()
Instead of converting the section-heading string to a trip-pointer
in QML and pass that to the tripTitle() and tripShortDate()
functions, pass the string and convert in C++ code.

Hopefully, this makes the code more robust.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-21 16:12:23 -07:00
Berthold Stoeger
ce751bd696 Mobile: pass trip-ids through QML, not formatted pointers
The section heading in the QtQuick ListView has to be a string.
Therefore, we passed a pointer formatted using hexadecimal notation.
Later, that was converted back without being checked.
A very scary proposition, so let's pass unique integer trip-id instead.
This means that on converting back we have to scan the trip table,
but that is a very minor cost comsidering to the gained robustness.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-21 16:12:23 -07:00
Berthold Stoeger
b3e5e5eef4 Cleanup: remove bogus assignment in startFilterDiveSites()
In MultiFilterSortModel::startFilterDiveSites(), the setting of the
dive sites to be filtered is done later in the code. Therefore,
remove the assignment in the first line of the function. Under
some circumstances, this would prevent a needed map reload!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-21 16:07:24 -07:00
Berthold Stoeger
20e847f9d8 Mobile: Map directly from source in DiveListSortModel::getIdxForId()
Instead of looping over all dives and search the dive with the given
id, let the source model determine the index and map that. Thus,
we do only one mapping and don't generate a ton of DiveObjectHelpers.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
62f1a92068 Mobile: provide direct access to dives in DiveListModel
Accesses were via DiveObjectHelpers. Provide a direct access to
struct dive *. Use this for the filter - there is no point in
mass generating DiveHelperObjects in the filter code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
ca939300e2 Mobile: create DiveObjectHelper only when needed
In DiveListModel::data() a DiveObjectHelper was created for any
data-access. Create it only when a DiveObjectHelper is actually
returned.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
a4f3580e10 Mobile: remove dive argument from DiveListModel::insertDive()
Since DiveListModel does not keep its own list of dives anymore,
insertDive() doesn't use the DiveObjectHelper argument. Remove it.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
0026aa3955 Mobile: replace clear()/addAllDives() pairs by reload()
The clear()/addAllDives() pair was bogus as the former didn't
clear the model (this is not possible anymore - the model
represents the core dive list) and the latter readded all
dives again.

Replace this by a reload() function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
57b77c90b9 Cleanup: remove DiveListSortModel::addAllDives()
This function was never used.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
f8c5c8bedf Mobile: Generate DiveObjectHelpers on the fly
Instead of keeping track of a list of DiveObjectHelpers, generate
them on-the-fly in DiveListModel. Thus, there is less danger of
model and core getting out of sync. On the flip-side, now the
DiveListModel and the DiveListSortModel might get out of sync.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
be763452ad DiveObjectHelper: Turn DiveObjectHelper into Q_GADGET based object
DiveObjectHelper is a tiny wrapper around dive * to allow access
to dive data from QML and grantlee. It doesn't have to be a
full-fledged QObject with support for signals, etc. Therefore,
turn it into a Q_GADGET based object. This allows us passing the
object around as object, not as pointer to DiveObjectHelper.
This makes memory-management distinctly easier.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
a79c45e401 Mobile: return depthDuration directly from DiveListModel
We don't want to generate a DiveObjectHelper numerous times for
every item in the dive list. Therefore, return this data directly
from the model. In this case, don't remove from DiveObjectHelper,
as these data might be used by grantlee templates.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00
Berthold Stoeger
c4831d7ace Mobile: return location directly from DiveListModel
We don't want to generate a DiveObjectHelper numerous times for
every item in the dive list. Therefore, return this datum directly
from the model. In this case, don't remove from DiveObjectHelper,
as this datum might be used by grantlee templates.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-14 13:20:59 +02:00