mapviewer.qml Example File

mapviewer/mapviewer.qml
/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** Commercial License Usage ** Licensees holding valid commercial Qt 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. ** ** BSD License Usage ** Alternatively, you may use this file under the terms of the BSD license ** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd nor the names of its ** contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/
import QtQuick 2.5 import QtQuick.Controls 1.4 import QtLocation 5.6 import QtPositioning 5.5 import "map" import "menus" import "helper.js" as Helper ApplicationWindow { id: appWindow property variant map property variant minimap property variant parameters //defaults property variant fromCoordinate: QtPositioning.coordinate(59.9483, 10.7695) property variant toCoordinate: QtPositioning.coordinate(59.9645, 10.671) function createMap(provider) { var plugin if (parameters && parameters.length>0) plugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin{ name:"' + provider + '"; parameters: appWindow.parameters}', appWindow) else plugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin{ name:"' + provider + '"}', appWindow) if (minimap) { minimap.destroy() minimap = null } var zoomLevel = null var tilt = null var bearing = null var fov = null var center = null var panelExpanded = null if (map) { zoomLevel = map.zoomLevel tilt = map.tilt bearing = map.bearing fov = map.fieldOfView center = map.center panelExpanded = map.slidersExpanded map.destroy() } map = mapComponent.createObject(page); map.plugin = plugin; if (zoomLevel != null) { map.tilt = tilt map.bearing = bearing map.fieldOfView = fov map.zoomLevel = zoomLevel map.center = center map.slidersExpanded = panelExpanded } else { // Use an integer ZL to enable nearest interpolation, if possible. map.zoomLevel = Math.floor((map.maximumZoomLevel - map.minimumZoomLevel)/2) // defaulting to 45 degrees, if possible. map.fieldOfView = Math.min(Math.max(45.0, map.minimumFieldOfView), map.maximumFieldOfView) } map.forceActiveFocus() } function getPlugins() { var plugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin {}', appWindow) var myArray = new Array() for (var i = 0; i<plugin.availableServiceProviders.length; i++) { var tempPlugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin {name: "' + plugin.availableServiceProviders[i]+ '"}', appWindow) if (tempPlugin.supportsMapping()) myArray.push(tempPlugin.name) } myArray.sort() return myArray } function initializeProviders(pluginParameters) { var parameters = new Array() for (var prop in pluginParameters){ var parameter = Qt.createQmlObject('import QtLocation 5.6; PluginParameter{ name: "'+ prop + '"; value: "' + pluginParameters[prop]+'"}',appWindow) parameters.push(parameter) } appWindow.parameters = parameters var plugins = getPlugins() mainMenu.providerMenu.createMenu(plugins) for (var i = 0; i<plugins.length; i++) { if (plugins[i] === "osm") mainMenu.selectProvider(plugins[i]) } } title: qsTr("Mapviewer") height: 640 width: 360 visible: true menuBar: mainMenu Address { id :fromAddress street: "Sandakerveien 116" city: "Oslo" country: "Norway" state : "" postalCode: "0484" } Address { id: toAddress street: "Holmenkollveien 140" city: "Oslo" country: "Norway" postalCode: "0791" } MainMenu { id: mainMenu function toggleMiniMapState() { if (minimap) { minimap.destroy() minimap = null } else { minimap = Qt.createQmlObject ('import "map"; MiniMap{ z: map.z + 2 }', map) } } function setLanguage(lang) { map.plugin.locales = lang; stackView.pop(page) } onSelectProvider: { stackView.pop() for (var i = 0; i < providerMenu.items.length; i++) { providerMenu.items[i].checked = providerMenu.items[i].text === providerName } createMap(providerName) if (map.error === Map.NoError) { selectMapType(map.activeMapType) toolsMenu.createMenu(map); } else { mapTypeMenu.clear(); toolsMenu.clear(); } } onSelectMapType: { stackView.pop(page) for (var i = 0; i < mapTypeMenu.items.length; i++) { mapTypeMenu.items[i].checked = mapTypeMenu.items[i].text === mapType.name } map.activeMapType = mapType } onSelectTool: { switch (tool) { case "AddressRoute": stackView.pop({item:page, immediate: true}) stackView.push({ item: Qt.resolvedUrl("forms/RouteAddress.qml") , properties: { "plugin": map.plugin, "toAddress": toAddress, "fromAddress": fromAddress}}) stackView.currentItem.showRoute.connect(map.calculateCoordinateRoute) stackView.currentItem.showMessage.connect(stackView.showMessage) stackView.currentItem.closeForm.connect(stackView.closeForm) break case "CoordinateRoute": stackView.pop({item:page, immediate: true}) stackView.push({ item: Qt.resolvedUrl("forms/RouteCoordinate.qml") , properties: { "toCoordinate": toCoordinate, "fromCoordinate": fromCoordinate}}) stackView.currentItem.showRoute.connect(map.calculateCoordinateRoute) stackView.currentItem.closeForm.connect(stackView.closeForm) break case "Geocode": stackView.pop({item:page, immediate: true}) stackView.push({ item: Qt.resolvedUrl("forms/Geocode.qml") , properties: { "address": fromAddress}}) stackView.currentItem.showPlace.connect(map.geocode) stackView.currentItem.closeForm.connect(stackView.closeForm) break case "RevGeocode": stackView.pop({item:page, immediate: true}) stackView.push({ item: Qt.resolvedUrl("forms/ReverseGeocode.qml") , properties: { "coordinate": fromCoordinate}}) stackView.currentItem.showPlace.connect(map.geocode) stackView.currentItem.closeForm.connect(stackView.closeForm) break case "Language": stackView.pop({item:page, immediate: true}) stackView.push({ item: Qt.resolvedUrl("forms/Locale.qml") , properties: { "locale": map.plugin.locales[0]}}) stackView.currentItem.selectLanguage.connect(setLanguage) stackView.currentItem.closeForm.connect(stackView.closeForm) break case "Clear": map.clearData() break case "Prefetch": map.prefetchData() break default: console.log("Unsupported operation") } } onToggleMapState: { stackView.pop(page) switch (state) { case "FollowMe": map.followme = !map.followme break case "MiniMap": toggleMiniMapState() isMiniMap = minimap break default: console.log("Unsupported operation") } } } MapPopupMenu { id: mapPopupMenu function show(coordinate) { stackView.pop(page) mapPopupMenu.coordinate = coordinate mapPopupMenu.markersCount = map.markers.length mapPopupMenu.mapItemsCount = map.mapItems.length mapPopupMenu.update() mapPopupMenu.popup() } onItemClicked: { stackView.pop(page) switch (item) { case "addMarker": map.addMarker() break case "getCoordinate": map.coordinatesCaptured(coordinate.latitude, coordinate.longitude) break case "fitViewport": map.fitViewportToMapItems() break case "deleteMarkers": map.deleteMarkers() break case "deleteItems": map.deleteMapItems() break default: console.log("Unsupported operation") } } } MarkerPopupMenu { id: markerPopupMenu function show(coordinate) { stackView.pop(page) markerPopupMenu.markersCount = map.markers.length markerPopupMenu.update() markerPopupMenu.popup() } function askForCoordinate() { stackView.push({ item: Qt.resolvedUrl("forms/ReverseGeocode.qml") , properties: { "title": qsTr("New Coordinate"), "coordinate": map.markers[map.currentMarker].coordinate}}) stackView.currentItem.showPlace.connect(moveMarker) stackView.currentItem.closeForm.connect(stackView.closeForm) } function moveMarker(coordinate) { map.markers[map.currentMarker].coordinate = coordinate; map.center = coordinate; stackView.pop(page) } onItemClicked: { stackView.pop(page) switch (item) { case "deleteMarker": map.deleteMarker(map.currentMarker) break; case "getMarkerCoordinate": map.coordinatesCaptured(map.markers[map.currentMarker].coordinate.latitude, map.markers[map.currentMarker].coordinate.longitude) break; case "moveMarkerTo": askForCoordinate() break; case "routeToNextPoint": case "routeToNextPoints": map.calculateMarkerRoute() break case "distanceToNextPoint": var coordinate1 = map.markers[currentMarker].coordinate; var coordinate2 = map.markers[currentMarker+1].coordinate; var distance = Helper.formatDistance(coordinate1.distanceTo(coordinate2)); stackView.showMessage(qsTr("Distance"),"<b>" + qsTr("Distance:") + "</b> " + distance) break case "drawImage": map.addGeoItem("ImageItem") break case "drawRectangle": map.addGeoItem("RectangleItem") break case "drawCircle": map.addGeoItem("CircleItem") break; case "drawPolyline": map.addGeoItem("PolylineItem") break; case "drawPolygonMenu": map.addGeoItem("PolygonItem") break default: console.log("Unsupported operation") } } } ItemPopupMenu { id: itemPopupMenu function show(type,coordinate) { stackView.pop(page) itemPopupMenu.type = type itemPopupMenu.update() itemPopupMenu.popup() } onItemClicked: { stackView.pop(page) switch (item) { case "showRouteInfo": stackView.showRouteListPage() break; case "deleteRoute": map.routeModel.reset(); break; case "showPointInfo": map.showGeocodeInfo() break; case "deletePoint": map.geocodeModel.reset() break; default: console.log("Unsupported operation") } } } StackView { id: stackView anchors.fill: parent focus: true initialItem: Item { id: page Text { visible: !supportsSsl && map && map.activeMapType && activeMapType.metadata.isHTTPS text: "The active map type\n requires (missing) SSL\n support" horizontalAlignment: Text.AlignHCenter font.pixelSize: appWindow.width / 12 font.bold: true color: "grey" anchors.centerIn: parent z: 12 } } function showMessage(title,message,backPage) { push({ item: Qt.resolvedUrl("forms/Message.qml") , properties: { "title" : title, "message" : message, "backPage" : backPage }}) currentItem.closeForm.connect(closeMessage) } function closeMessage(backPage) { pop(backPage) } function closeForm() { pop(page) } function showRouteListPage() { push({ item: Qt.resolvedUrl("forms/RouteList.qml") , properties: { "routeModel" : map.routeModel }}) currentItem.closeForm.connect(closeForm) } } Component { id: mapComponent MapComponent{ width: page.width height: page.height onFollowmeChanged: mainMenu.isFollowMe = map.followme onSupportedMapTypesChanged: mainMenu.mapTypeMenu.createMenu(map) onCoordinatesCaptured: { var text = "<b>" + qsTr("Latitude:") + "</b> " + Helper.roundNumber(latitude,4) + "<br/><b>" + qsTr("Longitude:") + "</b> " + Helper.roundNumber(longitude,4) stackView.showMessage(qsTr("Coordinates"),text); } onGeocodeFinished:{ if (map.geocodeModel.status == GeocodeModel.Ready) { if (map.geocodeModel.count == 0) { stackView.showMessage(qsTr("Geocode Error"),qsTr("Unsuccessful geocode")) } else if (map.geocodeModel.count > 1) { stackView.showMessage(qsTr("Ambiguous geocode"), map.geocodeModel.count + " " + qsTr("results found for the given address, please specify location")) } else { stackView.showMessage(qsTr("Location"), geocodeMessage(),page) } } else if (map.geocodeModel.status == GeocodeModel.Error) { stackView.showMessage(qsTr("Geocode Error"),qsTr("Unsuccessful geocode")) } } onRouteError: stackView.showMessage(qsTr("Route Error"),qsTr("Unable to find a route for the given points"),page) onShowGeocodeInfo: stackView.showMessage(qsTr("Location"),geocodeMessage(),page) onErrorChanged: { if (map.error != Map.NoError) { var title = qsTr("ProviderError") var message = map.errorString + "<br/><br/><b>" + qsTr("Try to select other provider") + "</b>" if (map.error == Map.MissingRequiredParameterError) message += "<br/>" + qsTr("or see") + " \'mapviewer --help\' " + qsTr("how to pass plugin parameters.") stackView.showMessage(title,message); } } onShowMainMenu: mapPopupMenu.show(coordinate) onShowMarkerMenu: markerPopupMenu.show(coordinate) onShowRouteMenu: itemPopupMenu.show("Route",coordinate) onShowPointMenu: itemPopupMenu.show("Point",coordinate) onShowRouteList: stackView.showRouteListPage() } } }