Commit graph

43 commits

Author SHA1 Message Date
Berthold Stoeger
635d67ee7f Dive list: clear internal data when clearing model
The DiveListModelBase::clear() implementation was flawed: It cleared
the data in the core, but left the data in the model untouched.
The code was relying on the fact that the caller would reset the
model manually. Not a good idea.

Therefore, clear the internal data to keep the model consistent at
all times.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19 21:13:40 -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
8a33c04894 Cleanup: use DiveTripModelBase::clear() to reset the log
Introduce a DiveTripModelBase::clear() function that cleanly
clears all dive data inside a beginResetModel()/endResetModel()
pair. Thus, the UI will be cleanly reset and we can remove
explicit calls to
 - graphics->setEmptyState()
 - mainTab->clearTabs()
 - mainTab->clearTabs()
 - diveList->reload()
from MainWindow::closeCurrentFile().

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-16 08:29:53 -08: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
a474264cc8 Cleanup: fix typos in comment
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-11 22:44:58 +01:00
Berthold Stoeger
f27d440bb3 Dive site: don't emit divesChanged signals when editing dive site
When editing the dive site, for certain fields a divesChanged signal
was emitted so that the dive-list can be updated.

Arguably it is wrong to decide which fields are relevant to the
dive list in the undo-command code. Therefore, let the list
catch the dive-site-edited signal and decide itself.

But the actual reason for this commit is that if the dive-site
field of a dive changes, we might have to reload the dive-location-model
because suddenly a new dive site appears. Now if this is done
in QML context on some Qt version (notably 5.9) we get crashes
later on. But that can happen if the user moves a flag. So in that
case only send a diveSiteChanged signal.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-06 11:48:47 -07: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
27944a52b1 Undo: don't send signals batched by trip
Since the default view is batched by trips, signals were sent trip-wise.
This seemed like a good idea at first, but when more and more parts used
these signals, it became a burden. Therefore push the batching to the
part of the code where it is needed: the trip view.

The divesAdded and divesDeleted are not yet converted, because these
are combined with trip addition/deletion. This should also be detangled,
but not now.

Since the dive-lists were sorted in the processByTrip function, the
dive-list model now does its own sorting. This will have to be
audited.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-06-23 20:08:46 +02:00
Berthold Stoeger
cbcddaa396 Dive list: cache shown flag in model (quick-fix for undo-crash)
We have a very fundamental problem with data-duplication in
core and qt-models. In a particular case, this led to an easily
reproducible crash:
1) An undo command moved the last dive of a trip to another.
2) When an undo-command removed the last dive of
   a trip to a different trip, the dive was removed from the
   trip in the core. Then, the model was updated.
3) That lead at first to a rearrangement of the trips, because
   the trip with the added dive is moved before the trip with
   the removed dive.
4) In such a case, the filter-model checks the visibility of
   the trip.
5) Since the trip with the removed dive has no dives in the core,
   visibility was determined as false.
6) From this point on the mappings of the QSortFilterProxyModel
   were messed up. Accesses led to crashes. It is unclear
   whether this is a Qt bug or only a QOI issue.

As a quick-fix, cache the visibility flag of trips directly
in the Qt-models. Don't set the visibility directly in the
core, but go via the Qt-models. Thus, a more clear layering
is achieved.

In the long run, we can hopefully get rid of the data-duplication
in the models.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-06-23 20:08:46 +02:00
Berthold Stoeger
e7063b6b08 Undo: update dive list if trip changed
In tree-mode, the trip locations are displayed. Update the corresponding
entries if the trip changed, by hooking into the tripChanged() signal.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-12 18:19:07 +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
Berthold Stoeger
911edfca71 Dive list: update position of trip if data changed
If the date of a dive changed, it might be necessary to reorder
the trips, as the date of the trip changed. Although this seems
like an odd usecase, move the trip if necessary, for consistency's
sake.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-18 16:50:09 -08:00
Berthold Stoeger
64e6e435f8 Core: remove "when" field of struct dive_trip
The when field gives the time of the first dive. Instead of keeping
this field in sync, replace it by a function that determines the time
of the first dive.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-18 16:50:09 -08:00
Berthold Stoeger
243962a67a Dive list: move sort-functionality into core
To make sorting more controlled, move all sorting functions into
the core. For this, introduce a "dive_or_trip" structure, which
represents a top-level item. Adapt the DiveTripModel accordingly.
There are now three sorting functions:
	1) dive_less_than
	2) trip_less_than
	3) dive_or_trip_less_than
These should be used by all sorting code. By moving them to a
single place, the mess can hopefully be cleaned up.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-18 16:50:09 -08:00
Berthold Stoeger
ab894c9b64 Dive list: implement custom lessThan function
The dive list was sorted using the default-sorter of
QSortFilterProxy model. This is mighty inflexible as it
considers only one column. This has the funky effect that
for rows with identical elements, the sort order depends
on the previous sorting.

Implement a lessThan() function in the MultiFilterSortModel,
which simply hands the sorting down to the actual model.
This might be considered a layering violation, but it makes
things so much easier.

Sadly, it seems like the column-to-be-sorted is transported
in the provided indices. Therefore, the comparison is chosen
using a switch for *every* comparison. It would seem much
more logical to set a function pointer once and use that.
Further investigations are necessary.

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
7f2026ded8 Cleanup: remove DiveTripModel::layout() function
This accessor was never used. This is a small step in splitting
the DiveTripModel in two (list & tree), which means that the
layout is moved up to the view.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-28 15:10:57 +00:00
Berthold Stoeger
2f81890f49 Dive list: update trip headers on filter-finish
On change of the filter, the headers of non-extended trips were not
updated. Therefore, on filter-finish-event loop over all trips
in DiveTripModel and signal data-changed.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-21 19:57:49 +03:00
Berthold Stoeger
32df0ab0da Cleanup: remove DiveItem and TripItem classes
The DiveItem and TripItem classes were wrappers around dive * and
dive_trip * used to extract tabular data. With the rework of
DiveTripModel they lost all their state besides the pointer itself.
The usage was:
	DiveItem item(d);
	item.data(...);
This can now be simplified to the much more idiomatic
	diveData(d, ...);
and analoguously for TripItem.

While adapting the data() function to be part of DiveTripModel, change
the
	QVariant ret
	switch(...) {
	...
	case ...:
		ret = ...;
		break;
	...
	}
	return ret;
style to
	switch(...) {
	...
	case ...:
		return ...;
	}
Not only is this shorter and easier to reason about, it generally also
improves the generated code. The compiler can directly construct the
return value in the buffer provided by the caller. Though modern
compilers start to be very good at avoiding unnecessary copies.

In total this cleanup results in a net-reduction of 190 lines of code.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-14 15:57:14 -04:00
Berthold Stoeger
f836b9ae97 Dive list: unify sorting in core and Qt-model
Ultimately, we want to use a single dive-list and not replicate
it in the Qt-model code. To this goal, let's start with using
the same sort function.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07: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
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
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
4fbb8ef399 Dive list: hand-code the DiveTripModel
The dive list is fed data by means of a sorted "DiveTripModel".
There are two modes: list and tree. This was implemented rather
elegantly with a general "TreeModel", which can represent trees
of arbitrary depths.

Nevertheless, we have at most two levels and on the second level
only dives can reside. Implementing proper model-semantics
(insert, delete, move) will be quite a challenge and implementing
it under the umbrella of a very general model will not make it
easier.

Therefore, for now, hardcode the model:
At the top-level there are items which may either be a trip
(can contain multiple dives) or a dive (contains exactly one dive).

Thus, we can completely de-virutalize the DiveItem and TripItem
classes, which are now trivial wrappers around dive * and dive_trip *.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
c341bc53c3 Dive list: replace dive-id by dive pointer
The undo-system now guarantees that pointers to dives are stable
throughout their lifetime. Therefore, replace the unique index by
pointers. This is a small performance improvement, but much more
importantly, it will make it more natural to transport a pointer
to the dive inside QModelIndex's private pointer.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11 16:22:27 -07:00
Berthold Stoeger
574065b314 Cleanup: reinstate override modifiers
This reverts commit 1c4a859c8d,
where the override modifiers were removed owing to the noisy
"inconsistent override modifiers" which is default-on in clang.

This warning was disabled in 77577f717f,
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-29 15:23:25 -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
1c4a859c8d Cleanup: remove all override modifiers
Commit df156a56c0 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-08-01 06:30:00 -07:00
Berthold Stoeger
df156a56c0 Cleanup: replace virtual by override where appropriate
The keyword "virtual" signalizes that the function is virtual,
i.e. the function of the derived class is called, even if the
call is on the parent class.

It is not necessary to repeat the "virtual" keyword in derived
classes. To highlight derived virtual functions, the keyword
"override" should be used instead. It results in a hard compile-
error, if no function is overridden, thus avoiding subtle bugs.

Replace "virtual" by "override" where appropriate. Moreover,
replace Q_DECL_OVERRIDE by override, since we require reasonably
recent compilers anyway. Likewise, replace /* reimp */ by
"override" for consistency and compiler support.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-31 11:02:34 +02: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
Berthold Stoeger
7dd49acf4b Cleanup: remove DiveItem::icon_names member array
Each DiveItem (which is a wrapper around diveId with some virtual
functions), had a member icon_names, which is an array of
four QStrings. These were not used anywhere and must be an obscure
oversight and was probably planned as a static cons array?.
In any case, remove it.

There *was* a function-local analogous icon_names array in
DiveItem::data() though. This array would initialize four
QStrings from C-string literals on every invocation. Make
this array static, local to the translation unit and use
the QStringLiteral macro to construct the QString object at
compile-time.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-23 17:05:15 +03: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
Stefan Fuchs
78cda85444 Display units in dive list table based on prefs option
Add a preferences option which enables or disables display of units in the
main dive liste table.

Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
2017-10-09 11:49:29 +03: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
Tomaz Canabrava
d5ab03ef4e [Divesite] Hook qt model for country
See #144

Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-10-02 09:52:58 -07:00
Dirk Hohndel
5372f12d8b Add SPDX header to Qt models
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-04-29 13:32:55 -07:00
Willem Ferguson
1fa855e1c0 Provide photos summary on dive list
1) Add an extra column to dive list, just left of Locality field.
2) For each dive, give summary of photos as follows:
   i)   no photos: no icon in that column
   ii)  photos taken during dive: show icon of fish
   iii) photos taken before/after dive: show icon of sun
   iv)  photos taken during as well as before/after dive: show
     icon with both fish and sun
3) Provide information for the sort operation to work on
   this column of the dive list.

Signed-off-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2016-11-24 09:58:16 +09:00
Dirk Hohndel
7be962bfc2 Move subsurface-core to core and qt-mobile to mobile-widgets
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>
2016-04-04 22:33:58 -07:00
Jan Mulder
604971ca0c Add missing tr() implementations
One specific string did not translate. First, Dirk and I (via IRC)
suspected a leading space was the issue (see commit eccac1321f).
However, I found out that the problem was still there. A non translated
string "%1 shown", when applying a filter on the divelist, and looking at
a trip line. It shows always untranslated "%1 shown". Extracting
to-be-translated strings from the code, I found 2 errors: Class
<classname> lacks Q_OBJECT macro.

This patch adds a missing tr() definition and implementation to 2 structs.

Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-10-23 22:48:41 +09:00
Tomaz Canabrava
85d4bb8a70 Move DiveTripModel to qt-models
Signed-off-by: Tomaz Canabrava <tomaz.canabrava@intel.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-05-29 14:13:00 -07:00