aboutsummaryrefslogtreecommitdiffstats
path: root/qt-models/diveplannermodel.cpp
AgeCommit message (Collapse)Author
2021-05-12Planner: Update plan when deco parameters changeGravatar Robert C. Helling
This makes sure that the dive plan is updated (including the planner notes) when parameters of the dive or the planner change. This fixes a bug reported by Jay Anchor. There is a chance that by partly undoing 77a6bc6d623148, this introduces too many recalculations of the plan. But without this patch, there are definitely not enough recalculations. Reported-by: Jay Anchor <jay.anchor-subsurface@e257.fi> Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-05-07Planner: Update notes when not computing variationsGravatar Robert C. Helling
A change not to compute plan variations when not needed was too aggressive and eliminated also the signal to update the notes. Bug fixed. Reported-by: Jay Anchor <jay.anchor-subsurface@e257.fi> Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-04-02planner: split DivePlannerPointsModel::remove() in twoGravatar Berthold Stoeger
There are two cases in this function: with and without holding the control-key. The former deletes one point, the latter all points starting with the selected point to the end. The code was interlaced making it very hard to reason about. Notably, it was buggy: with control, all points could be deleted, leading to a crash. Split the function in two versions, with their own bound checking. This produces a bit of duplicate code, which might be broken out later. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: avoid starting unneeded variation threadGravatar Berthold Stoeger
When updating the dive profile, a thread is started to calculate plan-variations. This is done even when only editing the profile or when variation calculation is disabled by the user. The thread then exits if it shouldn't calculate the variations. Turn this around: test whether variations should be calculated before starting the thread. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: remove DivePlannerPointsModel::recalc flagGravatar Berthold Stoeger
There was no user of that flag left. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: call removeDeco() explicitlyGravatar Berthold Stoeger
removeDeco() was called by addStop() if the recalc flag was set. If the caller didn't want to call removeDeco() it had to clear and restore the flag. Instead, call removeDeco() explicitly when needed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: don't clear recalc in DivePlannerPointsModel::clear()Gravatar Berthold Stoeger
There are no more external users of this flag, therefore clearing that flag is a no-op. Moreover, clear the cylinders array and the preserved_until flag befor emitting the model-reset signal. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: split DivePlannerPointsModel::removePoints() in twoGravatar Berthold Stoeger
Split the function in one external version, that updates the dive profile and cylinders and one internal version, that does no recalculations. In the latter case, the caller is responsible for updating the dive. Thus, the recalculation flag-clearing can be removed from removeDeco(). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: don't export recalc flag of DivePlannerPointsModelGravatar Berthold Stoeger
This is not queried anymore, so remove the accessor function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02profile/planner: don't update dive in ProfileWidget2::plotDive()Gravatar Berthold Stoeger
In planner or profile-edit mode, the plotDive() function takes the current plan and turns it into a dive profile. Not only is this a layering violation (the display layer modifying the dive), it is also fundamentally flawed. The control-flow is out of control, if you wish. There are numerous reasons why the profile needs to be replot, many of which do not need a recalculated dive profile. Move the code that updates the dive-profile to the DivePlannerPointsModel. Thus, the profile recalculations and replots can be pooled. This will break the planner, since there now might be missing calls to the profile recalculation. But it already has some positive effects: when removing multiple points, the profile is only recalculated once. This will need much more work, but it is a start. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: split addStop() into external and internal versionsGravatar Berthold Stoeger
The DivePlannerPointsModel::addStop() function is called by the profile to add a planner-stop. It is also used internally to create profiles. If we ever want to include this in the undo system, we have to split these into to versions. One will ultimately place an undo command and update the profile, the other one doesn't. For now, this makes the external interface simpler, as some parameters are redundant. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02cleanup: remove unused function DivePlannerPointsModel::size()Gravatar Berthold Stoeger
This is not a virtual function and does not seem to be called anywhere..? Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: split createTemporaryPlan() function.Gravatar Berthold Stoeger
The DivePlannerPointsModel::createTemporaryPlan() function had two distinct and independent parts: 1) create the data points. 2) create the dive sample and calculate variations. The second part was only exectuted if the recalc flag was set. Out of the two callers, one was explicitly disabling and setting the recalc flag to avoid the second part. The much more logical thing is to simply split the function in two and only call the first part. To avoid any functional change, the second caller (the profile) still tests for the recalc flag. However, if it shouldn't replot a new plan, why calculate it in the first place!? And why does the display function change the plan at all? This appears all very ill-thought out and should be changed in due course. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02cleanup: unify whitespace in switch statementGravatar Berthold Stoeger
The way the blocks in DivePlannerPointsModel::setData()'s switch statement were demarked messed with my mind. There were at least three variants. Let's try to be consistent. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: remove DivePlannerPointsModel::setRecalc()Gravatar Berthold Stoeger
The only external user of setRecalc() was turning recalculation on. In fact, this happened when constructing the planner-widget. However, for example editing of the profile only works when the recalc flag is on. This is all very confusing, let's just turn the flag on by default and remove the accessor. Internally, the planner can simply use the std::exchange function to set and reset the recalc flag. Perhaps the setting/resetting can be replaced by simple recalc = true; ... recalc = false; pairs. It is unclear whether there is need for recursion. Something to be investigated. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: remove displayed_dive from DivePlannerModelGravatar Berthold Stoeger
To remove global state, make the dive that DivePlannerModel works on a member variable. Pass the dive in createSimpleDive() and loadFromDive(). Moreover, this should pave the way to more fine-grained undo in the planner. Ultimately, the planner should not be modal. Attention: for now, the dive must still be displayed_dive, because of the convoluted way in which the profile and the planner work on the same dive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: move clearing of model into loadFromDive() functionGravatar Berthold Stoeger
Both loadFromDive() callers were clearing the model before calling loadFromDive(). Move the clearing into that function since it makes no sense to load into a non-cleared model. Apparently this changes the way that no-cylinder dives are treated and the code in ProfileWidget2::repositionDiveHandlers() must now explicitly check for that condition. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02cleanup: remove pointless cylinder model updateGravatar Berthold Stoeger
In DivePlannerPointsModel::clear(), the cylinder model is updated before it is cleared. This must be an artifact. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: move same-time check to DivePlannerPointsModelGravatar Berthold Stoeger
There must not be two dive planner points at the same time stamp, as this violates the laws of physics (and internal assumptions). The corresponding test was done in the profile code at two different places with floating point arithmetics. This is a bad idea, because 1) code duplication 2) danger of rounding issues Instead, do this in one central point in the planner model and use integer arithmetics. Simply add a few seconds until a unique timestamp is obtained. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: implement move semantics in DivePlannerPointsModelGravatar Berthold Stoeger
When reordering the points, the DivePlannerPointsModel would not emit the appropriate move signals, but simply a data-changed signal over all elements. This obviously violates Qt's model/view API, though it is probably harmless. Let's do the right thing so that the frontend knows that the selected item changed place. Also, emit dataChanged only on the actually changed element, not all elements. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: fix removal of points from DivePlannerPointsModelGravatar Berthold Stoeger
The beginRemoveRows() function was fed erroneous values. It is a mystery why this didn't crash. In any case, deletion of multiple points did not work properly. Instead of trying to be fancy, remove each point one-by-one. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: insert point at correct positionGravatar Berthold Stoeger
Instead of inserting the point at the calculated position, the DivePlannerPointsModel would append it at the end and then resort the vector. That's just silly. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02cleanup: use proper model/view semantics in DivePlannerModelGravatar Berthold Stoeger
When clearing the model, use "beginResetModel/endResetModel" instead of "beginRemoveRows/endRemoveRows". Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02cleanup: add DivePlannerPointsModel::addDefaultStop() functionGravatar Berthold Stoeger
When clicking on "+" in the planner, a default stop point was added using a signal/slot connection. This used the archaic string-based connect syntax, because it was realized with default parameters passed to "addStop()". Instead, add a "addDefaultStop()" slot, which passes the default parameters. Since all other callers do not use callbacks, unslotify "addStop()". The slot was the only user of the default parameters, so they can be removed alltogether. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02cleanup: constify DivePlannerPoints model accessor functionsGravatar Berthold Stoeger
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-17planner: pass in_planner argument to decoMode()Gravatar Berthold Stoeger
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>
2021-01-20cleanup: make a few DivePlannerModel functions privateGravatar Berthold Stoeger
It simplifies reasoning about control flow a lot if it is known that functions can't be invoked from a different part of the code base. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20planner: remove DivePlannerPointsModel::startTimeChanged signalGravatar Berthold Stoeger
The way the starting time of a new plan was set was bonkers: 1) PlannerWidgets::planDive() invokes DivePlannerPointsModel:: createSimpleDive(). 2) createSimpleDive() calls DivePlannerPointsModel:: setupStartTime() 3) setupStartTime() emits a signal startTimeChanged() 4) startTimeChanged is caught by PlannerWidget and sets the UI field 5) change of the UI field emits a timeChanged() signal which is connected to DivePlannerPointsModel::setStartTime() 6) setStartTime() sets the time of the plan and displayed_dive and emits dataChanged() 7) dataChanged() replots the dive() 8) Back in DivePlannerPointsModel::createSimpleDive() the diveplan start time is overwritten with displayed_dive (the value are equal owing to 6) Wow! But it gets worse: 9) The initial dive plan is set up in createSimpleDive(). Since the profile is drawn in 7) after clearing the displayed_dive and before constructing the initial plan, the profile is shown on a dive without samples. It therefore generates a dummy profile. To make this somewhat less insane, remove the startTimeChanged() signal in 3), explicitly set the start time of plan and dive to the one calculated by setupStartTime() and explicitly set the UI filed in the plannerWidget. This still indirectly draws the profile via signals in a convoluted way, but at it straightens out things somewhat. Most importantly, the profile doesn't have to generate a fake DC. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-11-24diveplannermodel: replace in_planner() by isPlanner()Gravatar Berthold Stoeger
The in_planner() function is problematic, because it depends on the application state that is only available on desktop. If we ever want to port the planner to mobile, we have to get rid of it. Luckily, the DivePlannerModel already has an appropriate flag that can be used instead. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25cleanup: split out divecomputer functions from dive.cGravatar Berthold Stoeger
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>
2020-08-24Planner: enforce minimal segement durationGravatar Robert C. Helling
You cannot be at two depths at the same time (and it confuses the planner). So give yourself at least 10 seconds. Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-08-24Planner: handle zero length segments when replanningGravatar Robert C. Helling
When setting up a dive for replanning, we ignored zero length segments as those tend to be generated by gas changes. But it is possible to enter those in the planner and the replanning should not ignore those. So be more clever about gas changes. Let's add 10 seconds so we are not at two depths at the same time and help since add_stop also does not like zero length segments (it thinks we are trying to replace a waypoint). Fixes #2901 Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-05-22cleanup: create common QDateTime -> timestamp conversion functionGravatar Berthold Stoeger
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>
2020-05-04planner: remove conditional command-calls for mobileGravatar Berthold Stoeger
In the planner the undo commands for adding / editing dives were only called if not on mobile. This is from days were mobile didn't have undo commands. We can remove these now. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-04Planner: fold MainWindow::setupForAddAndPlan into createSimpleDive()Gravatar Berthold Stoeger
There was only one caller of MainWindow::setupForAddAndPlan() left and that caller immediately called DivePlannerPointsModel::createSimpleDive(). Thus, we might just as fold the former in the latter and thus concentrate all the prepare-dive-for-plan business in one place. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-04planner: send plan in calculatedPlanNotesGravatar Berthold Stoeger
Thus, the MainWindow doesn't have to extract the plan from displayed_dive. This is a tiny step in an attempt to detangle the interfaces. The bigger goal will be to make displayed_dive local to the planner. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-04planner: update variations in planner not mainwindowGravatar Berthold Stoeger
When calculating variations, they were sent to the mainwindow, which updated displayed_dive accordingly. Do this directly in the planner-model. The idea is to detangle interdependencies and to make the code reusable (planner on mobile?). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-01cleanup: move dive_table from dive.h to divelist.hGravatar Berthold Stoeger
This allows us to decouple dive.h and divelist.h, a small step in include disentangling. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-01core: always keep an empty cylinder at the end of the cylinder arrayGravatar Berthold Stoeger
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>
2020-04-13Preserve events when editing dive in plannerGravatar Robert C. Helling
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>
2020-04-07CylindersModel: use flag to decide whether we are in plannerGravatar Berthold Stoeger
On desktop, we have two CylindersModel concurrently: One in the planner and one on the equipment-tab. They act differently, because the former modifies displayed_dive directly, the latter issues undo commands. To differentiate, we used the in_planner() function. However, that appears extremely brittle, especially when combined with undo-commands. Therefore when generating the model, pass in a parameter that says whether this is for the planner or the equipment tab and use that flag to decide how to act. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-07CylinderModel: make dive dynamicGravatar Berthold Stoeger
The CylinderModel always accessed the global "displayed_dive" and in some special cases also "current_dive". To implement cylinder undo, the model should work on an arbitrary dive. Therefore, in analogy to the weight model, make the dive dynamic. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-23cleanup: remove CleanerTableModel::warningMessage signalGravatar Berthold Stoeger
Nobody was ever listening to this signal(?) and the last sender was removed in ac52034778bc5c82bb6c689d765b337b6d75b24a. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-11Planner: don't filter cylindersGravatar Berthold Stoeger
In the planner we used to filter out "unused" cylinders as in the equipment tab. It is unclear whether that makes sense or can even easily be reproduced, since such cylinders have to come from an imported dive. To be on the save side, let's not do this. Replace the CylindersFilteredModel introduced recently by a plain CylindersModel. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-11Planner: make cylinder-model subobject of planner-modelGravatar Berthold Stoeger
The cylinder-model had an instance() function, but actually there were two cylinder models: one used by the equipment tab, one used by the planner. This is misleading. Therefore, remove the instance() function and make the cylinder-model a subobject of the planner-model. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-11Cylinders: Add CylindersModelFilteredGravatar Berthold Stoeger
When the show_unused_cylinders flag is not set, the cylinder tables in the equipment tab and the planner should not show unused cylinders. However, the code in CylindersModel is fundamentally broken if the unused cylinders are not at the end of the list: The correct number of cylinders is shown, but not the correct cylinders. Therefore, add a higher-level CylindersModelFiltered model on top of CylindersModel that does the actual filtering. Some calls are routed through to the base model (notably those that take indexes, as these have to be mapped), for some calls the caller has to get access to the source model first. We might want to adjust this. For filtering, reuse the already existing show_cylinder function and export it via CylindersModel. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-01-25diveplanner: add comments explaining different scalingGravatar jan Iversen
In some case the scaling (real value <-> UI value) is different for mobile and desktop. In order to make the difference understandable comments are added to each function. Signed-off-by: jan Iversen <jan@casacondor.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-01-25diveplanner: move mobile specific calc to diveplannermodelGravatar jan Iversen
setBottomSac, setDecoSac and setFactor in diveplannermodel receives display value which are then converted. subsurface-mobile have slightly different values, move the correction of these from plannershared to diveplannermodel, in order to keep the whole convert in one place. Signed-off-by: jan Iversen <jan@casacondor.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-01-20qt-models: add suffix Display to unit system aware asc/desc settersGravatar jan Iversen
Change ascent/descent setter function names to set_<name>Display to show the value is prepared for displaying (common for desktop and QML). Signed-off-by: jan Iversen <jan@casacondor.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-01-20qt-models: add getters to diveplanner modelGravatar jan Iversen
diveplannermodel already contains set_<asc/desc> function that convert from screen value to real value; this adds get functions that convert real value to screen value, so now all conversions are done in one place. Use prefix Display to identify this is values prepared for the UI (both desktop and QML). Signed-off-by: jan Iversen <jan@casacondor.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>