Commit graph

157 commits

Author SHA1 Message Date
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
Berthold Stoeger
5e29245e68 Refactoring: move undo commands to top level
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-14 21:02:07 +01:00
Berthold Stoeger
e434b5aa40 Cleanup: introduce DiveTripModelBase::IS_TRIP_ROLE
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-11 22:44:58 +01:00
Berthold Stoeger
fdfcbd0315 Cleanup: use pointer-to-member-function in addAction() calls
Since requiring Qt >= 5.9.1, we can use the pointer-to-member-function
overloads of addAction (introduced in Qt 5.6). This has the advantage
of compile-time checking of the signal/slot parameters.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-10-20 03:51:11 -04:00
Berthold Stoeger
093adf1ea8 Map: highlight correct dive sites in dive site mode
Since changing the highlighting to use the selected dive, dive
sites with no dive were never highlighted in dive site mode.
Obviously, because there was no dive to be selected.

Therefore special-case all dive-site selection code to recognize
when we are in dive site mode.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-06 11:48:47 -07:00
Berthold Stoeger
b766525183 Selection: properly update selection flag of map location
Owing to the recent changes, when the selection flag in the
MapLocationModel was not updated correctly when the user
manually selected the dive. Do that before raising the
divesSelected signal in DiveListView::selectionChanged()
because that will cause the MainWindow to repaint the flags.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-06 11:48:47 -07:00
Berthold Stoeger
488eb15423 Desktop: show all selected dive sites on click
When clicking a dive site on the map, the QML code would set
the selected dive site, but then all dives of dive sites in
the vicinity were set. But still only the clicked-on dive site
was shown.

Therefore, don't set the list of selected dive sites in QML,
but later in DiveListView::selectDives(), where we know all
the dives that were selected.

This, again, gives nasty entanglement of diverse widgets and
models.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-06 11:48:47 -07:00
Berthold Stoeger
5da09a21bb Cleanup: move error reporting function declarations to errorhelper.h
Move the declarations of the "report_error()" and "set_error_cb()"
functions and the "verbose" variable to errorhelper.h.
Thus, error-reporting translation units don't have to import the
big dive.h header file.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-08-08 16:26:30 -07:00
Berthold Stoeger
57c22d3dcc Cleanup: avoid spurious updateDiveInfo() calls
In 2e230da361 the dive-selection signals
were unified. Sadly, this was done in a suboptimal way resulting in
numerous calls to updateDiveInfo(), which refreshes the main-tab.

Firstly, the MainWindow connected to selection changes from both,
the undo-command and the divelist. Secondly, every selected dive
in the divelist caused a single signal.

Thus, connect only to the divelist (this is necessary for user-initiated
selection changes) and only send a single signal in the divelist
per selection-reset.

This is still less than perfect as updateDiveInfo() is called even
if the current dive doesn't change.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-07-04 10:40:47 +09:00
Berthold Stoeger
2e230da361 Cleanup: unify selection signals
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-23 20:08:46 +02:00
Berthold Stoeger
e1abf9485c Undo: unify selection behavior in dive-list commands
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-23 20:08:46 +02:00
Berthold Stoeger
7f4d9db962 Cleanup: move trip-related functions into own translation unit
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-19 13:11:10 -07:00
Berthold Stoeger
403206ca06 Selection: automatically unselect old selection in selectDives()
DiveListView::selectDives() would only select new dives but not clear
the old selection. Thus, callers would have to clear the selection
first. That would lead to two selection-changed signals.

Move the unselectDives() call into DiveListView::selectDives().
The DiveListView has an internal flag to prevent double signals.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-05-11 12:06:19 -07:00
Berthold Stoeger
7924c7dafb Undo: switch to edited trip
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-04-12 18:19:07 +03:00
Rolf Eike Beer
e3d43b5696 replace deprecated qSort() with std::sort()
Signed-off-by: Rolf Eike Beer <eike@sf-mail.de>
2019-04-12 12:59:17 +03:00
Berthold Stoeger
f1fc89b978 Dive list: split DiveTripModel into distinct models (tree and list)
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>
2019-01-07 09:33:52 -08:00
Tomaz Canabrava
e0f473fcb4 Drop old filter code
Drop tons of now-unused-code.

Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
2018-12-14 01:05:18 +08:00
Berthold Stoeger
3cdc2661d2 Dive media: add media to closest dive
Currently, when selecting "Load media files even if time does not
match the dive time", the media are added to *all* selected dives.
Instead add it to the closest dive.

This seems like the less surprising behavior. Of course now if the
user really wants to add a media file to multiple dives, they will
have to do it manually.

To avoid a messy interface, this is solved by moving the iterate-
over-selected-dives loop to the core. Thus, a helper-function can
be made local to its translation unit.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-12-13 08:11:22 +01:00
Berthold Stoeger
779e33be5d Cleanup: don't leak filename on picture creation
dive_create_picture() is called from DiveListView::matchImagesToDives()
with a copy of the picture-filename. But:
  - On error the filename is not freed
  - On success the filename is strdup()ed
Thus, in all cases the memory is lost. Instead, pass in a temporary
buffer using qPrintable().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-12-11 23:59:30 +02:00
Berthold Stoeger
9e565e3552 Cleanup: make "struct dive *" and "struct dive_trip *" Qt metatypes
Just as we did for pointer to struct dive_site, make pointers to
struct dive and struct dive_trip "Qt metatypes". This means that
they can be passed through QVariants without taking a detour via
void *.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-23 13:22:24 -08:00
Berthold Stoeger
7046c8b342 Dive list: invert sort-direction to reflect core
Traditionally, the DiveTripModel has its data sorted in opposite
direction to the core-data (chronologically descending vs. ascending).
This bring a number of subtle problems. For example, when filling
the model, trips are filled according to the *last* dive, whereas
later insertion points are according to the ->when value from the
core, which depends on the *first* dive.

As a start of fixing these subtleties, change the sort direction
to reflect the core-data. Ideally, this should lead to a removal
of the redundant data-representation.

Since the model is now sorted in ascending order, sorting has to
be enabled in the DiveListView constructor to reflect the
default-descending order.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-16 16:57:14 -08:00
Berthold Stoeger
64a1a50e10 Dive list: remove sortColumn and currentOrder members
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-05 07:55:53 -08:00
Berthold Stoeger
f2f18b4e16 Dive list: split reload() in reload() and setSortOrder()
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-05 07:55:53 -08:00
Berthold Stoeger
76f38ff33b Dive list: invert default sort order for sort by date / number
Commit 6dc1d239f8 introduced a
well-defined sort order in the case of equal contents. It changed
the code for sorting by date to simply use the order of the
source model.

BUT: The source-model was already sorted in descending order
on date. Thus setting the default order on descening by date,
the data was then presented as *ascending* by date.

Change this back to descending by always using default-ascending
in the filter model.

Ultimately, the source model should simply reflect the ordering
of the core-data (ascending on date), but such a change is
too invasive shortly before release.

Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-02 07:46:01 -07:00
Berthold Stoeger
6fb3a499e6 Dive list: remove forceSort parameter from DiveListView::reload()
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-11-01 07:28:15 -07:00
Berthold Stoeger
ade0d8e758 Dive list: connect header-signal in constructor
The QHeaderView::sectionPressed() signal was connected everytime
the list-view was reset. Likewise, setSectionsClickable() was
set to true everythime the list-view was reset.

Once in the constructor is enough.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-01 07:28:15 -07:00
Berthold Stoeger
803111ef02 Dive list: make filter model aware of its source
The data-flow from C-core to list-view is as follows:

C-core --> DiveTripModel --> MultiSortFilterModel --> DiveListView

The control-flow, on the other hand, differs as DiveListView
accesses both MultiSortFilterModel and DiveTripModel, whereas
MultiSortFilterModel is mostly unaware of its source model.

This is in principle legitimate, as the MultiSortFilterModel might
be used for different sources. In our particular case, this is
not so. MultiSortFilterModel is written for a particular use case.

Therefore, model control-flow follow after data-flow: Let MultiSortFilterModel
set its own source model and DiveListView access the MultiSortFilterModel,
which then manages its source model.

This is not bike-shedding, but will enable a more flexible and
higher-performance sorting.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-01 07:28:15 -07:00
Berthold Stoeger
f8768e40b4 Dive list: remove rememberSelection() without restoreSelection()
Remove three cases of rememberSelection() which did not possess
the corresponding restoreSelection() twins.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-28 15:10:57 +00:00
Berthold Stoeger
323a71941d Dive list: remember/restore selection only on view change
The selection was remembered/restored anytime the sort-order
changed. Yet, this is only necessary if the view (tree, list)
changes. Therefore, handle the selection  only if this is the
case.

This automatically fixes the problem of the trip-selection
not being remembered if the view doesn't change. If the view
does change, trip selection is lost. But since the list view
doesn't have trips to start with, losing trip-selection seems
like an understandable behavior.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-28 15:10:57 +00:00
Berthold Stoeger
139c749c90 Dive list: show sort indicator
On desktop, show the a sort indicator to give a visual feedback on changes
of the sort order. This is trivially done by calling the
setSortIndicatorShown() function in DiveListView's constructor.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-28 15:10:57 +00:00
Berthold Stoeger
f634554d30 Dive list: switch to a default sort order on column-header click
On desktop, clicking on a column header sorts the dive-list. This
has the interesting property that every click reverses the sort
order (unless changing from list to tree-mode). The much more
common idiom seems to be to define a default sort order for each
column and switch to that when changing sort-column. Switch order
after clicking the same column again.

Implement this more common behavior. For now, sort # and date
in descending, all other columns in ascending order.

While doing this, use the proper enum (NR) for setting the default
sort-column instead of its integer representation (0).

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-28 15:10:57 +00:00
Berthold Stoeger
583d8d653a Dive list: emit selectionChanged signal in filterFinished()
In commit 9829e49815 the dive
selection code was moved from the filter to the dive list.
As a consequence of that change, the selectionChanged signal
was not emitted anymore and therefore the map widget was not
informed of the new dive site list. This had funky effects on
the dive-site editing. Notably, changing the location would
move the map, but not update the flag.

Explicitly emit selectionChanged in filterFinished() to fix
dive site editing.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-25 23:24:06 +01:00
Berthold Stoeger
6ed5db4d51 Dive list: remove three unnecessary instances of qobject_cast<>.
In DiveListView, the result of model() was dynamically cast to
QSortFilterProxyModel. But then, only the virtual match() function
was used. The whole point of virtual functions is that you can
cast them on the base-class and it will execute the function of
the derived class. Thus, remove these casts and operate directly
on the QAbstractItemModel base class.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-21 19:57:49 +03:00
Berthold Stoeger
9829e49815 Dive list: move dive-selection code from filter to list
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-21 19:57:49 +03:00
Berthold Stoeger
3c6cdfd8c0 Dive list: propagate current-item to frontend
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-11 16:22:27 -07:00
Berthold Stoeger
b16be29595 Dive list: expand trips if dives are selected
If dives are deleted, the trip(s) containing the dives are expanded.
Thus, on undo it seems natural to re-expand the trip.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
7067e33596 Undo: select dives after add, remove, merge, split dive commands
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-11 16:22:27 -07:00
Berthold Stoeger
23db0ba68d Dive list view: replace signal-magic by flag
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-10-11 16:22:27 -07:00
Berthold Stoeger
0d98da5261 Dive list: remember selected dives
Don't delesect dives, when unregistering them from the backend.
If a previously selected dive is added, select it in the dive-list.
For this purpose introduce a SELECTED_ROLE to query the DiveTripModel
for selected dives.

Unfortunately, when adding multiple selected dives, current_dive_changed
is called for each of them, making this very slow. This will have
to be fixed in subsequent commits.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
ec7d85835f Dive list: implement proper Qt-model semantics for DiveTripModel
Previously, each dive-list modifying function would lead to a
full model reset. Instead, implement proper Qt-model semantics
using beginInsertRows()/endInsertRows(), beginRemoveRows()/
endRemoveRows(), dataChange().

To do so, a DiveListNotifer singleton is generatated, which
broadcasts all changes to the dive-list. Signals are sent by
the commands and received by the DiveTripModel. Signals are
batched by dive-trip. This seems to be an adequate compromise
for the two kinds of list-views (tree and list). In the common
usecase mostly dives of a single trip are affected.

Thus, batching of dives is performed in two positions:
- At command-level to batch by trip
- In DiveTripModel to feed batches of contiguous elements
  to Qt's begin*/end*-functions.

This is conceptually simple, but rather complex code. To avoid
repetition of complex loops, the batching is implemented in
templated-functions, which are passed lambda-functions, which
are called for each batch.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
43c3885249 Undo: isolate undo-commands
This refactors the undo-commands (which are now only "commands").

- Move everything in namespace Command. This allows shortening of
  names without polluting the global namespace. Moreover, the prefix
  Command:: will immediately signal that the undo-machinery is
  invoked. This is more terse than UndoCommands::instance()->...
- Remove the Undo in front of the class-names. Creating an "UndoX"
  object to do "X" is paradoxical.
- Create a base class for all commands that defines the Qt-translation
  functions. Thus all translations end up in the "Command" context.
- Add a workToBeDone() function, which signals whether this should be
  added to the UndoStack. Thus the caller doesn't have to check itself
  whether this any work will be done. Note: Qt5.9 introduces "setObsolete"
  which does the same.
- Split into public and internal header files. In the public header
  file only export the function calls, thus hiding all implementation
  details from the caller.
- Split in different translation units: One for the stubs, one for
  the base classes and one for groups of commands. Currently, there
  is only one class of commands: divelist-commands.
- Move the undoStack from the MainWindow class into commands_base.cpp.
  If we want to implement MDI, this can easily be moved into an
  appropriate Document class.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
f427226b3b Undo: make diverse trip-related operations undo-able
AddDivesToTrip, CreateTrip, AutogroupDives, RemoveAutogenTrips
and MergeTrips basically all did the same thing as RemoveDivesFromTrip,
which was already implemented. Thus, factor our the common functionality
and hook it up to make all these functions undo-able.

Don't do the autogroup-call everytime the dive-list is rebuilt
(that would create innumberable undo-actions), but only on dive-load /
import or if expressly asked by the user [by switching the autogroup
flag].

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
014c04f8bd Undo: implement rudimentary support for undo of dive-merging
For this, an output-parameter was added to the backend merge_dives()
function. When non-zero, instead of adding the merged dive to
the preferred trip, the preferred trip is returned to the caller.

Since the new UndoObject, just like the delete-dives UndoObject,
needs to remove/readd a set of dives, the corresponding functionality
was split-off in a helper function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
302f6adb79 Undo: implement rudimentary support for undo of dive-splitting
For this, the core functionality of the split_dive() and
split_dive_at_time() functions were split out into new
split_dive_dont_insert() and split_dive_at_time_dont_insert(),
which do not add the new dives to the log. Thus, the undo-command
can take ownership of these dives, without having to remove them
first.

The split-dive functionality is temporarily made desktop-only
until mobile also supports "UndoObjects".

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
403dd5a891 Undo: fix multi-level undo of delete-dive and remove-dive-from-trip
The original undo-code was fundamentally broken. Not only did it leak
resources (copied trips were never freed), it also kept references
to trips or dives that could be changed by other commands. Thus,
anything more than a single undo could lead to crashes.

Two ways of fixing this were considered
1) Don't store pointers, but unique dive-ids and trip-ids.
   Whereas such unique ids exist for dives, they would have to be
   implemented for trips.
2) Don't free objects in the backend.
   Instead, take ownership of deleted objects in the undo-object.
   Thus, all references in previous undo-objects are guaranteed to
   still exist (unless the objects are deleted elsewhere).

After some contemplation, the second method was chosen, because
it is significantly less intrusive. While touching the undo-objects,
clearly separate backend from ui-code, such that they can ultimately
be reused for mobile.

Note that if other parts of the code delete dives, crashes can still
be provoked. Notable examples are split/merge dives. These will have
to be fixed later. Nevertheless, the new code is a significant
improvement over the old state.

While touching the code, implement proper translation string based
on Qt's plural-feature (using %n).

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
willemferguson
809471fe4d Update the dive list context menu to reflect new media interface
A minor change to the UI. The wording of the two items in the dive
list context menu "Load image(s) from file(s)" and "Load
image from web" are updated since we now deal with both images
and videos. So it becomes "Load media from file(s)".... etc.

Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-15 07:20:55 -07:00
Jan Mulder
12789a3f9f Desktop: buddies in the dive list
As proposed in RFC #1587, now also alllow buddies to be shown in the
divelist.

Fixes: #1587

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2018-09-04 15:02:07 -07:00
Berthold Stoeger
89e0c3f464 Cleanup: make DiveTripModel a global object
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-09-01 07:48:43 -07:00
Berthold Stoeger
156e053050 Dive trips: don't crash on repeated trip-removal
In the UI it is possible to remove a dive from a trip twice,
which leads to a crash, because trip is NULL (obviously).

Instead of doing a proper fix (don't show the "remove from
trip" entry in the first place), ignore dives without a
trip, since a rewrite of the undo-code is planned for the
medium future anyway.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-29 21:38:48 -07:00
Lubomir I. Ivanov
449782a892 divelistview: always show at least one column
Currently it is possible to hide all columns by unchecking them
in the context menu that appears by right clicking the header
of the divelist. But once all are hidden the header disappears.
This can cause a situation where the user cannot show any
columns and the only fix for that is to edit the application
configuration.

To avoid this sutuation prevent the last column from being hidden.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2018-08-26 23:08:24 -07:00
Berthold Stoeger
4bdd811f06 Cleanup: remove DiveListView::fixMessyQtModelBehaviour()
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-30 12:21:17 -07:00
Berthold Stoeger
5e1e6110ce Cleanup: remove parameter from currentDiveChanged signal
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-30 12:20:26 -07:00
Berthold Stoeger
58cdc67227 Cleanup: remove DiveListView::testSlot()
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-30 07:40:36 -07:00
Berthold Stoeger
67a875ef81 Dive list view: setup columns in constructor
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-27 09:08:42 -07:00
Berthold Stoeger
079b99135a Dive list view: move column width logic back from DiveTripModel
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-27 09:08:42 -07:00
Stefan Fuchs
bb2dfdfe54 For media file open dialog add different file filters
On top of the file filter for all media files add a file filter
for images only, one for videos only and one for all files.

Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
2018-07-15 09:38:12 -07:00
Stefan Fuchs
669277d490 UI change of "images"/"photo" to "media" or "media files"
This changes the above mentioned terms everywhere in the UI to
reflect the fact that Subsurface now also supports video files on top
of image files.

Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
2018-07-15 09:38:12 -07:00
Berthold Stoeger
f3ef38ca0d Dive pictures: remove hashes
In the last commits, the canonical-to-local filename map was made
independent from the image hashes and the location of moved images
was based on filename not hashes. The hashes are now in principle
unused (except for conversion of old-style local filename lookups).

Therefore, remove the hashes in this commit. This makes addition
of images distinctly faster.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-04 02:27:36 +08:00
Berthold Stoeger
08962cb38d Dive pictures: index local file name by canonical filname
The connection canonical filename to local filename was done via
two maps:
  1) canonical filename -> hash
  2) hash -> local filename
But the local filename was always queried from the canonical filename.
Therefore, directly index the former with the latter.

On startup, convert the old map to the new one.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-04 02:27:36 +08:00
Berthold Stoeger
36b9e5e31e Cleanup: fold core/helpers.h into core/qthelper.h
helpers.h included qthelper.h and all functions declared in helpers.h
were defined in qthelper.h. Therefore fold the former into the latter,
since the split seems completely arbitrary.

While doing so, change the return-type of get_dc_nichname from
"const QString" to "QString".

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-06-04 08:50:10 -07:00
Berthold Stoeger
a76f15f0f6 Cleanup: Don't defer deletion of oldModel in DiveListView::reload()
There seems to be no point in using deleteLater() of the previous
model. Set the new model and delete the old one.

This fixes a crash with Qt 5.11.

Tested-by: Gaetan Bisson <bisson@archlinux.org>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-05-25 14:15:42 +03:00
jan Iversen
cb9951a484 desktop-widgets: replace (void) with no parameter name
Unused parameters in C++ are "silenced" by removing the name.

Signed-off-by: Jan Iversen <jani@apache.org>
2018-05-24 08:34:14 -07:00
Gaetan Bisson
d3af836467 Fix includes for building against Qt-5.11.0
Signed-off-by: Gaetan Bisson <bisson@archlinux.org>
2018-05-23 13:29:37 +03:00
jan Iversen
e536682b84 desktop-widgets: Change Q_UNUSED to no parameter name
C++ permits use of parameters without name, which signals unused

Signed-off-by: Jan Iversen <jani@apache.org>
2018-05-21 12:48:04 -07:00
Jeremie Guichard
12dc1889c7 Add "Tags" column in Desktop app's dive list view
Add DiveItem::displayTags helper method to return Tags as a QString
New Tags column is
 by default inserted before "Photos" column
 by default disabled

Signed-off-by: Jeremie Guichard <djebrest@gmail.com>
2018-04-04 14:10:45 +03:00
Berthold Stoeger
d1572a8d95 Cleanup: introduce copy_qstring() function
strdup(qPrintable(s)) and copy_string(qPrintable(s)) were such common
occurrences that they seem worthy of a short helper-function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-03-14 13:55:36 +02:00
Berthold Stoeger
b72cc1f317 Cleanup: consistently use qPrintable()
Replace constructs of the kind
  s.toUtf8().data(),
  s.toUtf8().constData(),
  s.toLocal8Bit().data(),
  s.toLocal8Bit.constData() or
  qUtf8Printable(s)
by
  qPrintable(s).

This is concise, consistent and - in principle - more performant than
the .data() versions.

Sadly, owing to a suboptimal implementation, qPrintable(s) currently
is a pessimization compared to s.toUtf8().data(). A fix is scheduled for
new Qt versions: https://codereview.qt-project.org/#/c/221331/

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-03-14 13:55:36 +02:00
Berthold Stoeger
f5eafe2a71 Cleanup: Fold add_hash() call into learnHash() function
learnHash() was always called in conjunction with add_hash(). The
pattern was that a local filename and a hash were connected in
the hash-to-filename and the filename-to-hash maps. Then, the
original picture-filename or url were registered in the filename-to-hash
map.

This commit changes learnHash() to take three parameters (original-filename,
local-filename and hash) and do all of the above. The new code is
simpler because no dummy picture struct has to be generated in
DiveListView::loadImageFromURL().

The tests were extended to check for all hash<->filename associations.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-03-05 18:04:57 +02:00
Berthold Stoeger
0a2e53caf2 Use QDir::exists() instead of QDir::setCurrent() to check for existence
Don't change into a directory just to see if it exists.
Remove unnecessary braces of one of the changed if statements.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-04 18:35:44 +01:00
Berthold Stoeger
ed92b60bfe Fix typo "LastIamgeDir"->"LastImageDir"
This fixes an actual bug, where the current image dir would only be
remembered on closing the program.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-04 18:35:44 +01:00
Dirk Hohndel
752d9b60c4 Divelistview: use report_error to report and error
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-10-26 15:53:47 +02:00
Jan Mulder
87db35de3c Fix broken multi selected dive to trip
See referenced issue number. It leads back to an ancient (3 year old)
commit 512c42e. Not sure this issue is introduced there, but that's not
relevant.

Key in reproducing this is the location where the context menu is
requested (using the right mouse button). When it is the row next
to the trip, the add-to-trip succeeds correctly, otherwise
it is a no-op.

The solution is rather trivial (in hindsight). Just loop over the
selected dives, and try to find the trip we want to add to.

Fixes: #522

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2017-10-23 10:06:33 -04:00
Lubomir I. Ivanov
52445ec8f5 dive-list: maintain a single instance of DiveTripModel
A weird crash occurs if DiveListView creates another local
instance of DiveTripModel inside reload(). Re-use the member
variable tripModel and assign it a new instance of DiveTripModel.

Reported-by: Gaetan Bisson <bisson@archlinux.org>
Tested-by: Gaetan Bisson <bisson@archlinux.org>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2017-10-03 21:34:43 -07:00
Lubomir I. Ivanov
e3118d915c divelist: prevent a crash for missing column width
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-10-03 15:43:03 -07:00
Robert C. Helling
462797396b File selector should filter images we can actually handle.
So better ask Qt about image formats known to it.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2017-05-06 08:07:16 -07:00
Dirk Hohndel
53ae83e038 Fix call to tr in order to create translation strings
Fixes #365

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-04-29 13:59:02 -07:00
Dirk Hohndel
9021a44ccc Add SPDX header to desktop widgets
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-04-29 13:32:55 -07:00
Dirk Hohndel
b8af3733ec Silence warning about unused parameter
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-03-11 08:51:46 -08:00
Joakim Bygdell
b0ec7146a0 Ignore double clicks on the divelist
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>
2017-01-28 07:20:03 -08:00
Robert C. Helling
f3cf9525de Images from web currently only works for single pictures
so we should not suggest otherwise by plural form.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
2017-01-12 14:06:54 -08:00