Commit graph

136 commits

Author SHA1 Message Date
Berthold Stoeger
646aead629 desktop: disable animation when selecting multiple dives
Selecting many dives when the animation was active
was increadibly slow, so disable it.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-10 14:33:15 -08:00
Berthold Stoeger
e943065977 cleanup: remove "GpsLocation *locationProvider" from MainWindow
This is mobile only and not used on desktop.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-01 12:38:50 -08:00
Berthold Stoeger
16f86f2f65 desktop: use getDiveSelection to access selected dives
In the list view two functions were still manually collecting
the selected dives. Use getDiveSelection() there as well.

Careful: that means that the check for dives that are already
outside of a trip now has to be done in the RemoveDivesFromTrip
command.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-12 15:52:40 -08:00
Berthold Stoeger
369c5b0dc6 desktop: init dive list header actions in constructor
The main window called a function to init the header actions
(i.e. the context menu) of the dive-list. There is no reason why
this shouldn't be done in the constructor of the dive list, since
it only accesses the QSettings, which are available at application
startup. This improves modularity of the code (by a tiny, tiny bit).

Moreover, the initialization function was at the same time the
header-reloading function. That function can now be folded
into the settings-changed function, since that is the only
remaining user.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-12 15:52:40 -08:00
Berthold Stoeger
2d7be7a0e3 preferences: create global settingsChanged signal
So far, the PreferencesDialog emitted a settingsChanged signal.
This meant that models that listened to that signal had to
conditionally compile out the code for mobile or the connection
had to be made in MainWindow.

Instead, introduce a global signal that does this and move
the connects to the listeners to remove inter-dependencies.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-12 15:52:40 -08:00
Dirk Hohndel
f193c2ef08 cleanup: fix deprecated QVector constructor
Annoyingly, the replacement has only been available since Qt 5.14.
To make the code less messy, implement our own stdToQt conversion helper.

Suggested-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-10-26 19:27:03 -07:00
Dirk Hohndel
5aaff77b9e cleanup: replace deprecated use of child member
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-10-26 19:27:03 -07:00
Berthold Stoeger
00abc04913 cleanup: use getDiveSelection() to loop over selected dives
getDiveSelection() returns a vector of the selected dives.
Use that instead of looping over the dive table and checking
manually.

This removes a few lines of code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-03 10:01:13 -07:00
Berthold Stoeger
7b196a5ef9 desktop: allow moving dives to arbitrary trips
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-10-03 10:01:13 -07:00
Berthold Stoeger
06c35026d6 desktop: fix paging through dive list with page-up key, etc
In the dive list we have horrible code, which intercepts all events
to save the selection before/after the event. This was necessary
because we couldn't get Qt's selection data flow under control.

This means intercepting all events that can change the selection.
The page-up, page-down, home and end keys were forgotten. Add these
cases.

Fixes #2957.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-02 11:10:28 -07:00
Berthold Stoeger
eb22c0205e cleanup: remove unnecessary includes in divelistview.cpp
Most of these became unnecessary when including media in the
undo system.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-29 14:12:56 -07:00
Berthold Stoeger
7417f865cd cleanup: un-singletonize ShiftTimesDialog
There is no reason that this dialog is a singleton. Since it is modal,
it can be created on demand. Apart from removing superfluous global state,
this simplifies code, because preparing the widget can now be done in
the constructor instead of overriding the showEvent() function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-27 09:47:35 -07:00
Berthold Stoeger
25f1bc488f cleanup: un-singletonize RenumberDialog
There is no reason that this dialog is a singleton. Since it is modal,
it can be created on demand. This simplifies code, because the mode
(selected-only or all-dives) can be set in the constructor.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-27 09:47:35 -07:00
Berthold Stoeger
4374605c12 undo: make adding of pictures undoable
This one is a bit hairy, because two things might happen if the
picture has a geo location:
- A dive gets a newly generated dive site set.
- The dive site of a dive is edited.
Therefore the undo command has to store keep track of that.
Oh my.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
74f03e3537 media: move addition of pictures out of create_picture()
If we want to make addition of pictures undoable, then create_picture()
must not add directly to the dive. Instead, return the dive to which the
picture should be added and let the caller perform the addition.

This means that the picture-test has to be adapted.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-06 13:58:09 -07:00
Berthold Stoeger
769915f3fe selection: create global single_selected_trip() function
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-05-03 15:02:21 -07:00
Berthold Stoeger
5147131701 selection: inform core of trip selection in DiveListView
When selecting / deselecting trips, keep the core updated.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-03 15:02:21 -07:00
Berthold Stoeger
f961ec7a8b selection: introduce clear_selection() function
The DiveListView would touch the selection-innards directly.
Let's encapsulate that. Moreover, take care to reset the trip
selection when resetting the core data.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-03 15:02:21 -07:00
Berthold Stoeger
2021035cfc selection: replace selectedTrips() by singleSelectedTrip() function
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-26 13:54:59 -07:00
Berthold Stoeger
6e83135fba desktop: select dives at once
The old code would call QItemSelectionModel::select() once for every dive.
Instead collect the selection in a QItemSelection and only call
QItemSelectionModel::select() once. This makes selecting multiple dives
significantly faster.

The loop also expanded the trips with selections. This has now to be
done in an extra loop.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-26 13:54:59 -07:00
Berthold Stoeger
4f438d1e32 dive list: don't access selected dives via indices
When determining the selected dive sites to highlight them on the
map, the DiveListView code used the local indices of the selected
dives. However, that was unreasonably slow. Even though a layering
violation, let's access the core data structures directly. In my
tests this improved from 700 ms to 0 ms!

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-26 13:54:59 -07:00
Berthold Stoeger
5d49da5d6b selection: move test for programmatical selection changes to widget
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-26 13:54:59 -07:00
Berthold Stoeger
b8e7a600d2 cleanup: remove DiveListView::selectDives()
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-25 13:20:25 -07:00
Berthold Stoeger
702d8c754d desktop: remove selectionChangeDone() from DiveListView::selectDive()
This was erroneous, as it should only be called at the end of
a selection change, not after every single dive. It made selection
of multiple dives extremely slow.

Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Debugged-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25 10:23:05 -07:00
Berthold Stoeger
9fae262188 desktop: fold DiveListView::selectDive into DiveListView::selectDive
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-25 10:23:05 -07:00
Berthold Stoeger
f8d3501c22 desktop: remove scrollto default parameter of DiveListView::selectDive()
No caller was using that parameter.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25 10:23:05 -07:00
Berthold Stoeger
e26ac9e58d desktop: remove selection-code to select a new current_dive
The undo-machinery makes sure that a current_dive always exists
after an undo command. This part of the code should never be
called.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25 10:23:05 -07:00
Berthold Stoeger
c00737eb23 desktop: don't select current dive after collapsing trips
This appears to be an artifact. Collapsing does not unselect
the current dive, so reselecting it appears pointless.
Also it is unclear why the selection should be restricted to
a single dive after collapsing.

Probably that was originally meant to expand only the trip
with the current dive in it?

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-25 10:23:05 -07:00
Berthold Stoeger
ca336d13e5 Dive list: add option to mark dives valid
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-20 15:20:44 -07:00
Berthold Stoeger
4e47cdfa2c Undo: implement invalidate-dive command
Connect command to context menu.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-20 15:20:44 -07:00
Robert C. Helling
285fa8acbc Grammar: replaces 'indexes' by 'indices'
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-11 08:26:30 -07:00
Berthold Stoeger
2b3dc019db selection: update selection on key-presses
Commit 2cea115ddb "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-03-01 10:23:53 -08:00
Berthold Stoeger
2cea115ddb Dive list: be more careful on when updating the UI after selection
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 4928c4ae04
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-08 14:06:18 -08:00
Berthold Stoeger
670a5bd55a Dive sites: select each dive site only once
After selecting dives, the selected dive sites are collected.
This was done using the selectionModel()->selection().indexes(),
which is wrong, because it gives one index per row *and* column.
Accordingly, every dive site was added numerous times to the
array of dive sites to be selected. Change this to
selectionModel()->selectedRows(), which gives one entry per row.

Moreover, if multiple dives with the same site were selected,
this site was also added to the array multiple times. Therefore,
check the array before adding sites.

Note that all this should not change the user experience in
any way, it is only a code-hygiene thing.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-02-04 02:18:28 +01:00
Dirk Hohndel
afd53be6f5 code cleanup: QFontMetrics::width() is deprecated
Qt5.11 introduced the suggested replacement QFontMetrics::horizontalAdvance().

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-01-10 02:37:03 +09:00
Berthold Stoeger
0f417a3bc1 Dive list: access header via filter-model
The dive list accesses the filter model, therefore it makes sense
to also get the header data from there, even if they are only
forwarded from the source model.

This makes control flow more logical and will allow us to remove
the global DiveTripModel instance.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-10 18:45:30 -08:00
Berthold Stoeger
71307bce42 Dive list: don't handle selection changes on filter-change in view
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-10 18:45:30 -08:00
Berthold Stoeger
28e97e7555 Cleanup: remove DiveListView::expandedRows member variable
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-04 13:00:23 +01:00
Berthold Stoeger
be26b0bd9a Cleanup: remove DiveListView::mouseClickSelection member variable
That hasn't been used since 2013 (9cc04c1ca6).

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04 13:00:23 +01:00
Berthold Stoeger
75dac8906e Cleanup: remove toggle parameter from DiveListView::selectDive()
This defaulted to false and no caller used anything different.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04 13:00:23 +01:00
Berthold Stoeger
364a8270d1 Cleanup: remove DiveListView::remember/restoreSelection()
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-04 13:00:23 +01:00
Berthold Stoeger
a83bc5ecdb Selection: don't reset selection when resorting
The old code saved, cleared and restored the selection. This
is not necessary anymore, because on model reset the selection,
which is stored in the core, is reset. Remove the unnecessary
selection handling.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04 13:00:23 +01:00
Berthold Stoeger
e46b1e88d9 Selection: move translation of indexes to filter model
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-04 13:00:23 +01:00
Berthold Stoeger
a431840075 Selection: move initialization of selection from view to model
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-04 13:00:23 +01:00
Berthold Stoeger
755f185cfc Selection: move selection of "first" dive to core
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-12-04 13:00:23 +01:00
Berthold Stoeger
86f384f932 Cleanup: rename newCurrentDive signal to currentDiveChanged
This is more consistent with the rest of the signals.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04 13:00:23 +01:00
Berthold Stoeger
4b1a3a1a6e Selection: move selection functions from divelist.c to selection.c
Since we now have a selection.c translation unit, put the selection-
related functions there.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04 13:00:23 +01:00
Berthold Stoeger
4928c4ae04 Desktop: Improve speed of selecting multiple (or all) dives
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-11-28 12:15:24 -08:00
Berthold Stoeger
3003c6e1ee Filter: move recalculation of filter from FilterModel to TripModel
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-19 21:13:40 -08:00
Berthold Stoeger
b76f207158 Filter: split out filter from model
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-19 21:13:40 -08:00