aboutsummaryrefslogtreecommitdiffstats
path: root/qt-models/divetripmodel.cpp
AgeCommit message (Collapse)Author
2020-03-10dive models: add helper role to find trip above or below diveGravatar Dirk Hohndel
This is only used in the mobile UI where the sort direction is fixed and we refer to dives based on the tree model. So the terms used and the concepts that these rely on should be guaranteed to be valid. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-03-10core: add 'diveInTrip' role to underlying data modelGravatar Dirk Hohndel
This will allow us to offer differentiated options in the context menu. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-03-10undo: clear undo-stack when clearing dive dataGravatar Berthold Stoeger
When the dive data is cleared, all pointers in the undo-stack become stale. Desktop explicitly called Command::clear() in that case, but mobile doesn't. Thus, move the clear() call into DiveTripModelBase::clear() Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-09mobile/divelist: implement trip title and short date for mobileGravatar Dirk Hohndel
We pass this through to the underlying data function. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-03-09mobile/divelist: copy & paste the roles-code from DiveListModelGravatar Berthold Stoeger
To act as a drop-in replacement (at least as much as possible), move the roles from the old DiveListModel to the common base model of mobile and desktop. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-09mobile/divelist: add first version of new MobileListModel proxy modelGravatar Berthold Stoeger
Create a model which represents all top-level items and, potentially, one expanded trip as a flat list. Pass down roles to the source model and let the source model handle that. We'll have to do some ifdef-ery, but so be it. Additionally, compile the base model on mobile as well. This contains a couple of hacks to make things compile at all. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-03-07divetripmodel: send shown changed signal on resetGravatar Berthold Stoeger
Once the the mobile app uses the new models, this will be necessary to get the correct number of filtered dives after startup. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-06divetripmodel: use change of CURRENT_ROLE to propagate current diveGravatar Berthold Stoeger
If compiled on mobile, on change of the current dive, don't send a signal, but send changed-event with the CURRENT_ROLE for both dives that changed status (previously selected and newly selected). Mobile does not use this yet, but will do so with the new flattened models. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-06divetripmodel: add TRIP_HAS_CURRENT_ROLEGravatar Berthold Stoeger
This role returns true if the given trip contains the current dive. This will be needed by the mobile list model to decide if a newly added trip should be expanded right away. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-06divetripmodel: introduce CURRENT_ROLEGravatar Berthold Stoeger
Use this role to test whether a dive is the currently displayed dive. This will be needed to transport changes of the current dive to the mobile list models. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-22Filter: move actual filtering loop to core/divefilter.cppGravatar Berthold Stoeger
The DiveFilter class defined the showDive() function to test whether a dive should be filtered or not. This was used in DiveTripModel to loop over all dives or all dives affected by an editing action. This restricts us in how we do filtering: We can't use indexes that give us directly the result. To make the filtering more flexible, move the actual loops that do the filtering to the DiveFilter class. The undo-commands likewise called directly the showDive() function to check whether newly added dives are shown. Use the new interface here as well. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-22Filter: update current dive if change hides current diveGravatar Berthold Stoeger
When changing the filter-criterion and the current dive is hidden, a new dive is made current. However, when a dive is hidden because it was edited, it is still shown. Make this consistent by also selecing a new current dive in the latter case. Do this by comparing the current_dive before and after calculating the filter. Since this is now done in multiple places move this code to the ShownChange class. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-22Cleanup: remove shown flag of DiveTripModelTree itemsGravatar Berthold Stoeger
Since we now filter at the model level, items are by definition shown. No need for a flag. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-22Cleanup: remove DiveTripModelBase::SHOWN_ROLEGravatar Berthold Stoeger
This role was used by the filter-proxy model as filter criterion. Since we don't use that model to filter anymore, we can remove the role. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-22Cleanup: remove DiveTripModelBase::sendShownChangedSignals()Gravatar Berthold Stoeger
This was used by the old filtering code. This is not necessary anymore. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-22Dive list: filter dives at DiveTripModel levelGravatar Berthold Stoeger
We use a QFilterProxyModel to filter out dives that are hidden according to the current filter-criterion. Instead, filter the dives already at the DiveTripModel level. Filter out hidden dives immediately when receiving them. The only difficult case is when dives are changed, because then visibility can change. This means that we have three cases to consider: 1) Visibility unchanged -> send change signal 2) Change from hidden to unhidden -> add dives to model 3) Change from unhidden to hidden -> remove dives from model Things get complicated by the fact that the tree-version of the model might have to add/remove full trips! Suggested-by: Dirk Hohndel <dirk@hohndel.org> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-11Cleanup: remove filterSelectedDives function in divetripmodel.cppGravatar Berthold Stoeger
The last users of the returned vector were removed in commit e1abf9485cf59f1b8cb79d827fa386af48f095a4 Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-01-10code cleanup: introduce empty_cylinder constantGravatar Dirk Hohndel
This deals with the issue of initializing structs in C++. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-12-13Coding style: use std::equal_to instead of lambdaGravatar Berthold Stoeger
Use std::equal_to instead of lambdas that compare two dive pointers. One could argue over which version is more readable. For whatever it's worth, std::equal_to is more compact and expressive. This removes an old erroneous comment that stated that std::equal_to is only available since C++14. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-11Dive list: implement DiveTripModelBase::reset()Gravatar Berthold Stoeger
On desktop, resetting the model is realized by generating a new model object. This is due to the fact that we have two different models (tree and list) and for switching between those, we have to create a new object. On mobile, currently there are no plans to support the list-mode. Therefore, there is no reason the recreate the object. Instead, implement a reset() function that reloads the core data. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-10Filter: correctly send changed signals in list modeGravatar Berthold Stoeger
The DiveTripModelList forgot to collect the changed dives when resetting the filter. Fix that. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-10Filter: instruct UI of changed current diveGravatar Berthold Stoeger
Updating the filter can lead to changes of the current dive. Keep the UI in the know by re-initializing the selection. This is not optimal, because the whole selection is reset, but the pragmatic thing to do for now. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-10Dive list: remove global pointer to DiveTrip modelGravatar Berthold Stoeger
This part of the code had that horrible pattern, where reseting the model would invalidate all pointers to the DiveTrip model. Internalize these complexities in the MultiFilterSortModel. All accesses are now performed via that proxy model. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-10Filter: send filterReset via signalGravatar Berthold Stoeger
The old code called directly into the DiveListModel. Instead, send a signal and hook into the signal from the model. This will allow us to remove the DiveListModel::instance() function. This, in turn, is a step towards supporting multiple models at the same time. However, currently the model manually sets the hidden_by_filter flag in the core and therefore only one active model is supported at a time. 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-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-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-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-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-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-09-06Dive site: don't emit divesChanged signals when editing dive siteGravatar Berthold Stoeger
When editing the dive site, for certain fields a divesChanged signal was emitted so that the dive-list can be updated. Arguably it is wrong to decide which fields are relevant to the dive list in the undo-command code. Therefore, let the list catch the dive-site-edited signal and decide itself. But the actual reason for this commit is that if the dive-site field of a dive changes, we might have to reload the dive-location-model because suddenly a new dive site appears. Now if this is done in QML context on some Qt version (notably 5.9) we get crashes later on. But that can happen if the user moves a flag. So in that case only send a diveSiteChanged signal. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-07-19Undo: make editing of dive number undoableGravatar Berthold Stoeger
When pressing F2 in the dive list, the number can be edited. Make this action undoable by implementing a EditNumber command. This command is differs from the other undo commands, as not the currently selected dives are changed. This means that the EditCommand needs an alternative constructor taking a single dive. This constructor was implemented in the base class so that all edit commands can now be called with a single dive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-06-23Cleanup: unify selection signalsGravatar Berthold Stoeger
For historic reasons, there where three distinct signals concerning dive-selection from the undo-machinery: 1) divesSelected: sent newly selected dives 2) currentDiveChanged: sent if the current dive changed 3) selectionChanged: sent at the end of a command if either the selection or the current dive changed Since now the undo-commands do a full reset of the selection, merge these three signals into a single signal. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-06-23Undo: unify selection behavior in dive-list commandsGravatar Berthold Stoeger
Some commands tried to retain the current selection on undo/redo, others set the selection to the modified dives. The latter was introduced because it was easier in some cases, but it is probably more user-friendly because the user gets feedback on the change. Therefore, unify to always select the affected dives on undo()/redo(). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-06-23Undo: don't send signals batched by tripGravatar Berthold Stoeger
Since the default view is batched by trips, signals were sent trip-wise. This seemed like a good idea at first, but when more and more parts used these signals, it became a burden. Therefore push the batching to the part of the code where it is needed: the trip view. The divesAdded and divesDeleted are not yet converted, because these are combined with trip addition/deletion. This should also be detangled, but not now. Since the dive-lists were sorted in the processByTrip function, the dive-list model now does its own sorting. This will have to be audited. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-06-23Dive list: cache shown flag in model (quick-fix for undo-crash)Gravatar Berthold Stoeger
We have a very fundamental problem with data-duplication in core and qt-models. In a particular case, this led to an easily reproducible crash: 1) An undo command moved the last dive of a trip to another. 2) When an undo-command removed the last dive of a trip to a different trip, the dive was removed from the trip in the core. Then, the model was updated. 3) That lead at first to a rearrangement of the trips, because the trip with the added dive is moved before the trip with the removed dive. 4) In such a case, the filter-model checks the visibility of the trip. 5) Since the trip with the removed dive has no dives in the core, visibility was determined as false. 6) From this point on the mappings of the QSortFilterProxyModel were messed up. Accesses led to crashes. It is unclear whether this is a Qt bug or only a QOI issue. As a quick-fix, cache the visibility flag of trips directly in the Qt-models. Don't set the visibility directly in the core, but go via the Qt-models. Thus, a more clear layering is achieved. In the long run, we can hopefully get rid of the data-duplication in the models. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-06-19Cleanup: move trip-related functions into own translation unitGravatar Berthold Stoeger
These functions were spread out over dive.c and divelist.c. Move them into their own file to make all this a bit less monolithic. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-06-19Cleanup: move tag functions into own translation unitGravatar Berthold Stoeger
Make dive.h a bit slimmer. It's only a drop in the bucket - but at least when modifying tag functions not the *whole* application is rebuilt anymore. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-05-20Cleanup: fix a few comments and debug messagesGravatar Berthold Stoeger
This is just minor fixes that are not user-visible: Fix a few erroneous comments and a debug message. These are copy & paste mistakes and mistakes introduced during code- refactoring. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>