In certain places the '(int)' cast is used, while in other the
llrint() or lrint() functions. Make the conversation from degrees
in the 'double' form to the 'int' degrees_t consistent using lrint().
lrint() is the function which should give the best results,
because it accepts a 'double' and results in a 'long'
even if degrees_t is 'int'. If the truncation from 'long' to 'int'
is discarding some of the precision then the next step
would be to turn degrees_t into a 64bit signed integer type.
Possible fix for #625.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Commit cf8e87545f implemented a way to cancel pin setup,
and this also has effects on an exit from the app after pressing
the android exit. The change button started with clearing the
email and passwd in order to get the credentail page(s) active
again. While this worked ok, it confuses users that exit the
app from the credential pages, resulting in the need to enter
the credentials again after a restart. It appears that clearing
the credential state is sufficient to get the pages active.
Notice that the android exit is still not working (it seems
a no-op), but the interaction with the buttons in the app
preserves the email/passwd.
Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za>
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
The old credential status should only be set when changing the
actual credential status using the setCredentialStatus function.
Setting it here is just wrong. It sets the old status to the
current, and than adds the current to the prefences,
obviously, resulting in old = current, which can not be right
and results in a wrong flow of control in the credential state
processing.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
If the QML modules for QtLocation and QtPositioning are
missing the QML in mapwidget.cpp will fail to load,
which can lead to crashes.
To solve the issue check if the QML has loaded and set
a flag 'isReady' to true. If the loading has failed
load another QML which is for showing a red error text
in the lines of `MapWidget.qml failed to load!`.
If the map QML has failed, use a macro in all relevant
MapWidget members to turn them into a NOP. This approach
leaves the rest of the codebase intact - e.g. no checks
in classes which connect to the MapWidget class.
Fixes#596
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This commit is empty when shown with '-w' - it just updates the
indentation after commit c00804eff6 ("QML UI: always start edit at top
of page").
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
When starting to edit / add a dive, the Flickable needs to be positioned
at the top of the page, not the last position shown.
For clarity I'll do the re-indentation in the next commit.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The hard switch was not ideal. This isn't perfect, yet, but a step in
the right direction. The 'transitions' to change the visibility
properties are a bit odd, but that's how it's done in the examples as
well.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
We need a white path drawn on the dark action button, but a black path
drawn for the main menu.
(looks like a white space change snuck in here)
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This addresses some review comment on whitespace and translated
string formatting.
In the string formatting, a tiny additional change is made.
I wanted the email address in the explanation text in a bold
font. Using the HTML <b> for this, removed the /n newline
characters in the output. Apparantly, mixing these two
formatting styles does not work. No problem, replaced the
/n to HTML style too.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This commit tries to implement most of issue #515. It reworks the
one credential page, which its dynamic PIN part, into two pages.
Main driver of selecting one of the two pages is the showPin
boolean. Page 1 contains the email/passwd field (and the
option to use a no cloud setup). Page 2 only contains the PIN
part (and the option to cancel the process).
The Kirigami central button does not seem very handy here. We
need, for example, a cancel, sign-in and register, only register,
etc. buttons, which are not easy to handle in specific icons.
Therefore, normal pushbuttons are chosen to deal with user
interaction, and the Kirigami button is removed from these
pages.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Previously, we could edit the cloud credentials in basically two
places. At startup of the app from a fresh install (and no previous
data on the device), and from the settings. Issue #515 proposes
only one way.
However, we need a way to access the new credential UI pages, so
that the pages at a fresh install of the app can be reused,
for example for account switching.
This commit replaces the settings cloud credentials block by
a simple (not editable) display of the current credentials, and
a button to access the initial pages, for all management tasks
on the credentials.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This commit is just a precaution. It makes sure that the old
(aka previous) credential status is correctly set on all changes
of this status.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This is a very subtile bug. Testing/developing on the desktop for mobile,
with a normal logbook in a git repo, resulted in a surprising effect.
When swichting from a cloud account to a NOCLOUD situation, the no cloud
repo was (not always) reset to the NOCLOUD_LOCALSTORAGE, but to the
normal logbook. Resuling in commits in the wrong repo.
This can easily be solved by setting the filename to NOCLOUD_LOCALSTORAGE,
when switching to NOCLOUD mode.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
In case the credential state is NOCLOUD, the saving of credentials
in the preferences was suppressed in case of invalid data in the
email/passwd fields.
There is no reason to check these fields for correct input, as they
are not used in case of NOCLOUD mode. A simple if statement is added.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
As written in 8d9ad3cfea7e4c0875, the user needs to be able
to exit the PIN entry UI, in case no PIN can be received due
to a wrong email address.
The simplest way seems to just clear the cloud credential data,
and let the user try again. Obviously, we could argue if the
exact previous state of the 1st credentials screen could
be restored, but as it is only 2 simple fields, of which
it is higly likely that the email adress is misspelled (and
the password hidden), it seems overly complex to implement.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Makes sure that the CS_NEED_TO_VERIFY status is carried forward
and sets the showPin flag that triggers the 2 different states
in de QML UI.
The new credential UI will have one page for username/passwd,
used for setting up an account or switchting to a different
account, and a second page to enter a PIN only.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
In case the credential status is UNKNOWN, and the cloud username
and password are empty, do not go automatically to NO_CLOUD status.
This is (again) preparation for future work on credential management.
For example, the user entered an email address with a spelling
error, so does not receive a PIN code email. This user needs a
way out, so there needs to be a <cancel> button on the PIN code
screen. And the most logic was of cancelling is emptying the
entered username/passwd and let the user try again.
Without this change, the user immediately gets into the (somewhat)
final NO_CLOUD state, which will result in (very) confused users.
With this change, there is exacly one way (left) to get into a
NO_CLOUD setup: hitting the proper button, so a deliberate user
action.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
It appears that the onCompleted of the StartPage item is triggered
before the onCompleted of the rootItem. This is logical as the
Startpage is a child of the rootItem. And, yes, this does matter.
As the divelist also contains the logic for initial cloud
registration (and is the default page shown in a state where
the cloud credentials are valid (CS_VERIFIED state)), we need to
know the correct credential state at start of the app.
The move of this one line of code makes sure of that, in addition
to setting the credential state from the preferences. Now, the
setupActions function can reference correct credential data.
This is further preparation for a better cloud creation
process from mobile.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
MapWidgetHelper::calculateSmallCircleRadius() uses
the second argument (boolean) of QDeclarativeGeoMap::toCoordinate()
and QDeclarativeGeoMap::fromCoordinate(), which isn't supported
in Qt 5.5.x and errors will be thrown on runtime.
This argument usage is redundant for the calculateSmallCircleRadius()
use case.
If the argument is set to "false" it tells the map to avoid
clipping the viewport and always return a valid QPointF/QGeoCoordinate.
Given that calculateSmallCircleRadius() only works with the
map center - i.e it's called like so in MapWidget.qml:
onZoomLevelChanged: mapHelper.calculateSmallCircleRadius(map.center)
The only way for the radius estimation to fail is if the map widget
width is smaller than SMALL_CIRCLE_RADIUS_PX * 2 = 52px, which is not
possible as the MainWindow splitter prevents it.
If the map widget becomes that small it would be hardly usable,
yet no errors should be thrown related to this change.
Tested-by: Stefan Fuchs <sfuchs@gmx.de>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Following on beb0d5703a, the context menu seems to work fine
with a much older QtQuick import - version 2.0.
The 2.7 import is technically a development leftover
and a minimal version should have been considered earlier.
On older Qt setups (e.g. 5.5.x) this might throw a:
'module "QtQuick" version 2.6 is not installed'
Reported-by: Stefan Fuchs <sfuchs@gmx.de>
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Having two different enums around with more or less the same
definition has lead to unclear code. After removing two not needed
states on the mobile end, the remaining step to one enum for the
credential state becomes almost is simple rename operation.
Unfortunately, I do not know a way to embed a plain C enum
from pref.h into the QMLManager object. So after this, there
are still 2 enums around, but now identical.
This commit is not changing any functionality.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
And here, the removal of a second superfluous state from QMLManager.
This is true no-brainer. While this state was set once troughout the
entire mobile code, it was never tested for this state. Testing shows
that it is safe to change to the UNKNOWN state.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This is a no-brainer removal of the VALID_EMAIL state used in QMLManager.
All current usage of this state is "if state is VALID or VALID_EMAIL",
so there is no distinction between the two states.
It is even a little different. The comment suggests "when we can open
a local cloud storage, tied to a cloud account (so explicitly not
the no-cloud status), we have at least a valid email". While this
is formally true, this implies that there is also a cloud account
on the cloud server (ie. the cloud account is in a VERIFIED state).
In other words: currently, there can't exist a valid local storage
that is tied to a valid email adress, without valid cloud account
on the server.
Notice that this touches the discussion on GitHub for commit
e76f527fe5 (pull request #520). Can we implement the creation
of a valid cloud account without data link to the cloud server?
Currently, we need the server to confirm the email address (for
example for uniqueness reasons on server side). Obviously, we could
hack our way out of this, but we have a perfect solution already
in place. Create a no-cloud account, and transfer that later to
a true and valid cloud account.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
When we want to go the NOCLOUD credential state, do not go the
incorrect INCOMPLETE state.
This is the first in a series of unraveling the preference parameter
prefs.cloud_verification_status and the data that is carried around
in the QMLManager::credentialStatus_t.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
The default location which is used when the
PluginParemeter "googlemaps.cachefolder" is not specified
should be ~/.cache/googlemaps on Linux or
/user/<name>/appdata/local/cache/googlemaps on Windows.
This patch moves the cache to the default system location
where we store the printing templates, cloudstorage and the
default user XML file.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The googlemaps plugin is about to support tile language
via the PluginParameter 'googlemaps.maps.language'.
To be able to pass the subsurface UI language (obtained
from the uiLanguage() helper) the Plugin has to be created
dynamically, only *after* the MapWidgetHelper is created.
MapWidgetHelper::pluginObject() now provides a QString which
contains the Plugin object and also include the uiLanguage
ISO value.
This string is used in mapwidget.qml as:
map.plugin = Qt.createQmlObject(pluginObject, rootItem)
This creates the Plugin object dynamically with the proper
UI language string, but also requires a couple of small changes:
- move the declaration of map.mapType after the
Qt.createQmlObject() call
- assign map.activeMapType after map.mapType has a value
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Looking for already existing locations with
m_mapLocationModel->getMapLocationForUuid() will not cover dive
sites which are too close to each other and are skipped when
creating MapLocations. See reloadMapLocations() and the usage of
MIN_DISTANCE_BETWEEN_DIVE_SITES_M.
Constructing a new QGeoCoordinate for the already retrieved
dive site (ds) coordinates ensures that we are traversing
*all* dive sites at the backend and not only those visible on the map.
Fixes the issue where not all dives in the DiveList are selected,
even if a dive clearly happened on a location currently visible in
the map viewport (map -> context menu -> select visible dive
locations).
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The QML Map has a couple of methods - toCoordinate(someQPointF) and
fromCoordinate(someQGeoCoordinate). Ideally, if one passes a point to
toCoordinate() and then attempts to convert the resulted coordinates
back to the point, the same point in the Map view port with minimal error
should be retrieved. That's not always the case - e.g. near
47.400200 -123.142066, which means that the methods are not exactly
*reliable* and there might be Map class bugs at hand.
The new zoom-in and zoom-out improvements try to work around the above:
- for both centerOnRectangle() and centerOnCoordinate(), if no good
zoom-out level is found (newZoomOut), the zoom-out is set to the default
value of defaultZoomOut. In practice, this prevents the case where the map
does not zoom-out at all when going from one place to another
- centerOnRectangle() now uses rectangle diagonals to estimate a fit,
instead of checking if 2 points (top-left and bottom-right) are visible
in the viewport. The usage of fromCoordinate() was giving bad results
in this case and comparing distances (diagonals) is more reliable
but more expensive on the CPU.
Due to the inconsistencies of toCoordinate() and fromCoordinate()
the dynamic zoom-in and zoom-out are still not ideal, but the current
implementation is somewhat usable with decent accuracy.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This appears to fix the mystery crashes that can occur when deleting a dive
from the dive list.
Fixes: #497
Signed-off-by: Rick Walsh <rickmwalsh@gmail.com>
This gets rid of TypeError messages, but does not appear to affect behaviour
qrc:///qml/DiveDetailsEdit.qml:254: TypeError: Cannot read property 'dive' of null
qrc:///qml/DiveDetailsEdit.qml:228: TypeError: Cannot read property 'dive' of null
qrc:///qml/DiveDetailsEdit.qml:216: TypeError: Cannot read property 'dive' of null
qrc:///qml/DiveDetailsEdit.qml:204: TypeError: Cannot read property 'dive' of null
Signed-off-by: Rick Walsh <rickmwalsh@gmail.com>
MapWidgetContextMenu now has a new action (SELECT_VISIBLE_LOCATIONS),
that will invoke the MapWidgetHelper method selectVisibleLocations().
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The new method selectVisibleLocations() contains a routine
to find all visible MapLocation objects in the Map viewport and
select the dives associated to said MapLocation objects.
This method is to be invoked from the QML context menu.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
First, this function calculates the zoom out effect until both the
current Map center and the target rectangle are visible - see the
"calculate zoom out" part.
Then it calculates a zoom level, so that the target rectangle
fits the viewport, but also so that the zoom is not too much (clamped).
see the "calculate zoom in" part.
NOTE: "centerStored" (the variable used to store the current map center)
is created using QtPositioning.coordinate(), because the code needs a new
object and not a reference of the map.center QGeoCoordinate object.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Add stopZoomAnimations(), which is really just a precaution
function to make sure we have stopped all animation of the
map before doing calculations! Since the animation *should*
be running in a separate thread, this would make sure the Map "center"
and "zoomLevel" properties do not change.
Add pointIsVisible(), which is a helper to determine
if a point created by map.fromCoordinate() method is inside
the viewport. fromCoordinate() has to be called without the
"false" (clip) flag for this to work.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
MapWidgetHelper::centerOnDiveSite() now checks if more than
one dive sites are selected and finds the most top-left and
bottom-right ones in the coordinate system to form
a rectangle.
It also supports the special cases where a selected dive site
does not have coordinates or the case where only a single dive site
with GPS coordinates are selected.
TODO: implement mapwidget.qml::centerOnRectangle()
This QML function will receive a QGeoCoordinate based rectangle which
has to be centered in the viewport with animation.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
For instance, if the 'googlemaps' geoservices plugin is missing
a new message is now shown:
"qml: MapWidget.qml: cannot find a plugin with the name 'googlemaps'"
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Do so until the following issue is resolved:
https://github.com/vladest/googlemaps/issues/9
With the satellite map ([1]), the black tiles at relatively high
zoom levels over the Red Sea cannot be seen. Instead it shows white
tiles at the ultra-maximum zoom level at places.
As a side note, the "satellite" map does not have the country labels
which the "hybrid" map has.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
No idea why this was restricted to be so narrow. Also, making
the font of the label smaller and lighter seems visually more
pleasing.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This makes sure that the autocompleting comboboxes never displays the scroll list where the user can pick an entry, and as such forces the view of a autocompleting textfield from the users point of view. The reasoning is that when scrolling in the drop down list it it possible to scroll to far and thus abort the ongoing edit by flicking away the edit page.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Mobile devices hare rather limited when it comes to screen size,
there is no point in reducing the availabel space more than neccecary.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
This handles a cornercase where a user starts editing and then cances the divedit followed by a return to edit mode. The previously acive textfield would then be active again even though all changes are lost.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
For some reason the textfields on dive edit page did not loose focus when editing ended by press on the return key.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
When the user makes a selection using the autocomplete function while editing a dive the keyboard should close and the selection list should disappear.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Add star icons from the material repository.
https://material.io/icons/
The icons are under Apache License Version 2.0
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
This patch makes use of the geolocation plugin "googlemaps"
for Qt Location with source code from here:
https://github.com/vladest/googlemaps
The change from the ESRI plugin is that it requires new indexes
for the Hybrid ([3]) and Street ([0]) map types.
There are more zoom levels in this plugins, but our default zoom-in
settings seem to transition well to it.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
In commit e76f527fe5, the scenario of switching between 2 already
VERIFIED cloud accounts was identified, which was working poorly. It
needed a restart of the app to get the new account visible.
Reason for this, was the setting of the credentialStatus to the value
of an undefined (never set) old credentialStatus. This commit makes
sure we have a defined credentialStatus, just before changing it to
the new one.
A really mini step forward, as the behavior is still not perfect. Now,
the user has to select the dive list manually, after entering
credentials of the new clould account.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
The PIN (and cloud account creation) is not limited to the
desktop (any more). Correct the string accordingly.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
I thought we had this automated, but Lubomirs commits introduced a few
files with dos line endings. This is purely a change of line endings, no
other changes.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The C++ side for the desktop version already does that. Add a slot
for that in QML, for later use in the mobile version.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The editing support is added via dragging. It is handled via the
MouseArea's drag.target of the MapQuickItem. The drag target changes
with the model selectedUuid.
"mapAnimationZoomIn" now also does an initial zoom-out before moving
to a new location.
centerOnCoordinate() now pefroms calculations to determine how much
the animation needs to zoom out. What it does is it reduces the Map
zoomLevel util both the current and the new target coordinates are visible.
It then restores the zoomLevel and performs animation based on newZoomOut.
animateMapZoomIn() is now obsolete.
The patch also includes the following smaller changes:
- remove the setSelectedUuid() call in deselectMapLocation()
This is now handled in C++
- sets "defaultZoomIn" to 12.0
- use ">=" when determining if a mapItem text should be visible
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The MapWidgetHelper QML instance now has the slot onEditModeChanged()
which toggles the visiblity of a newly added message box that
notifies the user if editing mode is enabled.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
updateCurrentDiveSiteCoordinates() should be called from
QML when a marker changed it's location. it emits the coordinatesChanged()
signal, which should be tracked in the MapWidget class. The MapWidget
class should emit the same signal to the MainWindow (Marble does that).
editMode is now a boolean property, which should put the QML map into
editing mode.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The marble globe tracks dive sites with the same name and discards
such that are less than 50 meters apart.
We already store names in MapLocation objects, but using a
QMap<QString, MapLocation *> to check the names is probably faster
with the expense of using more memory.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Call setSelectedUuid() from C++ also center on coodinates instead
on a MapLocation, as there is no point to pass the MapLocation object
back to QML.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The MapItemView delegate now includes a white Text element.
It uses the MapLocation "name" property as text.
This text is only visible if the map zoom is above "textVisibleZoom".
For hundreds of dives, using the DropShadow effect for the text
makes it laggy. Instead, using a fake drop shadow (duplicate black
Text under the default text) makes it much better.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The MapLocation QObject now has a QString property "name", which is
translating the dive_site->name member.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The buttons are positioned bellow the "toggle map type" button
and increment / decrement the zoom by "zoomStep" (2 for now).
Also clamp the zoom-in level to "map.maximumZoomLevel".
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Double clicking a marker or the newly added MouseArea now performs
a +2 zoom-in over a period of 500ms and centers on that clicked
coordinate.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Different actions might be performed depending on the count of selected
dives - e.g. deep zoom only for a single selected dive.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The signal emits a QList<int> filled with dive idexes from the
main backend dive table.
The MapWidgetHelper QML instance handles that in onSelectedDivesChanged().
This will only be needed for the mobile version, as the desktop version
should connect it's own slot in MapWidget.cpp.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Based on a current location (MapLocation), iterate the dive list
and add nearby dives (distance smaller than m_smallCircleRadius) to
a local QList property (m_selectedDiveIds).
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The idea of this flag is to be able to only to emit the
selectedLocationChanged() signal when the user clicked on the map
(fromClick == true).
MapWidgetHelper::selectedLocationChanged() listens for this signal
and only then it will select nearby dives based on a "small-cicle".
If "fromClick" is false, it's the backend or the dive list that
updated the selection and MapWidgetHelper::selectedLocationChanged()
should no be called.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Each time the zoom changes MapWidgetHelper::calculateSmallCircleRadius()
is called, and the "small circle" radius is stored in both C++ and QML.
On the C++ side this radius will be used to select multiple nearby
dives.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Based on a QGeoCoordinate, calculateSmallCircleRadius() calls
some QML Map methods to obtain how big a circle is in meters if
a circle is drawn over the Map widget with radius SMALL_CIRCLE_RADIUS_PX
pixels.
This is called a "small circle" of a sphere:
https://en.wikipedia.org/wiki/Circle_of_a_sphere
This "small circle" radius becomes huge if the map is zoomed out, while
quite small if the map is really zoomed in.
The idea behind this circle is to be able to select multiple nearby dives,
when clicking on the map (TODO).
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Use QGeoCoordinate::distanceTo() to skip dive sites
which are too close (50m) to dives sites which are already added
as MapLocations.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This method uses the helper printGPSCoords() to format the
coordinates of a location into either decimal or sexagesimal.
The selection is handled by the boolean flag "formatTraditional"
and the user preferences flag - prefs.coordinates_traditional.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
openLocationInGoogleMaps() now can be used to open a URL in an
external browser, triggered by the context menu. Use the same
Google Maps URL formating as in main.qml showMap().
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The actionSelected() signal is now dispatched when the user selects
an action from the menu (see the "actions" object). Then the declaration
of the MapWidgetContextMenu object in mapwidget.qml can catch that
signal in the onActionSelected() slot and obtain the action via
switch() branching.
The actions enumeration is kept in QML for now, with the idea that
specific C++ methods from the mapwidgethelper class will be called
directly (if marked as Q_INVOCABLE), instead of a generic
onMapAction(action) C++ method in the helper. But if the actions
are possible from QML (like copying to clipboard) and are also
small and non-expensive, it might be better to keep them
in mapwidget.qml.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
- move the readonly properties near the top of the root Item
- move the rest of the properties bellow the readonly properties
- make the ListView Timer as a child of the ListView
- slight rename of the timer ID
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
NOTES:
- the ListView object uses lsitItemDelagate to display all elements from
the model listModel
- onCountChanged() is used to adjust the x position based on the
maxItemWidth property which is calculated when the items are populated
with text
- onVisibleChanged() is used to deselect the last selected item by
calling listModel.selectedIdx = -1
- onOpacityChanged() i sued to make sure that the View is hidden if the
opacity becomes 0.0
- inside the View there is a MouseAre which obtains the selected item via
indexAt(x,y)
- there is a Timer with id listViewVisibleTimer, which is called each
time the user selects an item from the list and the timer performs a
"delayed hide"
- a couple of State and a Transition objects are used to preform smooth
fade-in / out animation when the ListView is hidden or becomes visible
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This property would act like a state flag. If -1 (default) no QML State
animation will be pefromed, otherwise the ListView will either fade in
(1), or fade out (0) when the user clicks the context menu button
(Image) or selects an item from the list.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The ListView delegate is a simple Component with a parent Rectangle.
It contains a text field with the ListView action.
This patch also defines some properties for the delegate animations
and looks. The property maxItemWidth tracks the width of all item
text, and makes the width of all items be of that value.
The above prevents potential issues when a fixed width item is used
and some translated language string cannot be fit inside of it.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Menu item indexes are enumerated in the object menuItemIndex, while
menuItemData, holds an array of objects which will define the number
of items, with indexes (idx) and text (itemText).
When the ListModel is created, it's dynamically populated from
from menuItemData.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The anchor of the menu itself will be positioned near the edge of the
map widget, while the menu contents will have negative coordinates.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This QML component will be used to provide a context menu for the
QML map widget. Include the file in QRC and test it's creation
in MapWidget.qml.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Make the "enumeration" local to the Map object for now.
This will possibly break if another plugin is used in place of the
ESRI plugin, but it will simplify the map toggle button which is about
to be implemented next.
If support for multiple plugins is added on runtime a simple
helper function will be needed that will check the current plugin "name".
And return the appropriate supportedMapTypes[X] for e.g. STREET of that
plugin.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The QML based map will have a toggle in the top left corner to toggle
between the satellite and steet tiles.
The images are created specifically for use in this Qt Location widget
and are free for use in Subsurface.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The animation sequence when deselecting a zoomed in map location, should
be:
- zoom out completely
- pan to center
To achieve that a new animation object is created - "mapAnimationZoomOut"
The previous zoom in animation is renamed to "mapAnimationZoomIn".
The map functions centerOnMapLocation() and deselectMapLocation()
now call the helper functions animateMapZoomIn() and animateMapZoomOut().
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
If a divesite doesn't have a GPS location we want to deselect
the currently selected markers and zoom out the map. In the Map
QML object the function deselectMapLocation will handle that.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
It's best to only animate the flags when clicked, thus play the animation
in the onClicked() slot from the MouseArea.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
To be used to center the map on a dive location or reset the map
if a dive from the dive list doesn't have GPS coordinates.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
When centering on a map location, use the predefined zoom
map.defaultZoomIn.
Later the map should be able to center on (0, 0) and zoom-out
if a dive doesn't have GPS data.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The rest of the QML code in subsurface doesn't use the ';' to
end a line of code or a declaration. Remove all the redundant ';'.
Also clean extra blank lines.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
If a marker is clicked it's source image changes, which will
call the onSourceChanged() slot. If a marker is selected
play the newly added sourceItemAnimation which is a short scale
animation for the image.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
These properties will be used when zooming-in on a map location
or when zooming out if no map location is selected.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The function in QML centerOnCoordinate() is now renamed
centerOnMapLocation() and accepts a MapLocation object, so that
a marker is selected (based on UUID).
In MapWidgetHelper::centerOnDiveSite(), the pointer to a MapLocation
is retrieved via MapLocationModel::getMapLocationForUuid(). Added in the
previous commit.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
When MapLocationModel updates the selected marker, MapWidgetHelper now
receives a signal. The slot is named selectedLocationChanged().
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Add a MouseArea to the MapItemView delagate and onClick set
the "mapHelper.model.selectedUuid" to the uuid of the clicked marker.
This updates the "selectedUuid" property inside MapLocationModel.
Based on "mapHelper.model.selectedUuid" it is now possible to
show two seprate images for selected / deselected markers.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The "uuid" property will be the one from the dive_site. At first it
will also be used to track the active marker/flag selection.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The image for the unselected marker is now a slightly darker flag.
Same behaviour as the current Marble implementation.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Rename the QML function "centerOnCoordinates" to "centerOnCoordinate"
and pass a QGeoCoordinate to it in ::centerOnDiveSite().
This will prevent the creation of a QGeoCoordinate object on the
QML side and instead it will be created in C++.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This method should be used if many markers are added at once.
It's main purpose is to reduces the number of beingInsertRows()
calls.
Make MapWidgetHelper::reloadMapLocations() use it.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
reloadMapLocations() is the method which is called when the list
of markers (model) should be cleared and re-populated with new MapLocation
objects.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Instead of maintaining a seperate latitude/longitude values
in C++ and passing them to QML separatelly, pass them as a QGeoCoordinate.
This reduces the number of model "roles" and also prevents the creations
of extra objects in QML (e.g. via QtPositioning.coordinate(..)).
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
MapItemView is the QML class that handles the "create map markers based
on a model". In this case the model is created as part of the
MapWidgetHelper, so here passing "mapHelper.model" to the "model"
property is enough.
The delegate receives coordinates from the model as "model.latitude",
"model.logitude" and converts them to QGeoCoordinate.
The "sourceItem" image for the delagete is just an image ATM and is
fetched from QRC.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The idea here is that the QML code should be able to fetch a model
from the MapWidgetHelper instance which is instantiated inside the
QML code; fetch it in the lines of "mapHelper.model".
This way, updates at the backend would be reflected on the Map QML widget.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
When calling centerOnCoordinates() the map will now animate over a
period of 3 seconds the zoom level and over 2 seconds the center
of the map.
Can be tweaked and improved later on.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This function can be called to center the map on a specific coordinates.
For the C++ version call it via QMetaObject::invokeMethod() in
centerOnDiveSite().
TODO: add QML property animations.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
MapWidget sould not handle any of the map backend.
Instead it should just pass calls to MapWidgetHelper.
Do that for centerOnDiveSite().
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The idea here is that the Map object can be controlled from C++ via
the "m_map" private member. Also, for the mobile version, QML code can
call the same C++ methods (if marked as Q_INVOCABLE).
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This instance in the QML code itself will be accessed by both the
mobile and desktop version. That way, the map code between
the two Subsurface versions will be shared.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The idea with this class is that it should be used by both the mobile
and desktop version.
TODO STEPS:
1) the class should be registered in both the mobile and desktop version
with qmlRegisterType<MapWidgetHelper>...
2) the MapWidget.qml should create an instance of this class.
3) this way the helper will be part of the QML and both the desktop and
mobile version can have access to it.
4) the desktop version as a first implementation can just use findChild()
in desktop-widgets/mapwidget.cpp.
5) desktop-widgets/mapwidget.cpp on the desktop should just translate
calls from the rest of the desktop-widgets to this helper class.
6) the mobile version access to this object would be easy but is off the
scope for now.
7) the idea, when implementing the desktop support is to make it so
that when implementing the mobile version later, no or only minimal
changes would be required to the MapWidgetHelper class.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Add a local "enumeration" (object) for the two possibly map types
of interest: SATELLITE and STREET.
Use SATELLITE by default.
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
The root element is now an Item and also doesn't have explicit
anchors and dimensions as these will be handled by the parent:
- on desktop: a QQuickWidget
- on mobile: any QML based QQuickItem
Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
Like the subject says. We do not want the password to be made
visible, so a switch to show it, is useless and is therefore
removed. Futher, the entry mode is set to PasswordEchoOnEdit,
which causes the passwd to be visible (for easy entry), but
can't be made visible again after save/end edit.
Fixes: #512
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Kirigami prevents us from altering the color of the gps icon in the action menu. So let's display an gps fix icon in the lower left corner of the drawer when the location services is running, colored to match the themes primary accent color.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Independ of the settings, the threshold to reset the GPS data was
hard coded to 5 minutes. Now, honour the entered (and updated during
a session) time to refresh the GPS data in the location service.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Not the lsit is much more compact and shows a lot more dives even on
smaller screens. And it's similar in style to the dive list.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Replace the theme checkboxes on the settings page
so that we get a unified UI.
These switches are linked and as such can only be activated
deactivation occurs when the user selects another theme.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Move the location services switch to the GPS menu, indicate both with icon and text if the service is active or not.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Strangely, a click/tap anywhere else worked as expected, but if you hit
exactly on the checkbox, the status change wasn't propagated.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
In stead of using the fixed 4 column code introduced in f2fcad89b0db9b164d8fd3f89218ad27ca362bd3 use percentages of page width to allow for a more flexible layout since no block really has 4 columns.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Automatically save changes made on the settings page on completion of text fields or theme checkboxes.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Put all GPS settings in one block and revert to a 2 column layout while maintaing the 4 column widh.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Addresses: #492
Signed-off-by: Rick Walsh <rickmwalsh@gmail.com>
Had a bit of rebase issue with this one.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
New icons for the dive management sub-menu
ttps://material.io/icons/
The icons are under Apache License Version 2.0
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Add a couple of icons from the material repository.
https://material.io/icons/
The icons are under Apache License Version 2.0
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Add a checkbox to the preferences page to facilitate selective visibility of the developer menu. With the coresponding function in qmlmanager.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Fixes: #490 items 1) and 2).
1) Reference to isBluetooth.leftPadding is removed as the isBooltooth
checkbox is gone.
2) Do not set background color of downloaded dives. The checkbox is used
to denote "selected or not".
In addition, incorrect references to subsurfaceTheme.PrimaryColor (which
does not exist) are replaced by the correct subsurfaceTheme.primaryColor.
Finally, an obvious copy/paste error width: childrenRect.height. that
is supposed to be width: childrenRect.width.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
This commit adds the capability to cancel a running download from DC.
The actual cancel is fully handled in the underlying libdivecomputer
code. As the user may be interested in the dives downloaded up to
the moment of cancel, do not just close the download screen (as
it was before this commit). Now, the <quit> button changes to
<cancel> when the download is started, and pressing cancel, only
cancels the download and does not close the download screen, but
presents the so far downloaded data. When no download is running,
the <quit> button just quits the screen as before.
Fixes: #485
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Trucate the logfile on open to remove any data from previous sessions.
This confused me very much, as the new logfile started from the
top, leaving old data on the bottom.
Also added system date for easy reference.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
The connection already clearly defines whether this is Bluetooth or not.
No reason for the separate checkbox.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
I wonder if we even need this anymore at all as the connection
clearly determines whether this is a BT download or not.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
If we can't find a match, just leave it unchanged. This way, if we
mis-recognize a device, the user can correct the product (or even
vendor) without losing the correct connection.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Add styling to the GPS fixes page.
The background color of the swipe list objects is wrong and also the icon overlay. This is a Kirigami issue.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
The built in theme in Kirigami has special variables for sertain objects, this sets the correct color for each object to match our themes.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
THe editable textboxes rely on the material theme to set the correct colors. This sets the appropriate colors for each theme.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Email addresses are checked for a someone useful pattern, passwords are
letters, numbers, and +-_. only. Reject anything else.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This hides the text for the map it button if ther are no coordinates for a dive. Needed as for the dark theme the map it text was still visible.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
This adds the right handle icon that is needed for the swipe list items not to report an error when activated.
Signed-off-by: Joakim Bygdell <j.bygdell@gmail.com>
Right now we need to restart Subsurface-mobile in order to detect
Bluetooth devices - so simply turning on BT after Subsurface-mobile was
started is not sufficient.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit only has the actual changes, the next commit will clean up
the white space in order to make it more obvious what was done.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The trick is to pick a path that is accessible from other applications.
In theory QStandardPaths::GenericDataLocation should provide that.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
These buttons only work when we successfully downloaded a dive. Also, don't
show a list of dives when there are no dives.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
To be shared between C/C++ and QML code in order to show the updates
and potential error messages from libdivecomputer.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Latest Kirigami master allows us to turn off reachability mode. In
general this had been rather confusing to our users and it seems to
somewhat conflict with the pull down to refresh of the dive list.
Latest Kirigami also changes the behavior of refresh slightly, you now
need to pull "down" for at least 500ms before it triggers. So, with this
change and the latest Kirigami, hopefully the user experience for
refresh is good enough that we can consider keeping it enabled and use
it as an equivalent to manual sync (even in offline mode).
See #454
See #456
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Fast flicking to the top of the divelist triggers almost certainly a
pull down sync, as the default boundBehavior is DragAndOvershootBounds.
Despite being the default QML action, this leads to unwanted pull
down syncs (even in offline mode).
Setting the boundBehavior to DragOverBounds solves this issue. Now,
the user has to explicitly drag the top down to force a pull down
sync, and a accidental fast flick is stopped at the upper bound.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
Now that we support this for many dive computers, that seem reasonable.
I'm not happy with the icon, but couldn't figure out a better one in the
breeze icon set.
See #426
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
For now just do an indeterminate busy indicator - we can get more fancy
and use the libdivecomputer progress event, later.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>