- Qt 5.5
- Qt Location
- Map Viewer (QML)
- mapviewer.qml Example File
- Qt 5.5.1 Reference Documentation

# mapviewer.qml Example File

mapviewer/mapviewer.qml

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the examples of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:BSD$
    ** 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.5
    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.3; Plugin{ name:"' + provider + '"; parameters: appWindow.parameters}', appWindow)
            else
                plugin = Qt.createQmlObject ('import QtLocation 5.3; Plugin{ name:"' + provider + '"}', appWindow)

            if (map) {
                map.destroy()
                minimap = null
            }

            map = mapComponent.createObject(page);
            map.plugin = plugin;
            map.zoomLevel = (map.maximumZoomLevel - map.minimumZoomLevel)/2
        }

        function getPlugins()
        {
            var plugin = Qt.createQmlObject ('import QtLocation 5.3; Plugin {}', appWindow)
            var myArray = new Array()
            for (var i = 0; i<plugin.availableServiceProviders.length; i++) {
                var tempPlugin = Qt.createQmlObject ('import QtLocation 5.3; 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.3; 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
                }

                if (minimap) {
                    minimap.destroy()
                    minimap = null
                }

                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
                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
            }

            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()
            }
        }
    }