Instead of having people treat latitude and longitude as separate
things, just add a 'location_t' data structure that contains both.
Almost all cases want to always act on them together.
This is really just prep-work for adding a few more locations that we
track: I want to add a entry/exit location to each dive (independent of
the dive site) because of how the Garmin Descent gives us the
information (and hopefully, some day, other dive computers too).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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>
Comits f427226b3b and 43c3885249 of the undo series introduced 2 calls
of autogroup_dives() without checking the autogroup global boolean.
This is a bug. An import from DC (for example) then triggers an
autogrouping, the divelist is autogrouped, and the UI button
is off.
This commit solves this. I've chosen for a guard in the autogroup_dives()
that now is a no-op when called when the user did not select autogrouping.
In additon, simplified the other calls to this function, as we do
not need to check before calling any more.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Instead of the weirdly named "information" and the inconsistent
"dive_list" use the logical "mainTab" and the camel-cased
"diveList", respectively.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The keeps track of different sub widgets needed by other parts
of the code, notably:
MainTab
PlannerDetails
PlannerSettingsWidget
ProfileWidget2
DivePlannerWidget
DiveListView
Access to these widgets was provided with accessor functions.
Now these functions were very weird: instead of simply returning
pointers that were stored in the class, they accessed a data
structure which describes the different application states.
But this data structure was "duck-typed", so there was an
implicit agreement at which position the pointers to the
widgets were put inside. The widgets were then down-cast by
the accessor functions. This might make sense if the individual
widgets could for some reason be replaced by other widgets
[dynamic plugins?], but even then it would be strange, as one
would expect to get a pointer to some base class.
Therefore, directly store the properly typed pointers to the
widgets and simply remove the accessor functions. Why bother?
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
SsrfFilterSortProxyModel was a thin wrapper around QFilterSortProxyModel,
which was intended as a convenience class to avoid deriving from the
latter. The filter and sort functions were replaced by simple function
pointers.
Unfortunately, by using function-pointers, the whole thing was rather
weak as these functions do not have state. The last user was removed
in ac8dcd7f65b78958587ba025280ed4c529b0b519. Therefore, remove the
whole class.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The location information shows a list of dive sites at the
same location as the edited dive site. This was done by passing
a function to an "SsrfSortFilterProxyModel". Unfortunately,
the latter does only support function pointers without state
and therefore had to access the global "displayed_dive_site"
object.
Replace the SsrfSortFilterProxyModel by a proper subclass of
QSortFilterProxyModel that contains information on the position
and id of the currently edited dive site.
Update the filter model if the location of the dive site changes.
This introduces a behavioral change: editing the GPS location
will lead to an updated list.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Planned dives were still added by directly calling core code.
This could confuse the undo-machinery, leading to crashes.
Instead, use the proper undo-command. The problem is that as
opposed to the other AddDive-commands, planned dives may
belong to a trip. Thus, the interface to the AddDive command
was changed to respect the divetrip field. Make sure that
the other callers reset that field (actually, it should never
be set). Add a comment describing the perhaps surprising
interface (the passed-in dive, usually displayed dive, is
reset).
Moreover, a dive cloned in the planner is not assigned a
new number. Thus, add an argument to the AddDive-command,
which expresses whether a new number should be generated
for the to-be-added dive.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, the filter is recalculated if a filter-entry is changed.
This also happens if the counts of a filter-entry changes. This
is to be avoided, as it causes unnecessary churn.
Therefore, send the proper role with the dataChanged() signal
and add a new slot, which invalidates only if a field with the
Qt::CheckStateRole is changed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of reloading all the filter, only increment / decrement the
count of the entries of added / removed dives.
Originally, this was planned to be done via the signals from the
divelist, but it turned out that this was suboptimal, because
if the filter decides that the new item is selected, this has to
be done *before* adding the dive. Otherwise, it wouldn't be shown.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
The current code cheats when it comes to move dives inside
a trip or move dives between trips: Instead of using the
*MoveRows() functionality, the dives are removed from and
re-added to the respective trips. This loses the selection.
Therefore, remember which of the moved dives are selected
and select them manually after they are re-added.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
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>
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>
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>
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>
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>
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>
For increased maintainability, use the same columns, roles and
the same accessor function for both dive-site models.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The LocationInformationModel added two dummy sites to the front
of the list (add new dive site). This was never used - desktop
uses its own model, mobile only extracts the list of dive site
names with a custom function. Remove this functionality.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Editing of dive sites does not work via this model and the function
was broken anyway (it didn't subtract 2 from the index).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If only selected dives were exported into HTML, the statistics would
nevertheless cover all dives. A counter-intuitive behavior. Fix by
adding a selected_only flag to calculate_stats_summary().
Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Statistics were calculated into global variables every time the
current dive was changed.
Calculate statistics only when needed and into a structure
provided by the caller.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
process_imported_dives() is more efficient for downloaded than for
imported (from a file) dives, because it checks only the divecomputer
of the first dive.
This condition is checked via the "downloaded" flag of the first
dive. Instead, pass an argument to process_imported_dives().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Dives are now in all cases imported via distinct dive_tables.
Therefore the "preexisting" marker is useless. Remove.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Dives were directly imported into the global dive table and then
merged in process_imported_dives(). Make this interface more flexible,
by passing an independent dive table.
The dive table of the to-be-imported dives will be sorted and merged.
Then each dive is inserted in a one-by-one manner to into the global
dive table.
This actually introduces (at least) two functional changes:
1) If a new dive spans two old dives, it will only be merged to the
first dive. But this seems like a pathological case, which is of
dubious value anyway.
2) Dives unrelated to the import will not be merged. The old code
would happily merge dives that were not even close to the
newly imported dives. A surprising behavior.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
process_dives() is used to post-process the dive table after loading
or importing. The first parameter states whether this was after
load or import.
Especially in the light of undo, load and import are fundamentally
different things. Notably, that latter should be undo-able, whereas
the former is not. Therefore, as a first step to make import undo-able,
split the function in two versions and remove the first parameter.
It turns out the the load-version is very light. It only sets the
DC nicknames and sorts the dive-table. There seems to be no reason
to merge dives.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These also showed up as concerns when creating translation strings.
Adding them thankfully didn't create new strings, but not having them
potentially leads to incorrect runtime behavior.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
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>
All callers of FilterModelBase::updateList() sorted the items
(except the last one). Thus we can do the sorting inside the
function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since FilterModelBase now contains complex data (counts and checked),
we might just as well make it a full model and keep track of
the name as well. I.e. do not derive from QStringListModel but from
QAbstractListModel and add the name to the item structure.
Implement proper reset / add / rename semantics. This is overkill at the
moment, as after all any modification the model will be reset, but
ultimately it will allow us to be smarter and only update rows when
needed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Valgrind found use of some uninitialized variable (probably
ds->gf_low_pressure_this_dive ), see #1614. Zero is the correct
value to start with. Lacking a working version of valgrind I cannot
check this actually fixes the problem.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
Currently, in FilterModelBase::data() the number of dives is recalculated.
This happens for every mouse-over event!
Calculate the number of dives only on recalculation and store the count
in the items-struct.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In the future, we might be smarter about the dive-counts and calculate
them only once and incrementally (if e.g. new dives are added).
Prepare for more complex caching by turning the checked boolean into
a struct, which can then be extended by a count and other things
(e.g. the name).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is another entry in the series to make more things
"const-clean" with the ultimate goal of merge_dive() take
const pointers.
This concerns functions taking pointers to events and
the fallout from making these const.
The somewhat debatable part of this commit might be
that get_next_event() is split in a two distinct
(const and non-const) versions with different names,
since C doesn't allow overloading. The linker should
recognize that these functions are identical and remove
one of them.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In a previous commit, the get_gasmix_* functions were changed to
return by value. For consistency, also pass gasmix by value.
Note that on common 64-bit platforms struct gasmix is the size
of a pointer [2 * 32 bit vs. 64 bit] and therefore uses the
same space on the stack. On 32-bit platforms, the stack use
is probably doubled, but in return a dereference is avoided.
Supporting arbitrary gas-mixes (H2, Ar, ...) will be such an
invasive change that going back to pointers is probably the
least of our worries.
This commit is a step in const-ifying input parameters (passing
by value is the ultimate way of signaling that the input parameter
will not be changed [unless there are references to said parameter]).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The filter code was an unholy intermixture of backend and frontend
logic, which made it hard to access it from outside of the UI.
Notably, it expected that Qt would call filterAcceptsRow on all rows.
For trip-view, apparently the filter functions were called twice
(once for filtering the trip, then for filtering the individual dives).
Make the filtering explicit, by calling showDive() for all dives in
MultiFilterSortModel::myInvalidate(), setting the hidden_by_filter
flags accordingly and ultimately invalidating the filter.
The UI code only accesses the hidden_by_filter flag set previously.
The "justCleared" flag can then be removed, since accessing the filter
does not have side effects. Moreover, there is no noticeable performance
gain by returning out early.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
remove use of SettingsObjectWrapper::
remove include of SettingsObjectWrapper.h
use qPrefFoo:: for setters and getters
replace prefs.foo with qPrefXYZ::foo() where feasible
(this expands to the same code, but gives us more control
over the variable).
Signed-off-by: Jan Iversen <jani@apache.org>
To make dive-filtering accessible from other parts of the code,
break out the actual dive-filtering code into a function that
takes a pointer-to-dive instead of QModelIndex.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Conceptually, the doFilter() functions shouldn't modify the dive
they test. Therefore, make the argument const. To do this, constify
the parameter of get_dive_location(), which likewise seems to be
the right thing to do.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Change the signature from of the virtual doFilter() functions from
bool doFilter(struct dive *d, QModelIndex&, QAbstractItemModel*) const;
to
bool LocationFilterModel::doFilter(struct dive *d) const;
as the QModelIndex and QAbstractItemModel parameters were not used.
This makes this functions independent from Qt's model/view
framework. This is in preparation for making the undo-machinery
compatible with the filtering.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
remove DivePlanner from SettingsObjectWrapper and reference qPrefDivePlanner
update files using SettingsObjectWrapper/DivePlanner to use qPrefDivePlanner
this activated qPrefDivePlanner and removed the similar class from
SettingsObjectWrapper.
Signed-off-by: Jan Iversen <jani@apache.org>
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>