This is a messy commit, because the "qPref" system relies
heavily on QString, which means lots of conversions between
the two worlds. Ultimately, I plan to base the preferences
system on std::string and only convert to QString when
pushing through Qt's property system or when writing into
Qt's settings.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is a humongous commit, because it touches all parts of the
code. It removes the last user of our horrible TABLE macros, which
simulate std::vector<> in a very clumsy way.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This makes memory management more simple, as not explicit deletion
is necessary.
A rather large commit, because changing QVector<> to std::vector<>
is propagated up the call chain.
Adds a new range_contains() helper function for collection
types such as std::vector<>. I didn't want to call it
contains(), since we already have a contains function
for strings and let's keep argument overloading simple.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was very weird: a setSelection() call was always followed
by a selectionChanged() call, though sometimes in convoluted
ways. Notably, the formed was called by the DiveListView, the
lattern then by the MainWindow.
Let's just merge these two functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The uiLanguage() function was used for two purposes: to initialize
the language related preferences and to read the current language.
To make things more easy to follow, split this function in two:
one for initializing, one for getting the current language.
Moreover, don't return the current locale in an out-parameter
as there is already a function to do that [getLocale()].
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
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>
Let's face it: this is a value type. No point in having Java-style
getters and setters. Replace by plain old and boring member variables.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
When changing the selection the MapLocationModel was reset.
This lead to crashes on Qt-5.9 which are due to QML accessing
data that was freed during model reset. This putative Qt bug
doesn't happen on newer Qt versions. At least Qt-5.12 is known
to work.
Instead of fighting the bug, let's simply not reset the model
but send a dataChanged() for every element of the MapLocationModel.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Experimentation has shown that the image of a flag will
only be changed after dataChanged() if it is a simple
property. The old code had a complex QML expression and
then - for some reason - it didn't work.
To give us better control over the flags and avoid full
reloads of the map therefore introduce a model-property
pixmap name. The name depends on whether the site is
selected and if not, whether we are in divesite-edit mode.
This makes the code rather convoluted. Firstly, we have
to save whether the site is selected in the map-item.
Secondly we have to access the global map-widget, which
in turn has to go to the map-widget helper (layering
violation!).
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When clicking on a flag
1) The QML would call MapLocationModel::setSelected() with
fromClick = true
2) MapLocationModel::setSelected() would emit a signal
selectedLocationChanged()
3) MapWidgetHelper would catch that signal and do the actual
processing.
Other functions would call MapLocationModel::setSelected() with
fromClick = false, which would not emit the selectedLocationChanged()
signal.
Detangle this a bit by calling the selectedLocationChanged() function
directly from QML and remove the fromClick parameter.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There weree two functions in MapWidgetHelper: one to enter and
one to exit edit mode. Both functions set the flag and emitted
a signal if the flag had changed.
Since the edit mode only depends on a flag of the filter this
can be simplified to a simple function that updates the flag
and raises the signal if the flag changed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of multiple string-concatenations, create the string object
from a single string literal.
Yes, this is a mostly pointless "optimization". But it saves a few
bytes.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, dive site names are only updated on full reload.
Instead hook directly into the corresponding signal in the
MapLocationModel to set the name. Also to the coordinates
directly there instead of going via the MapWidgetHelper.
In the MapWidgetHelper, just center on the changed dive site.
Hook into the signal directly there and remove the slot
from the MapWidget. This makes the whole call-chain at least
one call shorter.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Move the code to add the first selected dive site from
MapWidgetHelper::enterEditMode() to MapLocationModel::reload().
Thus, the list of sites is built only at one place. For this
it is necessary to pass a pointer to the map, so that new
dive sites can be added at the center of the map.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
In MapWidgetHelper::centerOnSelectedDiveSite() the selected dive
sites were recalculated. Simply use the ones we already know are
selected.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since the dive-site-filter is active either on the dive-site-edit
page or the dive-site-list page, use that as the flag for dive-site-edit
mode. Moreover, when the filter is reset, the
MapWidgetHelper::reloadMapLocations() function is called, so we
can use that place to enter/exit edit mode.
This makes it easier to keep everything consistent.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When entering map-edit mode and the dive site existed, its
coordinates were extracted but never used. Remove that useless
if-branch.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This member variable was only used locally in functions.
Accordingly, make it a function-local variable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
MapWidgetHelper::selectVisibleLocations() calls setSelection()
on a single dive. Firstly, this make no sense anymore, as
we now support multiple highlithed flags. Secondly, the
highlted dives are now derived from the selected dives.
Therefore, remove the call.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
To detangle this code a little bit, let centerOnSelectedDiveSite()
just do what is says: center on the selected dive sites.
Don't update the selected dive site by calling
MapLocationModel::setSelected().
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The map model keeps track of the dive site positions on the
map. Therefore, it seems more logical to have the code calculating
the map position in the model, not in the helper-class.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When on the dive site tab or editing a dive site, we want
to show all dive sites so that the user can related different
dive sites. Therefore export a "in dive site mode" flag from
the filter model and don't filter in that case in MapWidgetHelper.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The dive_site_has_gps_location() function already checks for the null
dive site. Remove redundant checks.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When the dive site was not on the map because it had no dives,
entering dive site edit mode would place the map at the center
of the map, not at the location of the dive site.
Use the location of the dive site unless it has no location.
In that case use the map center.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since no dive site field editing enters edit mode anymore,
the whole edit mode state and code can be removed from the
widget.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
printGPSCoords() returned a newly allocated C-style string. Most
callers simply made a QString out of it and freed the C-style string.
This is paradoxical, as printGPSCoords internally works with QStrings
and converts them to C-style on return.
Therefore, let printGPSCoords() return a QString and create a
printGPSCoordsC() wrapper for the two C-callers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The printGPSCoords() function returns a copied C-style string. Since
the owndership is transferred to the caller, the correct return type
is "char *" instead of "const char *".
Thus a number of casts when calling free can be removed.
Moreover a number of callers didn't free the string and thus were
leaking memory. Fix them. Ultimately we might want two versions
of the function: one for QString, one for C-style strings.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Since "struct dive_site *" is now a Q_METATYPE, the functions
MapWidgetHelper::centerOnDiveSite() and ::getCoordinates()
can directly get such a pointer instead of a QVariant. This
makes the code nicer to read.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace the UUID reference of struct dive by a pointer to dive_site.
This commit is rather large in lines, but nevertheless quite simple
since most of the UUID->pointer work was done in previous commits.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
MapWidgetHelper::reloadMapLocations() used an array of uuids to
add dive sites to the map only once. Replace this by an array
of pointers. This is a small piece of a larger effort to remove
dive site UUIDs.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace UUIDs by pointers to dive-site in mobile code. In both
cases, the value is transported via a QVariant. The function
getCoordinatesForUUID(), which was only used from mobile, can
be replaced by a getCoordinatesFor() function taking a variant
supposed to contain a dive-site pointer. Likewise, the variant
of the centerOnDiveSite function is now supposed to wrap a
pointer-to-divesite.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There are two updateDiveSiteCoordinates() member-functions, viz.
in MapWidget and MapWidgetHelper. Adapt them to take a pointer
to dive_site instead of a UUID. This is part of an effort to
replace UUIDs by pointers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Replace the uuid argument to MapWidgetHelper::enterEditMode() by a
pointer. Likewise, adapt the only caller prepareForGetDiveCoordinates().
This is a small step in a bigger effort to replace dive-site UUIDs
by pointers.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
Commit 0aef04352a made it impossible
to move new dive sites on the map. When entering dive-site-edit mode,
the filter would be instructed to show only dives of the corresponding
dive site [which didn't yet exist] and therefore all dive sites
on the map were deselected.
Fix this by explicitly centering on the dive site to be edited in
MapWidgetHelper::enterEditMode().
Fixes#1809
Reported-by: Jan Mulder <jlmulder@xs4all.nl>
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
MapWidgetHelper::reloadMapLocations() reloads all dive flags
of the non-hidden dives plus the one of the currently edited
dive. Use the current_dive macro to determine whether this
is the current dive site instead of the global displayed_dive_site
object.
This is part of a series of commits, which makes the map-code
independent of the global displayed_dive_site object.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Instead of reading out the global object "displayed_dive_site",
pass the dive site to be edited in arguments to
prepareForGetDiveCoordinates() and enter edit mode.
Simplify the code in LocationInformationWidget by not using
signals to call the prepareForGetDiveCoordinates() function.
While doing this, collect common code in accept() and reject()
in the already existing resetState() function.
This is another entry in a series of commits that makes
data-flow more clear by removing access to the global
"displayed_dive_site" object.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The setEditMode(bool) function behaves very differently, when
entering and exiting edit mode. Therefore, split it in two
versions. This will allow to pass arguments that make sense
only when entering the edit mode.
Since setEditMode() doesn't exist anymore, turn the editMode
Q_PROPERTY line to the MEMBER version. Accordingly, remove
the reader function. If QML wants to enter edit mode, it
should invoke the appropriate function and not simply set
the flag.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The coordinates of a "dragged flag" were passed out-of-bound via
the global "displayed_dive_site" object and then a signal was sent
to notify of the changed coordinates.
Instead, pass the coordinates directly via the signal. This makes
the data- and control-flow more clear.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was used by LocationInformationWidget to instruct the map
that the coordinates of the current dive site has changed.
There is no reason why this couldn't be a function call, as no
other object ever connect()s to this signal. In fact, such a
function already exists viz. updateLocationOnMap.
Therefore, replace the signal by a simple function call.
Moreover, the uuid and coordinates of the dive site were transported
via the global "displayed_dive_site" object. Instead, pass this
information in the parameters of the function. This makes it
easier to reason about data- and control-flow.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The dive site list was connected to centerOnDiveSite(). Apparently,
the currently selected dive site should have been shown in the map.
Yet, this never worked, because the actual dive site of the selected
dive had precedence in centerOnDiveSite().
It seems that centerOnDiveSite() had actually to purposes:
1) center on the passed in dive site
2) center on the dive sites of the selected dives
Therefore, split this function in two separate functions for
each of these use-cases. This allows us to remove some pre-processor
magic (mobile vs. desktop) and to remove a parameter from the
MainTab::diveSiteChanged() signal.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
If the dive list is filtered the map should hide dive locations
that do not match the dive list filter.
To achieve that, loop over dives instead of dive sites in
MapWidgetHelper::reloadMapLocations() and discard
dives that are hidden by the filter. Then check if a dive
has a dive site attached to it and re-use the old functionality.
Suggested-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
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>
centerOnLocationHard() is added in MapPage.qml so that
on `firstRun` the map is hard panned to the desired location
without animation.
This affects the selection of a new "Dive details" -> "Map it" or
when opening a GPS location in the map.
The idea behind this change is to avoid starting the map animation
from an arbitrary location such as [0,0] or London. Also, to not
start the map zoomed out completely and then zoom in on a selected
dive.
For this change to work, add the helper getCoordinatesForUUID()
to qmlmapwidgethelper.cpp/.h and use it to obtain the
QGeoCoordinates for a dive site UUID.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>