aboutsummaryrefslogtreecommitdiffstats
path: root/desktop-widgets/divelistview.h
AgeCommit message (Collapse)Author
2020-10-03desktop: allow moving dives to arbitrary tripsGravatar Berthold Stoeger
The UI only allowed adding dives to trips above or below the current dive (and even that is buggy). This is a strange restriction, since trips are designed to be non-contiguous. Allow adding dives to any trip using the new trip selection dialog. The undo-command is already there, so only little code to write. This feature was requested on the mailing list. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-03selection: create global single_selected_trip() functionGravatar Berthold Stoeger
The DiveListView had a singleSelectedTrip function that returns the selected trip if exactly one trip is selected. This could be very slow if numerous non-trip items were selected, because all the selection indices were back- translated by the proxy model. This could make selection changes very slow, because the MainTab used said function to determine whether it should show trip or dive data.. Indeed, with a 3500 dive test log, when selecting all dives in tree mode, the updating of the TabWidgets is sped up from 130 ms to 5 ms this commit. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-26selection: replace selectedTrips() by singleSelectedTrip() functionGravatar Berthold Stoeger
To check wether the tab widgets should show the trip view, they called the selectedTrips() function. The trip view was shown if that contained only one trip. However, the selectedTrips() function was very slow, because it has to query to core models. Change the function to singleSelectedTrip(), which returns a trip if there is exactly one trip selected. The function returns early if there is more than one trip selected. This makes the select-all case much faster. There are two cases which are still very slow: - List mode, because here all top-level items are queried. - Dive log with many only top-level items. Ultimately, we will have to cache the trip selection because querying the model is too slow. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-26cleanup: make DiveListView slots privateGravatar Berthold Stoeger
It makes reasoning about code so much easier when one knows that functions cannot be accessed from the outside. Therefore, make a number of DiveListView slots private. Moreover, unslotize functions that never were used in connect calls. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-26selection: move test for programmatical selection changes to widgetGravatar Berthold Stoeger
The DiveListView widget has to differentiate between programmatical und user-initiated selection changes. It did so by using the DiveListNotifier::inCommand() flag. However, 1) There is only one point of entry for such selection changes, viz. the MultiFilterSortModel::selectionChanged() signal 2) This signal is not only emitted in command-context. Another source is for example dive-map selection changes. Therefore, move the programmatical-selection-change status down to the widget and set/reset it in the diveSelectionChanged() slot. This makes "select all visible dive sites" somewhat faster. Sadly, not as much as expected. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25cleanup: make various functions in DiveListView privateGravatar Berthold Stoeger
Outside callers had no business calling these functions. Especially some functions that were simply there to override default DiveListView behavior. Mark these as overridden. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25cleanup: remove DiveListView::selectDives()Gravatar Berthold Stoeger
This was used by the map to select dives. However, the map now calls the core function directly, so this can be removed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25desktop: fold DiveListView::selectDive into DiveListView::selectDiveGravatar Berthold Stoeger
DiveListView::selectDive() is an overloaded function. The second version was only called by the first version, so we can fold one into the other. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25desktop: remove scrollto default parameter of DiveListView::selectDive()Gravatar Berthold Stoeger
No caller was using that parameter. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25desktop: make DiveListView::selectDive() privateGravatar Berthold Stoeger
Thus, it is made clear that these member functions can only be accessed from DiveListView itself. This should make debugging easier. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-20Dive list: add option to mark dives validGravatar Berthold Stoeger
If the dive the user clicked on is invalid show an option to make the dive valid. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-11Grammar: replaces 'indexes' by 'indices'Gravatar Robert C. Helling
Grammar-nazi ran git grep -l 'indexes' | xargs sed -i '' -e 's/indexes/indices/g' to prevent future wincing when reading the source code. Unfortunatly, Qt itself is infected as in QModelIndexList QItemSelection::indexes() const Signed-off-by: Robert C. Helling <helling@atdotde.de>
2020-03-01selection: update selection on key-pressesGravatar Berthold Stoeger
Commit 2cea115ddb7528d9e6dd1bf918ebf5c670b82479 "fixed" the selection by hooking into mouseRelease events. An unintended consequence was that scrolling with the cursor keys didn't update the current dive. Therefore, also hook into the corresponding key-press events. This is just horrible, but I'm not aware of any possibility to fix it properly. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-08Dive list: be more careful on when updating the UI after selectionGravatar Berthold Stoeger
Fix two issues: 1) When narrowing the selection, we didn't get setSelection() calls. Only, when the user released the mouse button was the selection updated. Therefore, hook into the mouse-release- event and update the UI if the selection changed. 2) We updated the ui in setSelection(). However, this was called on mouse-move even if the actual selection didn't change. Therefore, compare selection before and after processing of the event and only refresh the UI if there are changes. Clearly, this can only be a quick stopgap solution and we should find out how to properly hook into the selection change machinery. Though see commit 4928c4ae0421193bbd371cb0924091a970489611 for the reason why we do things as we do them. Fixes #2595 Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-04Cleanup: lower-case filenames in core/subsurface-qt/Gravatar Berthold Stoeger
We tend to use lower-case filenames. Let's do it for these files as well. Simple search & replace. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-10Dive list: don't handle selection changes on filter-change in viewGravatar Berthold Stoeger
The selection changes upon completing the filter are handled by the core. Don't do this explicitly in the DiveListView. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Cleanup: remove DiveListView::dontEmitDiveChangedSignal memberGravatar Berthold Stoeger
Should have been removed in 4928c4ae04. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Cleanup: remove DiveListView::expandedRows member variableGravatar Berthold Stoeger
The QList served as backing store for backupExpandedRows() and restoreExpandedRows(). However, these always came in pairs in the same scope. There is no reason to store the expanded rows over a longer time. Therefore, return the expanded rows from backupExpandedRows() and take them as argument in restoreExpandedRows(). Morover replace the QList<int> by the much lighter std::vector<int>. We certainly don't need copy-on-write, reference-counting and immutability of iterators in this case. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Cleanup: remove DiveListView::mouseClickSelection member variableGravatar Berthold Stoeger
That hasn't been used since 2013 (9cc04c1ca6). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Cleanup: remove toggle parameter from DiveListView::selectDive()Gravatar Berthold Stoeger
This defaulted to false and no caller used anything different. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Cleanup: remove DiveListView::remember/restoreSelection()Gravatar Berthold Stoeger
Calls of these functions were removed in the previous commits. Now, remove the functions themselves. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Selection: move selection of "first" dive to coreGravatar Berthold Stoeger
The DiveListView has a function to select the first dive. Move this to the core to be able to call it from all parts (not only desktop) of the code. Currently, this has a (small?) UI regression: when filtering dives and no selected dive is visible anymore, the old code would select the first dive in the list. The new code selects the newest dive, which might not be the first if some sort-criterion is active. To revert to the old behavior, it will be necessary to move the sorting function likewise to the core. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-28Desktop: Improve speed of selecting multiple (or all) divesGravatar Berthold Stoeger
When selecting all dives via CTRL-A or manually and the trips were not expanded, the QSelectionModel sends a single selectionChanged signal per trip. We are reloading the map in every call, making this very slow. I couldn't figure out how to make QSelectionModel behave more nicely, therefore I chose the nuclear option: Remove the map reloading from selectionChanged() and hook into all functions that do selection changes. In these functions, first call the original code and then do the selection-changed operations. This will certainly need some tuning. Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za> 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-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-04-12Undo: switch to edited tripGravatar Berthold Stoeger
If fields in a trip are edited, select that trip, which will display the trip in the notes-box. This is realized by hooking into the tripChanged signal in the dive-list. A layering-violation, perhaps? Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-07Dive list: split DiveTripModel into distinct models (tree and list)Gravatar Berthold Stoeger
The DiveTripModel was used to represent both, trip and list views. Thus many functions had conditionals checking for the current mode and both modes had to be represented by the same data structure. Instead, split the model in two and derive them from a base class, which implements common functions and defines an interface. The model can be switched by a call to resetModel(), which invalidates any pointer obtained by instance(). This is quite surprising behavior. To handle it, straighten out the control flow: DiveListView --> MultiFilterSortModel --> DiveTripModelBase Before, DiveListView accessed DiveTripModelBase directly. A goal of this commit is to enable usage of the same model by mobile and desktop. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-05Dive list: remove sortColumn and currentOrder membersGravatar Berthold Stoeger
Since the QHeaderView of DiveListView is now the authority over sort-column and sort-order, it makes little sense to keep these as member variables. That would only risk inconsistencies. Remove them and query the QHeaderView instead. We still need to keep track of currentLayout, as we have to detect if it changes to change the underlying model from tree to list or vice-versa. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-05Dive list: split reload() in reload() and setSortOrder()Gravatar Berthold Stoeger
The DiveListView code had a very fundamental problem with its header: Each had its own idea of who is responsible for sorting. Since we can't easily change QHeaderView, accept QHeaderView as the authority on sort-column and order. To make this possible, split the reload() function in two distinct functions: - reload() reloads the model and sorts according to the current sort criterion. - setSortOrder() tells the header to display a certain sort criterion. If this is a new criterion, it will then emit a signal. In this signal, resort according to that criterion. Thus, the actual sorting code has to be moved from the headerClicked() to a new sortIndicatorChanged() slot. Morover, the sorting of the QHeaderView has to be used. Reported-by: Stefan Fuchs <sfuchs@gmx.de> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-01Dive list: remove forceSort parameter from DiveListView::reload()Gravatar Berthold Stoeger
DiveListView::reload() was called for full reset of the dive list and for changing the view (tree vs. lis) in DiveListView::headerClicked(). Since the latter does sorting by itself, a parameter "forceSort" was introduced, which defaulted to true, but was set to false by DiveListView::headerClicked(). To remove complexity, simply let DiveListView::headerClicked() set the view by itself and remove tha parameter. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-21Dive list: move dive-selection code from filter to listGravatar Berthold Stoeger
After invalidating the filter, the dive-selection was modified to ensure that at least one dive is selected. This was done in the filter code, but it seems preferrable to do this in the dive-list code, which has direct access to the selection-model. Therefore, move the code from MultiFilterSortModel to DiveListView. While doing so, split the code in DiveListView into more functions to: 1) Get the index of the first dive (if any). 2) Select the first dive (if any). This allows a distinct size reduction of conditional compilation in MultiFilterSortModel (accesses to MainWindow are not possible in mobile code). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Dive list: propagate current-item to frontendGravatar Berthold Stoeger
The command-objects select a current item, but this selection was not propagated to the front-end. The current item is the base for keyboard-navigation through the dive-list and therefore should be set correctly. It took some experimentation to get the flags right: QItemSelectionModel::Current Hopefully, these are the correct flags across all supported Qt versions! Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Undo: select dives after add, remove, merge, split dive commandsGravatar Berthold Stoeger
Select the proper dives after the add, remove, split and merge dives commands on undo *and* redo. Generally, select the added dives. For undo of add, remember the pre-addition selection. For redo of remove, select the closest dive to the first removed dive. The biggest part of the commit is the signal-interface between the dive commands and the dive-list model and dive-list view. This is done in two steps: 1) To the DiveTripModel in batches of trips. The dive trip model transforms the dives into indices. 2) To the DiveListView. The DiveListView has to translate the DiveTripModel indexes to actual indexes via its QSortFilterProxy- model. For code-reuse, derive all divelist-changing commands from a new base-class, which has a flag that describes whether the divelist changed. The helper functions which add and remove dives are made members of the base class and set the flag is a selected dive is added or removed. To properly detect when the current dive was deleted it became necessary to turn the current dive from an index to a pointer, because indices are not stable. Unfortunately, in some cases an index was expected and these places now have to transform the dive into an index. These should be converted in due course. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Dive list view: replace signal-magic by flagGravatar Berthold Stoeger
In DiveListView, we have a very fundamental problem: When On the one hand, we get informed of user-selection in the DiveListView::selectionChanged() slot. This has to set the correct flags in the C-backend. On the other hand, sometimes we have to set the selection programatically, e.g. when selecting a trip. This is done by calling QItemSelectionModel::select(). But: this will *also* call into the above slot, in which we can't tell whether it was a user interaction or an internal call. This can lead to either infinite loops or very inefficient behavior, because the current dive is set numerous times. The current code is aware of that and disconnects the corresponding signal. This is scary, as these signals are set internally by the model and view. Replace this by a global "command executing" flag in DiveListNotifier. The flag is set using a "marker" class, which resets the flag once it goes out of scope (cf. RAII pattern). In DiveListView, only process a selection if the flag is not set. Otherwise simply call the QTreeView base class, to reflect the new selection in the UI. To have a common point for notifications of selection changes, add such a signal to DiveListNotifier. This signal will be used by the DiveListView as well as the Command-objects. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-09-29Cleanup: reinstate override modifiersGravatar Berthold Stoeger
This reverts commit 1c4a859c8d0b37b2e938209fe9c4d99e9758327a, where the override modifiers were removed owing to the noisy "inconsistent override modifiers" which is default-on in clang. This warning was disabled in 77577f717f5aad38ea8c4c41c10c181486c4337f, so we can reinstate the overrides. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-01Cleanup: make DiveTripModel a global objectGravatar Berthold Stoeger
DiveTripModel (the model describing the dive-list) was destroyed and recreated on every reset of the list. This seems excessive. Instead - in analogy to most other models - make it a single global object. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-01Cleanup: remove all override modifiersGravatar Berthold Stoeger
Commit df156a56c08a56eb380711a507ef739d8150a71f replaced "virtual" by "override" where appropriate. Unfortunately, this had the unintended consequence of producing numerous clang warnings. If clang finds a override-modified function in a class definition, it warns for *all* overriden virtual functions without the override modifier. To solve this, go the easy route and remove all overrides. At least it is consistent. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-30Cleanup: remove DiveListView::fixMessyQtModelBehaviour()Gravatar Berthold Stoeger
The function DiveListView::fixMessyQtModelBehaviour() was used to expand the first columns of dive-trips in the dive-list view. This function was called everytime that the dive-list was modified. It is kind of ludicrous that external callers would have to tell the DiveListView, when it has to update its column headers. Instead, place this functionality in the overriden reset() and rowsInserted() functions, as these are the only ways that rows can be added. Change the DiveTripModel to use the proper beginResetModel()/endResetModel() pair instead of the previous full deletion and full repopulation using the beginRemoveRows()/ endRemoveRows() and beginInsertRows()/endInsertRows(). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-30Cleanup: remove parameter from currentDiveChanged signalGravatar Berthold Stoeger
The currentDiveChanged signal was emitted by the DiveListView to inform the MainWindow of a change of current dive. The new current dive was passed as a parameter. The slot in MainWindow then called select_dive() on the dive. This seems pointless because: 1) In both emits, selected_dive dive was passed as argument. But MainWindow can read this global variable itself. 2) Calling select_dive() again is a no-op, because obviously, this already *was* the selected dive. Moreover it seems conceptually wrong to set the current dive in the slot that is informed of the change of the current dive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-30Cleanup: remove DiveListView::testSlot()Gravatar Berthold Stoeger
This debugging-slot was not linked anywhere. And especially in the light of the impending refactoring of DiveListView/DiveTreeModel it seems pointless to keep old debugging code. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-27Dive list view: setup columns in constructorGravatar Berthold Stoeger
The column-widths must only be set once the source-model is that. The old code realized this with a rather complicated logic. Instead, simply set the source-model in the constructor and set the column widths after that. Rename the corresponding function from "setupUi" to "setColumnWidths". Moreover, the setupUi function had different code-paths for the first and other calls. Since it is only called once, remove the other code paths. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-27Dive list view: move column width logic back from DiveTripModelGravatar Berthold Stoeger
Conceptually, the width of the columns should probably reside in the view not the model. But much more severly, the old code didn't work: Columns were set in a DiveTripModel, which was deleted right away. Therefore, move the logic back to the DiveListView. Introduce a QVector<int> of the initial column widths, so that they can be erased from the setting if unchanged. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-04Dive pictures: implement FindMovedImagesDialogGravatar Berthold Stoeger
Move the find-moved-images functions into a new translation unit and present the user with the identified matches before applying them. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-06-09Cleanup: make lastUsedDir() functions static and non-slot, respectivelyGravatar Berthold Stoeger
The lastUsedDir() functions of MainWindow and Smrtk2ssrfcWindow don't use any member-objects and are only used in their respective translation units. Therefore, remove them from the class and made of static linkage. The lastUsedImageDir() function was declared as a slog, which makes no sense. Make it a normal static function (though one might argue why it is assiociated with the DiveListView class in the first place). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-10-03divelist: prevent a crash for missing column widthGravatar Lubomir I. Ivanov
The `static int defaultWidth[]` definition in divelistview.cpp could potentially end up missing an element which can later result in out-of-bounds access when iterating through the list of columns and updating their widths. Add a couple of methods in DiveTripModel for setting and getting the widths and use those. The default values are now pre-set in a QVector in the DiveTripModel() constructor. Throw warnings if out-of-bounds columns are requested. Reported-by: Gaetan Bisson <bisson@archlinux.org> Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2017-04-29Add SPDX header to desktop widgetsGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-01-28Ignore double clicks on the divelistGravatar Joakim Bygdell
Fixes #170 on GitHub Simple catch function for double click events in the divelist, prevents users from trying to edit the divenumber ithe wrong way. Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
2016-04-04Move subsurface-core to core and qt-mobile to mobile-widgetsGravatar Dirk Hohndel
Having subsurface-core as a directory name really messes with autocomplete and is obviously redundant. Simmilarly, qt-mobile caused an autocomplete conflict and also was inconsistent with the desktop-widget name for the directory containing the "other" UI. And while cleaning up the resulting change in the path name for include files, I decided to clean up those even more to make them consistent overall. This could have been handled in more commits, but since this requires a make clean before the build, it seemed more sensible to do it all in one. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-10-30Move qt-ui to desktop-widgetsGravatar Tomaz Canabrava
Since we have now destkop and mobile versions, 'qt-ui' was a very poor name choice for a folder that contains only destkop-enabled widgets. Also, move the graphicsview-common.h/cpp to subsurface-core because it doesn't depend on qgraphicsview, it merely implements all the colors that we use throughout Subsurface, and we will use colors on both desktop and mobile versions Same thing applies for metrics.h/cpp Signed-off-by: Tomaz Canabrava <tomaz.canabrava@intel.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>