aboutsummaryrefslogtreecommitdiffstats
path: root/qt-models
AgeCommit message (Collapse)Author
2019-11-11Cleanup: introduce DiveTripModelBase::IS_TRIP_ROLEGravatar Berthold Stoeger
To test whether an entry is a trip, we passed a pointer to the trip through a QVariant and tested that for null-ity. Passing pointers through QVariants has given us myriads of problems in QML, therefore introduce a bool IS_TRIP_ROLE Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-11Cleanup: fix typos in commentGravatar Berthold Stoeger
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09Cylinders: access cylinders with get_cylinder()Gravatar Berthold Stoeger
Instead of accessing the cylinder table directly, use the get_cylinder() function. This gives less unwieldy expressions. But more importantly, the function does bound checking. This is crucial for now as the code hasn't be properly audited since the change to arbitrarily sized cylinder tables. Accesses of invalid cylinder indexes may lead to silent data-corruption that is sometimes not even noticed by valgrind. Returning NULL instead of an invalid pointer will make debugging much easier. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09Core: remove MAX_CYLINDERS restrictionGravatar Berthold Stoeger
Instead of using fixed size arrays, use a new cylinder_table structure. The code copies the weightsystem code, but is significantly more complex because cylinders are such an integral part of the core. Two functions to access the cylinders were added: get_cylinder() and get_or_create_cylinder() The former does a simple array access and supposes that the cylinder exists. The latter is used by the parser(s) and if a cylinder with the given id does not exist, cylinders up to that id are generated. One point will make C programmers cringe: the cylinder structure is passed by value. This is due to the way the table-macros work. A refactoring of the table macros is planned. It has to be noted that the size of a cylinder_t is 64 bytes, i.e. 8 long words on a 64-bit architecture, so passing on the stack is probably not even significantly slower than passing as reference. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09Cleanup: Make cylinder formatting functions const-cleanGravatar Berthold Stoeger
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-09Cleanup: free plot data on exitGravatar Berthold Stoeger
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-09Profile: dynamically allocate plot pressure dataGravatar Berthold Stoeger
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-09Profile: use pressure data functions in DivePlotDataModelGravatar Berthold Stoeger
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-09Cleanup: implement proper Qt-model semantics in DivePlotData modelGravatar Berthold Stoeger
User beginResetModel()/endResetModel() pairs to reset the model. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-09Cylinders: dynamically allocate cylinder arraysGravatar Berthold Stoeger
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-09Core: dynamically allocate the result of get_gas_used()Gravatar Berthold Stoeger
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-08Mobile: correctly update filter text and update all three modelsGravatar Dirk Hohndel
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-08Mobile: ensure the sort order is always setGravatar Dirk Hohndel
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-08Mobile: add second filter proxy model for dive listGravatar Dirk Hohndel
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-10-31Planner: Add option to treat O2 as narcoticGravatar Robert C. Helling
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-27Cleanup: NULL check pointer before dereferencingGravatar Dirk Hohndel
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-27Cleanup: add missing break statementsGravatar Dirk Hohndel
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-26Cleanup: avoid resource leak in dive planner modelGravatar Dirk Hohndel
Found by Coverity. Fixes CID 350121 Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-10-26Cleanup: avoid out of bounds accessGravatar Dirk Hohndel
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-26Desktop: use undo command when replanning diveGravatar Berthold Stoeger
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-20Mobile: remove remaining accesses to DiveObjectHelper from QMLGravatar Dirk Hohndel
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-20Mobile: get dive details directly from the modelGravatar Dirk Hohndel
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-20Planner: copy deco state before passing it to worker threadGravatar Berthold Stoeger
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-04Cleanup: Make constructor of singletons privateGravatar Berthold Stoeger
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-04Cleanup: Turn DiveListSortModel into classical singletonGravatar Berthold Stoeger
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-04Cleanup: turn GpsListModel into standard singletonGravatar Berthold Stoeger
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-04Cleanup: turn DiveListModel into standard singletonGravatar Berthold Stoeger
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-04Cleanup: initialize DiveListSortModel in constructorGravatar Berthold Stoeger
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-02Import: remove DiveImportedModel::lastIndexGravatar Berthold Stoeger
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-02Cleanup: remove DiveImportedModel::firstIndexGravatar Berthold Stoeger
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-02Import: avoid model inconsistency in DiveImportedModel::recordDives()Gravatar Berthold Stoeger
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-02Import: keep dive and dive site tables in DiveImportedModelGravatar Berthold Stoeger
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-02Import: extract number of dives from model not from threadGravatar Berthold Stoeger
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-02Import: get tables from DiveImportedModel not DownloadThreadGravatar Berthold Stoeger
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-02Import: keep model state consistent when deleting unselected divesGravatar Berthold Stoeger
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-02Import: Make DownloadThread a subobject of DiveImportedModelGravatar Berthold Stoeger
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-09-27Mobile: replace model-reset by row-addition in DiveListModel::reload()Gravatar Berthold Stoeger
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-27Mobile: clear dive data via modelGravatar Berthold Stoeger
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-27Revert the singleton PRGravatar Dirk Hohndel
It turns out that this isn't working the way it was intended to. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-09-25Cleanup: Pass gpsTrackers directly to GpsListModel::update()Gravatar Berthold Stoeger
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-25Cleanup: unify idiosyncratic singletonsGravatar Berthold Stoeger
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-21Mobile: pass section directly to tripTitle() and tripShortDate()Gravatar Berthold Stoeger
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-21Mobile: pass trip-ids through QML, not formatted pointersGravatar Berthold Stoeger
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-21Cleanup: remove bogus assignment in startFilterDiveSites()Gravatar Berthold Stoeger
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-14Mobile: Map directly from source in DiveListSortModel::getIdxForId()Gravatar Berthold Stoeger
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-14Mobile: provide direct access to dives in DiveListModelGravatar Berthold Stoeger
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-14Mobile: create DiveObjectHelper only when neededGravatar Berthold Stoeger
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-14Mobile: remove dive argument from DiveListModel::insertDive()Gravatar Berthold Stoeger
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-14Mobile: replace clear()/addAllDives() pairs by reload()Gravatar Berthold Stoeger
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-14Cleanup: remove DiveListSortModel::addAllDives()Gravatar Berthold Stoeger
This function was never used. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>