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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>