aboutsummaryrefslogtreecommitdiffstats
path: root/apps/com.pelagicore.qtlocation/views/MapView.qml
diff options
context:
space:
mode:
Diffstat (limited to 'apps/com.pelagicore.qtlocation/views/MapView.qml')
-rw-r--r--apps/com.pelagicore.qtlocation/views/MapView.qml300
1 files changed, 300 insertions, 0 deletions
diff --git a/apps/com.pelagicore.qtlocation/views/MapView.qml b/apps/com.pelagicore.qtlocation/views/MapView.qml
new file mode 100644
index 00000000..e07ab71c
--- /dev/null
+++ b/apps/com.pelagicore.qtlocation/views/MapView.qml
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2017-2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune 3 IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.8
+import QtQuick.Controls 2.2
+import QtQuick.Layouts 1.3
+import QtPositioning 5.9
+import QtLocation 5.9
+import QtGraphicalEffects 1.0
+
+import Qt.labs.platform 1.0
+
+import utils 1.0
+import controls 1.0 as NeptuneControls
+import animations 1.0
+
+import com.pelagicore.styles.neptune 3.0
+
+import "../controls"
+import "../panels"
+import "../stores"
+import "../helpers"
+
+Item {
+ id: root
+
+ property bool offlineMapsEnabled
+ onOfflineMapsEnabledChanged: getAvailableMapsAndLocation()
+
+ property MapStore store
+
+ // props for secondary window
+ property alias mapInteractive: mapBoxView.mapInteractive
+ property alias mapCenter: mapBoxView.center
+ property alias mapZoomLevel: mapBoxView.zoomLevel
+ property alias mapTilt: mapBoxView.tilt
+ property alias mapBearing: mapBoxView.bearing
+ readonly property alias mapReady: mapBoxView.mapReady
+ readonly property alias currentLocation: priv.positionCoordinate
+
+ property bool searchViewEnabled: false
+ property Helper helper: Helper {}
+
+ signal maximizeMap()
+
+ Component.onCompleted: {
+ root.store.homeCoord = mapBoxView.mapHeader.homeAddressData;
+ root.store.workCoord = mapBoxView.mapHeader.workAddressData;
+ }
+
+ onStateChanged: root.searchViewEnabled = false;
+
+ function fetchCurrentLocation() { // PositionSource doesn't work on Linux
+ var req = new XMLHttpRequest;
+ req.onreadystatechange = function() {
+ if (req.readyState === XMLHttpRequest.DONE) {
+ var objectArray = JSON.parse(req.responseText);
+ if (objectArray.errors !== undefined) {
+ console.warn("Error fetching location:", objectArray.errors[0].message);
+ } else {
+ priv.positionCoordinate = QtPositioning.coordinate(objectArray.location.lat, objectArray.location.lng);
+ console.info("Current location:", priv.positionCoordinate);
+ }
+ }
+ }
+ req.open("GET", "https://location.services.mozilla.com/v1/geolocate?key=geoclue");
+ req.send();
+ }
+
+ function getAvailableMapsAndLocation() {
+ if (mapBoxView.mapReady) {
+ mapTypeModel.clear();
+ console.info("Supported map types:");
+ for (var i = 0; i < mapBoxView.supportedMapTypes.length; i++) {
+ var map = mapBoxView.supportedMapTypes[i];
+ mapTypeModel.append({"name": map.name, "data": map}) // fill the map type model
+ console.info("\t", map.name, ", description:", map.description, ", style:", map.style, ", night mode:", map.night);
+ }
+ if (!root.offlineMapsEnabled) {
+ fetchCurrentLocation();
+ }
+ }
+ }
+
+ function getMapType(name) {
+ if (!mapBoxView.mapReady || !mapTypeModel.count) {
+ return
+ }
+ for (var i = 0; i < mapTypeModel.count; i++) {
+ var map = mapTypeModel.get(i);
+ if (map && map.name === name) {
+ return map.data;
+ }
+ }
+ }
+
+ QtObject {
+ id: priv
+ readonly property var plugins: ["mapboxgl", "osm"]
+ property var positionCoordinate: offlineMapsEnabled ? QtPositioning.coordinate(57.709912, 11.966632) // Gothenburg
+ : QtPositioning.coordinate(49.5938686, 17.2508706) // Olomouc
+ property var originalPosition: positionCoordinate
+ readonly property string defaultLightThemeId: "mapbox://styles/qtauto/cjcm1by3q12dk2sqnquu0gju9"
+ readonly property string defaultDarkThemeId: "mapbox://styles/qtauto/cjcm1czb812co2sno1ypmp1r8"
+ }
+
+ ListModel {
+ // lists the various map styles (including the custom ones); filled in Map.onMapReadyChanged
+ id: mapTypeModel
+ }
+
+ Plugin {
+ id: mapPlugin
+ locales: Style.languageLocale
+ preferred: priv.plugins
+
+ readonly property string cacheDirUrl: StandardPaths.writableLocation(StandardPaths.CacheLocation);
+
+ // Mapbox Plugin Parameters
+ PluginParameter {
+ name: "mapboxgl.access_token"
+ value: "pk.eyJ1IjoicXRhdXRvIiwiYSI6ImNqY20wbDZidzBvcTQyd3J3NDlkZ21jdjUifQ.4KYDlP7UmQEVPYffr6VuVQ"
+ }
+ PluginParameter {
+ name: "mapboxgl.mapping.additional_style_urls"
+ value: [priv.defaultLightThemeId, priv.defaultDarkThemeId].join(",")
+ }
+
+ // OSM Plugin Parameters
+ PluginParameter { name: "osm.useragent"; value: "Neptune UI" }
+
+ // Offline maps support
+ PluginParameter { name: "mapboxgl.mapping.cache.directory";
+ // needs to be an absolute filepath so strip the file:/// protocol; several leading slashes don't matter
+ value: mapPlugin.cacheDirUrl.toString().substring(mapPlugin.cacheDirUrl.indexOf(':')+1) }
+ }
+
+ // This is needed since MapBox plugin does not support geocoding yet. TODO: find a better way to support geocoding.
+ Plugin {
+ id: geocodePlugin
+ name: "osm"
+ locales: Style.languageLocale
+
+ // OSM Plugin Parameters
+ PluginParameter { name: "osm.useragent"; value: "Neptune UI" }
+ }
+
+ GeocodeModel {
+ id: geocodeModel
+ plugin: geocodePlugin
+ limit: 20
+ }
+
+ MapBoxPanel {
+ id: mapBoxView
+ anchors.fill: parent
+ plugin: mapPlugin
+ center: priv.positionCoordinate
+ state: root.state
+ currentLocation: priv.positionCoordinate
+ offlineMapsEnabled: root.offlineMapsEnabled
+ destination: root.store.destination
+ model: root.store.model
+ routeDistance: root.store.routeDistance
+ routeTime: root.store.routeTime
+ routeSegments: root.store.routeSegments
+ homeRouteTime: root.store.homeRouteTime
+ workRouteTime: root.store.workRouteTime
+ destCoord: root.store.destCoord
+
+ activeMapType: {
+ if (!mapReady || plugin.name !== "mapboxgl") {
+ return supportedMapTypes[0];
+ }
+ return NeptuneStyle.theme === NeptuneStyle.Light ? getMapType(priv.defaultLightThemeId) : getMapType(priv.defaultDarkThemeId);
+ }
+ onOpenSearchTextInput: {
+ root.maximizeMap();
+ searchViewEnabled = true;
+ }
+ onStartNavigationRequested: {
+ priv.originalPosition = priv.positionCoordinate;
+ }
+ onShowRouteRequested: {
+ priv.originalPosition = priv.positionCoordinate;
+ root.store.destCoord = destCoord;
+ root.store.destination = description;
+ root.store.startCoord = mapBoxView.currentLocation;
+ }
+ onStopNavigationRequested: {
+ priv.positionCoordinate = priv.originalPosition;
+ mapBoxView.center = priv.positionCoordinate;
+ }
+
+ onMapReadyChanged: getAvailableMapsAndLocation();
+ onMaximizeMap: root.maximizeMap();
+ Component.onCompleted: {
+ root.store.routingPlugin = geocodePlugin
+ }
+ }
+
+ NeptuneControls.Tool {
+ anchors.left: parent.left
+ anchors.leftMargin: Style.hspan(0.6)
+ anchors.top: parent.top
+ anchors.topMargin: Style.vspan(0.6)
+ opacity: root.state === "Widget1Row" ? 1 : 0
+ Behavior on opacity { DefaultNumberAnimation {} }
+ visible: opacity > 0
+ symbol: Qt.resolvedUrl("../assets/ic-search.png")
+ background: Image {
+ fillMode: Image.Pad
+ source: helper.localAsset("floating-button-bg", NeptuneStyle.theme)
+ }
+ onClicked: root.maximizeMap()
+ }
+
+ FastBlur {
+ anchors.fill: mapBoxView
+ source: mapBoxView
+ radius: 64
+ visible: searchViewEnabled
+ }
+
+ BorderImage {
+ id: overlay
+ anchors.fill: root
+ border.top: 322
+ border.bottom: 323
+ border.left: 0
+ border.right: 0
+ source: Style.gfx2("input-overlay")
+ visible: searchViewEnabled
+ }
+
+ SearchOverlayPanel {
+ id: searchOverlay
+ anchors.fill: root
+ anchors.topMargin: Style.vspan(1)
+ visible: searchViewEnabled
+ spacing: Style.vspan(1)
+ model: geocodeModel
+
+ onBackButtonClicked: searchViewEnabled = false
+
+ onSearchFieldAccepted: {
+ geocodeModel.query = searchOverlay.searchQuery;
+ geocodeModel.update();
+ searchViewEnabled = false;
+ }
+
+ onSearchQueryChanged: {
+ geocodeModel.reset();
+ geocodeModel.query = searchQuery;
+ geocodeModel.update();
+ }
+
+ onEscapePressed: searchViewEnabled = false
+
+ onItemClicked: {
+ searchViewEnabled = false;
+ mapBoxView.center = coordinate;
+ root.store.startCoord = priv.positionCoordinate;
+ root.store.destCoord = coordinate;
+ root.store.destination = addressText;
+ if (boundingBox.isValid) {
+ mapBoxView.visibleRegion = boundingBox;
+ }
+ mapBoxView.navigationMode = true;
+ }
+ }
+}