summaryrefslogtreecommitdiffstats
path: root/qt-models
AgeCommit message (Collapse)Author
2019-12-05Undo: make weight editing undoableGravatar Berthold Stoeger
Implement the EditWeight undo command. Since there is common code (storage of the old weight), this creates a common base class for RemoveWeight and EditWeight. The model calls directly into the undo command, which is somewhat unfortunate as it feels like a layering violation. It's the easy thing to do for now. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-05Desktop: refactor WSInfoDelegate logicGravatar Berthold Stoeger
The WSInfoDelegate (weight-system-info delegate) is used to display a combo box of known weightsystem-types and auto-fills the weight if the weightsystem-type is changed. This would overwrite the weight data of the displayed dive when the user hovers over the different entries. Moreover, it saves the original weight in case the user cancels the editing action. This is not viable when implementing undo of weightsystem changes, because hovering over entries should not produce individual undo commands. Instead, implement a special "temporary" row in the weightsystem model. On canceling of the edit actions, simply reload the weightsystem from the unmodified dive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-05Cleanup: introduce empty_weightsystem constantGravatar Berthold Stoeger
To make things more future-proof, introduce an empty_weightsystem constant. Replace explicit aggragate initialization of empty weightsystems by this constant. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-05Cleanup: remove redundant "row" member of WeightModelGravatar Berthold Stoeger
Before undoization, the WeightModel could be out-of-sync with the actual dive and therefore had a row member variable. This became redundant. Therefore, remove it. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-05Cleanup: return value type from WeightModel::weightSystemAt()Gravatar Berthold Stoeger
There is only one caller of WeightModel::weightSystemAt() and that certainly does not need a pointer into the weightsystem-table of the current dive. Return a value type instead of a pointer. This allows us to mark WeightModel::weightSystemAt() as const and use it from WeightModel::data(). Slightly cleaner code. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-05Undo: make weight-deletion an undoable actionGravatar Berthold Stoeger
This one is a bit more complicated than weight adding, because the multiple-dive case is not well defined. If multiple dives are selected, this implementation will search for weights that are identical to the weight deleted in the currently shown dive. The position of the weight in the list is ignored. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-05Desktop: don't connect to remove() slot of model from TableModelGravatar Berthold Stoeger
When connecting a model to the TableModel class, it would connect clicking on an item to the remove() slot of the model. This breaks the program flow implied by the undo code: Ui --> Undo-Command --> Model --> UI Moreover, the naming of the remove() slot is illogical, because clicks can also have different effects, as for example in the cylinder-table. Therefore, move the connect() call from TableModel to the callers. In the case of TabDiveSite, move the remove() function from the model to the TabWidget, where it makes more sense. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-05Undo: make adding of weights an undoable actionGravatar Berthold Stoeger
Introduce an AddWeight undo command. This is modelled after the numerous dive-edit undo commands. The redo and undo actions are connected to the WeightModel via two new signals, weightAdded and weightRemoved. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-05Cleanup: remove displayed_dive from WeightModelGravatar Berthold Stoeger
The WeightModel always acted on the displayed dive. To support undo of weightsystem changes, operate on an arbitrary dive. This is in line with other models, where the updateDive() function resets the model to represent a certain dive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Selection: move translation of indexes to filter modelGravatar Berthold Stoeger
The DiveListView caught signals from the DiveTripModel with the corresponding indexes. However, the DiveListView is actually connected to the MultiFilterSortModel and thus has to translate the indexes. Instead, catch the signals in the MultiFilterSortModel, transform them and resend. Let the DiveListView get its signal from the MultiFilterSortModel. Yes, this makes things less efficient because there is an extra signal. On the upside, the makes data-flow much more logical. Selection will have to be fixed anyway. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Selection: move initialization of selection from view to modelGravatar Berthold Stoeger
The goal here is to unify desktop and mobile by moving selection code from the desktop-only view. Currently, initialization of the selection still has to be called from the view after connecting the appropriate signals. This is due to the weird way in which create completely new models when resetting them. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Cleanup: rename newCurrentDive signal to currentDiveChangedGravatar Berthold Stoeger
This is more consistent with the rest of the signals. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Filter: use changed-signals to update filterGravatar Berthold Stoeger
The dive-trip models now send changed-events if the shown-status changed. Thus, there is no reason to fully reset the filter on filter changes. Simply tell the filter that it has to react to changes of SHOWN_ROLE. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Dive list model: send changed signals for top-level itemsGravatar Berthold Stoeger
In analogy to the tree-model send signals when dives change their shown status in the list-view. Do this in two passes (collect changes; send changes) to be able to reuse the already existing functions. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Dive trip model: send changed signals for top-level itemsGravatar Berthold Stoeger
Send signals if the shown-status of top level items changed. Do this in two passes to be able to use the previously created function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Dive trip model: send changed signals if visibility changed in tripsGravatar Berthold Stoeger
To avoid having to do full filter reloads, send dive-changed signals for dives in trips when the shown-status changed. But only for trips where not all dives are hidden. Because for those, the plan is to hide the trip as a whole. Implement the signal sending in its own function so that it can be reused for top-level items and the list-view. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Dive list model: move filtering of trip-items to own functionGravatar Berthold Stoeger
Implementing proper model semantics (only sending a changed signal for items that actually changed) will be somewhat complicated. Therefore, move the filtering of trip-items to its own function to make the nesting a little bit less deep. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-26Cylinders: Fix crash when removing cylindersGravatar Berthold Stoeger
Change the remove() function of the cylinder and weight models to take the index by value. The code used to take it by reference and the reference would be invalidated when removing rows from the model! Reported-by: Gaetan Bisson <bisson@archlinux.org> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Dive list: clear internal data when clearing modelGravatar Berthold Stoeger
The DiveListModelBase::clear() implementation was flawed: It cleared the data in the core, but left the data in the model untouched. The code was relying on the fact that the caller would reset the model manually. Not a good idea. Therefore, clear the internal data to keep the model consistent at all times. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Dive list: update selection after clearing modelGravatar Berthold Stoeger
When clearing the model the selection is cleared. Send the according signal. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: move recalculation of filter from FilterModel to TripModelGravatar Berthold Stoeger
The way this was accessed via Qt's model semantics was horrible. This gives arguably more readable code, since we don't have to shoehorn things through QVariants. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: move num_shown logic from model to coreGravatar Berthold Stoeger
Since the number of shown dives is stored in the core, let's also keep it updated there. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: split out filter from modelGravatar Berthold Stoeger
Split out the actual filtering from the MultiFilterSortModel. Create a DiveFilter class that does the actual filtering. Currently, mobile and desktop have their own version of this class, though ultimately we may want to merge them. The idea here is that the trip-model and undo-commands have direct access to the filter-function and thus can take care of keeping track of the number of shown dives, etc. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: move calculation of shown dives to undo commandGravatar Berthold Stoeger
The filter-model was catching dives-added / dives-deleted signals from the models to keep track of the number of shown dives. To simplify the data flow, do this directly in the undo-command. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: move number of shown dives to coreGravatar Berthold Stoeger
We mark hidden/shown dives in the core but store the number of shown dives in the MultiFilterSortModel. Move this datum to the core for improved locality. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Cleanup: remove MultiFilterSortModel::filterChanged()Gravatar Berthold Stoeger
Nobody was calling this function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Cleanup: remove MultiFilterSortModel::clearFilterGravatar Berthold Stoeger
Nobody was using that function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-16Cleanup: use DiveTripModelBase::clear() to reset the logGravatar Berthold Stoeger
Introduce a DiveTripModelBase::clear() function that cleanly clears all dive data inside a beginResetModel()/endResetModel() pair. Thus, the UI will be cleanly reset and we can remove explicit calls to - graphics->setEmptyState() - mainTab->clearTabs() - mainTab->clearTabs() - diveList->reload() from MainWindow::closeCurrentFile(). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-16Partially revert 3025e0630de2b9ced3d0aadd1513cb0e1c93b159Gravatar Berthold Stoeger
This commit did the "right" thing by implementing Qt mode semantics as intended, but for unknown reasons the profile is not properly cleared on close-file anymore. This code is so convoluted that there is not point in fighting it at the moment. Revert to remove-rows instead of reset-model. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-15Dive list: signal correct trip in DiveTripModelTree::topLevelChangedGravatar Berthold Stoeger
DiveTripModelTree::topLevelChanged() has pretty complex code, as it has to handle the fact that when adding/removing a dive from a trip, the trip can change its position. The code did not account for the fact that when moving an object back in the top level list, one has to subtract one from the new index, because the object was removed somewhere in the front of the list. To make matters worse, when an entry stayed where it was, this was realized by moving the entry right behind itself, which of course means that it stays where it is. But this meant that in the by far most common case (no moving) the wrong entry was updated. Fix this by subtracting 1 from the new index when moving an entry to the back. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-14Refactoring: move undo commands to top levelGravatar Berthold Stoeger
In the future we might want to use undo-commands for mobile as well (even if not implementing undo). Therefore, move the undo-command source from desktop-widgets to their own commands top-level folder. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>