import QtQuick 2.0
import QtLocation 5.0
import QtLocation.examples 5.0
import "content/map"
import "content/dialogs"
Item {
id: page
width: parent ? parent.width : 360
height: parent ? parent.height : 640
property bool mobileUi: true
property variant map
property variant minimap
property list<PluginParameter> parameters
Rectangle {
id: backgroundRect
anchors.fill: parent
color: "lightgrey"
z:2
}
Menu {
id:mainMenu
anchors.bottom: parent.bottom
z: backgroundRect.z + 3
Component.onCompleted: {
addItem("Tools")
addItem("Map Type")
addItem("Provider")
}
onClicked: {
switch (button) {
case "Tools": {
page.state = "Tools"
break;
}
case "Map Type": {
page.state = "MapType"
break;
}
case "Provider": {
page.state = "Provider"
break;
}
}
}
}
Menu {
id: toolsMenu
z: backgroundRect.z + 2
y: page.height
horizontalOrientation: false
Component.onCompleted: {
update()
}
onClicked: {
switch (button) {
case "Reverse geocode": {
page.state = "RevGeocode"
break;
}
case "Geocode": {
page.state = "Geocode"
break;
}
case "Route": {
page.state = "Route"
break;
}
case "Follow me": {
map.followme =true
page.state = ""
break;
}
case "Stop following": {
map.followme =false
page.state = ""
break;
}
case "Minimap": {
minimap = Qt.createQmlObject ('import "content/map"; MiniMap{ z: map.z + 2 }', map)
page.state = ""
break;
}
case "Hide minimap": {
if (minimap) minimap.destroy()
minimap = null
page.state = ""
break;
}
}
}
function update(){
clear()
addItem("Reverse geocode")
addItem("Geocode")
addItem("Route")
var item = addItem("Follow me")
item.text = Qt.binding(function() { return map.followme ? "Stop following" : "Follow me" });
item = addItem("Minimap")
item.text = Qt.binding(function() { return minimap ? "Hide minimap" : "Minimap" });
}
}
Menu {
id: mapTypeMenu
z: backgroundRect.z + 2
y: page.height
horizontalOrientation: false
exclusive: true
Component.onCompleted: {
update()
}
onClicked: {
page.state = ""
}
onExclusiveButtonChanged: {
for (var i = 0; i<map.supportedMapTypes.length; i++){
if (exclusiveButton == map.supportedMapTypes[i].name){
map.activeMapType = map.supportedMapTypes[i]
break;
}
}
}
function update(){
clear()
for (var i = 0; i<map.supportedMapTypes.length; i++)
addItem(map.supportedMapTypes[i].name)
if (map.supportedMapTypes.length > 0)
exclusiveButton = map.activeMapType.name
}
}
Menu {
id: providerMenu
z: backgroundRect.z + 2
y: page.height
horizontalOrientation: false
exclusive: true
Component.onCompleted: {
var plugins = getPlugins()
for (var i = 0; i<plugins.length; i++)
addItem(plugins[i])
if (plugins.length > 0) exclusiveButton = plugins[0]
}
onClicked: {
page.state = ""
}
onExclusiveButtonChanged: {
createMap(exclusiveButton)
}
}
Message {
id: messageDialog
z: backgroundRect.z + 2
onOkButtonClicked: {
page.state = ""
}
onCancelButtonClicked: {
page.state = ""
}
states: [
State{
name: "GeocodeError"
PropertyChanges { target: messageDialog; title: "Geocode Error" }
PropertyChanges { target: messageDialog; text: "No data available for the specified location" }
},
State{
name: "UnknownGeocodeError"
PropertyChanges { target: messageDialog; title: "Geocode Error" }
PropertyChanges { target: messageDialog; text: "Unsuccessful geocode" }
},
State{
name: "AmbiguousGeocode"
PropertyChanges { target: messageDialog; title: "Ambiguous geocode" }
PropertyChanges { target: messageDialog; text: map.geocodeModel.count + " results found for the given address, please specify location" }
},
State{
name: "RouteError"
PropertyChanges { target: messageDialog; title: "Route Error" }
PropertyChanges { target: messageDialog; text: "Unable to find a route for the given points"}
},
State{
name: "Coordinates"
PropertyChanges { target: messageDialog; title: "Coordinates" }
},
State{
name: "LocationInfo"
PropertyChanges { target: messageDialog; title: "Location" }
PropertyChanges { target: messageDialog; text: geocodeMessage() }
},
State{
name: "Distance"
PropertyChanges { target: messageDialog; title: "Distance" }
}
]
}
RouteDialog {
id: routeDialog
Coordinate { id: endCoordinate }
Coordinate { id: startCoordinate }
Address { id: startAddress }
Address { id: endAddress }
z: backgroundRect.z + 2
GeocodeModel {
id: tempGeocodeModel
plugin : map.plugin
property int success: 0
onStatusChanged:{
if ((status == GeocodeModel.Ready) && (count == 1)) {
success++
if (success == 1){
startCoordinate.latitude = get(0).coordinate.latitude
startCoordinate.longitude = get(0).coordinate.longitude
clear()
query = endAddress
update();
}
if (success == 2)
{
endCoordinate.latitude = get(0).coordinate.latitude
endCoordinate.longitude = get(0).coordinate.longitude
success = 0
routeDialog.calculateRoute()
}
}
else if ((status == GeocodeModel.Ready) || (status == GeocodeModel.Error)){
var st = (success == 0 ) ? "start" : "end"
messageDialog.state = ""
if ((status == GeocodeModel.Ready) && (count == 0 )) messageDialog.state = "UnknownGeocodeError"
else if (status == GeocodeModel.Error) {
messageDialog.state = "GeocodeError"
messageDialog.text = "Unable to find location for the " + st + " point"
}
else if ((status == GeocodeModel.Ready) && (count > 1 )){
messageDialog.state = "AmbiguousGeocode"
messageDialog.text = count + " results found for the " + st + " point, please specify location"
}
success = 0
page.state = "Message"
map.routeModel.clearAll()
}
}
}
onGoButtonClicked: {
var status = true
messageDialog.state = ""
if (routeDialog.byCoordinates) {
startCoordinate.latitude = routeDialog.startLatitude
startCoordinate.longitude = routeDialog.startLongitude
endCoordinate.latitude = routeDialog.endLatitude
endCoordinate.longitude = routeDialog.endLongitude
calculateRoute()
}
else {
startAddress.country = routeDialog.startCountry
startAddress.street = routeDialog.startStreet
startAddress.city = routeDialog.startCity
endAddress.country = routeDialog.endCountry
endAddress.street = routeDialog.endStreet
endAddress.city = routeDialog.endCity
tempGeocodeModel.query = startAddress
tempGeocodeModel.update();
}
page.state = ""
}
onCancelButtonClicked: {
page.state = ""
}
function calculateRoute() {
map.routeQuery.clearWaypoints();
map.routeQuery.addWaypoint(startCoordinate)
map.routeQuery.addWaypoint(endCoordinate)
map.routeQuery.travelModes = routeDialog.travelMode
map.routeQuery.routeOptimizations = routeDialog.routeOptimization
for (var i=0; i<9; i++) {
map.routeQuery.setFeatureWeight(i, 0)
}
for (var i=0; i<routeDialog.features.length; i++) {
map.routeQuery.setFeatureWeight(routeDialog.features[i], RouteQuery.AvoidFeatureWeight)
}
map.routeModel.update();
map.center.latitude = startCoordinate.latitude
map.center.longitude = startCoordinate.longitude
}
}
InputDialog {
id: geocodeDialog
title: "Geocode"
z: backgroundRect.z + 2
Component.onCompleted: {
var obj = [["Street", "Brandl St"],["City", "Eight Mile Plains"],["State", ""],["Country","Australia"], ["Postal code", ""]]
setModel(obj)
}
Address {
id: geocodeAddress
}
onGoButtonClicked: {
page.state = ""
messageDialog.state = ""
geocodeAddress.street = dialogModel.get(0).inputText
geocodeAddress.city = dialogModel.get(1).inputText
geocodeAddress.state = dialogModel.get(2).inputText
geocodeAddress.country = dialogModel.get(3).inputText
geocodeAddress.postalCode = dialogModel.get(4).inputText
map.geocodeModel.query = geocodeAddress
map.geocodeModel.update()
}
onCancelButtonClicked: {
page.state = ""
}
}
InputDialog {
id: reverseGeocodeDialog
title: "Reverse Geocode"
z: backgroundRect.z + 2
Component.onCompleted: {
var obj = [["Latitude","-27.575"],["Longitude", "153.088"]]
setModel(obj)
}
Coordinate {
id: reverseGeocodeCoordinate
}
onGoButtonClicked: {
page.state = ""
messageDialog.state = ""
reverseGeocodeCoordinate.latitude = dialogModel.get(0).inputText
reverseGeocodeCoordinate.longitude = dialogModel.get(1).inputText
map.geocodeModel.query = reverseGeocodeCoordinate
map.geocodeModel.update();
}
onCancelButtonClicked: {
page.state = ""
}
}
InputDialog {
id: coordinatesDialog
title: "New coordinates"
z: backgroundRect.z + 2
Component.onCompleted: {
var obj = [["Latitude", ""],["Longitude", ""]]
setModel(obj)
}
onGoButtonClicked: {
page.state = ""
messageDialog.state = ""
var latitude = parseFloat(dialogModel.get(0).inputText)
var longitude = parseFloat(dialogModel.get(1).inputText)
if (latitude !== "NaN" && longitude !== "NaN") {
var coordinate = Qt.createQmlObject('import QtLocation 5.0; Coordinate {}', map)
coordinate.latitude = latitude
coordinate.longitude = longitude
if (coordinate.isValid) {
map.markers[map.currentMarker].coordinate.latitude = latitude
map.markers[map.currentMarker].coordinate.longitude = longitude
map.center.latitude = latitude
map.center.longitude = longitude
}
}
}
onCancelButtonClicked: {
page.state = ""
}
}
InputDialog {
id: localeDialog
title: "New Locale"
z: backgroundRect.z + 2
Component.onCompleted: {
var obj = [["Language", ""]]
setModel(obj)
}
onGoButtonClicked: {
page.state = ""
messageDialog.state = ""
map.setLanguage(dialogModel.get(0).inputText.split(Qt.locale().groupSeparator));
}
onCancelButtonClicked: {
page.state = ""
}
}
function geocodeMessage(){
var street, district, city, county, state, countryCode, country, postalCode, latitude, longitude, text
latitude = Math.round(map.geocodeModel.get(0).coordinate.latitude * 10000) / 10000
longitude =Math.round(map.geocodeModel.get(0).coordinate.longitude * 10000) / 10000
street = map.geocodeModel.get(0).address.street
district = map.geocodeModel.get(0).address.district
city = map.geocodeModel.get(0).address.city
county = map.geocodeModel.get(0).address.county
state = map.geocodeModel.get(0).address.state
countryCode = map.geocodeModel.get(0).address.countryCode
country = map.geocodeModel.get(0).address.country
postalCode = map.geocodeModel.get(0).address.postalCode
text = "<b>Latitude:</b> " + latitude + "<br/>"
text +="<b>Longitude:</b> " + longitude + "<br/>" + "<br/>"
if (street) text +="<b>Street: </b>"+ street + " <br/>"
if (district) text +="<b>District: </b>"+ district +" <br/>"
if (city) text +="<b>City: </b>"+ city + " <br/>"
if (county) text +="<b>County: </b>"+ county + " <br/>"
if (state) text +="<b>State: </b>"+ state + " <br/>"
if (countryCode) text +="<b>Country code: </b>"+ countryCode + " <br/>"
if (country) text +="<b>Country: </b>"+ country + " <br/>"
if (postalCode) text +="<b>PostalCode: </b>"+ postalCode + " <br/>"
return text
}
function createMap(provider){
var plugin
if (parameters.length>0)
plugin = Qt.createQmlObject ('import QtLocation 5.0; Plugin{ name:"' + provider + '"; parameters: page.parameters}', page)
else
plugin = Qt.createQmlObject ('import QtLocation 5.0; Plugin{ name:"' + provider + '"}', page)
if (plugin.supportsMapping()
&& plugin.supportsGeocoding(Plugin.ReverseGeocodingFeature)
&& plugin.supportsRouting()) {
if (map) {
map.destroy()
minimap = null
}
map = Qt.createQmlObject ('import QtLocation 5.0;\
import "content/map";\
MapComponent{\
z : backgroundRect.z + 1;\
width: page.width;\
height: page.height - mainMenu.height;\
onFollowmeChanged: {toolsMenu.update()}\
onSupportedMapTypesChanged: {mapTypeMenu.update()}\
onCoordinatesCaptured: {\
messageDialog.state = "Coordinates";\
messageDialog.text = "<b>Latitude:</b> " + roundNumber(latitude,4) + "<br/><b>Longitude:</b> " + roundNumber(longitude,4);\
page.state = "Message";\
}\
onGeocodeFinished:{\
if (map.geocodeModel.status == GeocodeModel.Ready){\
if (map.geocodeModel.count == 0) {messageDialog.state = "UnknownGeocodeError";}\
else if (map.geocodeModel.count > 1) {messageDialog.state = "AmbiguousGeocode";}\
else {messageDialog.state = "LocationInfo";}\
}\
else if (map.geocodeModel.status == GeocodeModel.Error) {messageDialog.state = "GeocodeError";}\
page.state = "Message";\
}\
onShowDistance:{\
messageDialog.state = "Distance";\
messageDialog.text = "<b>Distance:</b> " + distance;\
page.state = "Message";\
}\
onMoveMarker: {\
page.state = "Coordinates";\
}\
onRouteError: {\
messageDialog.state = "RouteError";\
page.state = "Message";\
}\
onRequestLocale:{\
page.state = "Locale";\
}\
onShowGeocodeInfo:{\
messageDialog.state = "LocationInfo";\
page.state = "Message";\
}\
onResetState: {\
page.state = "";\
}\
}',page)
map.plugin = plugin
}
}
function getPlugins(){
var plugin = Qt.createQmlObject ('import QtLocation 5.0; Plugin {}', page)
var tempPlugin
var myArray = new Array()
for (var i = 0; i<plugin.availableServiceProviders.length; i++){
tempPlugin = Qt.createQmlObject ('import QtLocation 5.0; Plugin {name: "' + plugin.availableServiceProviders[i]+ '"}', page)
if (tempPlugin.supportsMapping()
&& tempPlugin.supportsGeocoding(Plugin.ReverseGeocodingFeature)
&& tempPlugin.supportsRouting()) {
myArray.push(tempPlugin.name)
}
}
return myArray
}
function setPluginParameters(pluginParameters) {
var parameters = new Array()
for (var prop in pluginParameters){
var parameter = Qt.createQmlObject('import QtLocation 5.0; PluginParameter{ name: "'+ prop + '"; value: "' + pluginParameters[prop]+'"}',page)
parameters.push(parameter)
}
page.parameters=parameters
createMap(map.plugin.name)
}
states: [
State {
name: "RevGeocode"
PropertyChanges { target: reverseGeocodeDialog; opacity: 1 }
},
State {
name: "Route"
PropertyChanges { target: routeDialog; opacity: 1 }
},
State {
name: "Geocode"
PropertyChanges { target: geocodeDialog; opacity: 1 }
},
State {
name: "Coordinates"
PropertyChanges { target: coordinatesDialog; opacity: 1 }
},
State {
name: "Message"
PropertyChanges { target: messageDialog; opacity: 1 }
},
State {
name : "Tools"
PropertyChanges { target: toolsMenu; y: page.height - toolsMenu.height - mainMenu.height }
},
State {
name : "Provider"
PropertyChanges { target: providerMenu; y: page.height - providerMenu.height - mainMenu.height }
},
State {
name : "MapType"
PropertyChanges { target: mapTypeMenu; y: page.height - mapTypeMenu.height - mainMenu.height }
},
State {
name : "Locale"
PropertyChanges { target: localeDialog; opacity: 1 }
}
]
transitions: [
Transition {
to: "RevGeocode"
NumberAnimation { properties: "opacity" ; duration: 500; easing.type: Easing.Linear }
},
Transition {
to: "Route"
NumberAnimation { properties: "opacity" ; duration: 500; easing.type: Easing.Linear }
},
Transition {
to: "Geocode"
NumberAnimation { properties: "opacity" ; duration: 500; easing.type: Easing.Linear }
},
Transition {
to: "Coordinates"
NumberAnimation { properties: "opacity" ; duration: 500; easing.type: Easing.Linear }
},
Transition {
to: "Message"
NumberAnimation { properties: "opacity" ; duration: 500; easing.type: Easing.Linear }
},
Transition {
to: ""
NumberAnimation { properties: "opacity" ; duration: 500; easing.type: Easing.Linear }
},
Transition {
to: "Provider"
NumberAnimation { properties: "y" ; duration: 300; easing.type: Easing.Linear }
},
Transition {
to: "MapType"
NumberAnimation { properties: "y" ; duration: 300; easing.type: Easing.Linear }
},
Transition {
to: "Tools"
NumberAnimation { properties: "y" ; duration: 300; easing.type: Easing.Linear }
}
]
}