(Difference between revisions)

Google Landmarks on a Nokia Map using Qt Quick

From Nokia Developer Wiki
Jump to: navigation, search
rahulvala (Talk | contribs)
m (Rahulvala -)
somnathbanik (Talk | contribs)
(Somnathbanik - - page 2 in main.qml)
Line 142: Line 142:
       console.log("latitude:" +myLatitude + "longitude:" +myLongitude+ "landmark:"+landmarkname );
       console.log("latitude:" +myLatitude + "longitude:" +myLongitude+ "landmark:"+landmarkname );
       var url =
       var url =
           "https://maps.googleapis.com/maps/api/place/search/xml?location="+myLatitude+","+myLongitude+"&radius=1000&name="+landmarkname+"&sensor=false&key=<Your Google API Key>";
         var doc = new XMLHttpRequest();
         var doc = new XMLHttpRequest();
         doc.onreadystatechange = function() {
         doc.onreadystatechange = function() {

Revision as of 09:36, 2 January 2012

This article demonstrates how to plot landmarks on a map using Nokia Map API for Qt.

Article Metadata
Code ExampleTested with
Devices(s): N9/N950
Platform(s): Symbian/ MeeGo
Keywords: Nokia Maps, Location, LandMark
Created: somnathbanik (30 Dec 2011)
Last edited: somnathbanik (02 Jan 2012)



The example combines gets information about local landmarks using the Google Place API and plots them on a Nokia Map using "push pins". When user clicks on any of the pins the application displays a popup with the landmark information and the distance of the landmark from user’s location.


We create two page items in the main.qml file. The first page item lists available landmark categories while the second page displays the Nokia Map with the landmarks.

page 1 in main.qml

//page 1
Rectangle {
id: page1
width: parent.width
color: "black"
height: parent.height
RssModel {id: feedModelLandmark}
ListView {
id: list
width: parent.width ;
height: parent.height-111;
model: feedModelLandmark
delegate: CategoryListDelegate {}
color: "white"
Text {
id: tileText
height: 40
text: qsTr("Near Me")
color: "green"
font.pixelSize: 80
Image {
id: titleImage
source: "maps-icon.png"
height: 80
width: 80
color: "white"
height: 2
State {
name: "Item"; when: appWindow.inFirstScreen == true
PropertyChanges { target: page1; x: 0 }
PropertyChanges { target: page2; x: -(parent.width * 1.5) }
PropertyChanges { target: commonTools; visible:false }
transitions: Transition {
NumberAnimation { properties: "x"; duration: 700; easing.type: Easing.InOutQuad }

page 2 in main.qml

//page 2
Item {
id: page2
width: parent.width
height: parent.height
//display the map
id: mapRect
anchors.fill: parent
signal xmlMapReady
onXmlMapReady: container.xmlReady = !container.xmlReady
RssModelMap {id: feedModelMap}
MapDelegate {id: container }
State {
name: "Item"; when: appWindow.inSecondScreen == true
PropertyChanges { target: page2; x: 0 }
PropertyChanges { target: page1; x: -(parent.width * 1.5) }
PropertyChanges { target: commonTools; visible:true }
transitions: Transition {
NumberAnimation { properties: "x"; duration: 700; easing.type: Easing.InOutQuad }

The page also has a "back" button, which is visible when the Map displays

// menu bar
ToolBarLayout {
id: commonTools
visible: false
ToolIcon {
platformIconId: "toolbar-back"
anchors.bottom: (parent === undefined) ? undefined : parent.bottom
onClicked: {

When a user clicks on any of the landmark categories the application calls the loadLandMark() function, which uses the Google Places API to get the near by landmark information.

function loadLandMark(landmarkname)
myLatitude = positionSource.position.coordinate.latitude;
myLongitude = positionSource.position.coordinate.longitude;
console.log("latitude:" +myLatitude + "longitude:" +myLongitude+ "landmark:"+landmarkname );
var url =
"https://maps.googleapis.com/maps/api/place/search/xml?location="+myLatitude+","+myLongitude+"&radius=1000&name="+landmarkname+"&sensor=false&key=<Your Google API Key>";
var doc = new XMLHttpRequest();
doc.onreadystatechange = function() {
if (doc.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
else if (doc.readyState == XMLHttpRequest.DONE) {
console.log("HttpRequest DONE");
var status = doc.status;
if(status!=200) {
var data = doc.responseText;
//console.log("Google Data:\n"+data);
feedModelMap.xmlData = data;
doc.open("GET", url);

In this case we are using XmlListModel instead of LandmarkModel for storing the data. The Google Places API is a HTTPS request so , first we download all the data through loadLandMark () function and then pass the data to the xml property of XmlListModel leaving the source property empty.


XmlListModel {
id: feedModelMap
property string xmlData:"";
xml: xmlData
query: "/PlaceSearchResponse/result"
namespaceDeclarations: ""
XmlRole { name: "name"; query: "name/string()" }
XmlRole { name: "vicinity"; query: "vicinity/string()" }
XmlRole { name: "type"; query: "type/string()" }
XmlRole { name: "lat"; query: "geometry/location/lat/string()" }
XmlRole { name: "lng"; query: "geometry/location/lng/string()" }
XmlRole { name: "reference"; query: "reference/string()" }
XmlRole { name: "id"; query: "id/string()" }
onStatusChanged: {
if (status === XmlListModel.Ready) {
console.log("xmlModel OK - count =", count);

When the data loading is finished the XmlListModel generates a signal which then fetches landmark information from the XmlListModel and calls the function addPushPin() to plot the coordinates on the Map element dynamically.


onXmlReadyChanged: {
console.log("******", feedModelMap.count);
var locationCount = feedModelMap.count;
for(var i=0; i<locationCount; i++ )
var name = feedModelMap.get(i).name;
var address = feedModelMap.get(i).vicinity
var latitude =feedModelMap.get(i).lat;
var longitude =feedModelMap.get(i).lng;
console.log("******",name, latitude, longitude);
map.addPushPin(latitude , longitude, name, address);

addPushPin() function creates instances of PushPin.qml component dynamically (PushPin.qml is a MapImage), and then calls the method addMapObject() to add the map object to the Map.

            function addPushPin( latitude, longitude,name,address ) {
var myArray
var count = map.markers.length
var component = Qt.createComponent("PushPin.qml");
console.log(component.status + " " + Component.Null);
var object = component.createObject(container,
{ "latid": latitude, "longit": longitude,"name":name, "address":address}
if (object.status == Component.Ready) {
console.log("Component ready");
myArray = new Array()
for (var i = 0; i<count; i++){
markers = myArray
if (object.status == Component.Error) {
console.log("Error: " + component.errorString());


MapImage {
width: 35
signal clicked(double lat, double lon,string name, string address)
source: "pushpin.png"
property alias latid: mapMarkerCordinate.latitude
property alias longit: mapMarkerCordinate.longitude
property string name:""
property string address:""
coordinate: Coordinate
id: mapMarkerCordinate;
MapMouseArea {
onClicked: mapMarker.clicked(coordinate.latitude, coordinate.longitude,name,address)

When users click on the pushpin it displays a popup message with Landmark name, address and the approximate distance of the landmark from user location.


function pushPinClicked(aLat , aLng,aName,aAddress)
myLatitude = positionSource.position.coordinate.latitude;
myLongitude = positionSource.position.coordinate.longitude;
var dist= distance(myLatitude,myLongitude,aLat,aLng);
popup.text = aName + "\n";
popup.text1 =aAddress;
popup.text2 ="You are around "+dist+" away";
popup.posX = 250;
popup.posY = 350;

The application also has the Pinch Zoom In/Out feature. The user can go back with the back key and select other landmarks from the category. We also need to keep in mind that when we add map object on the Map we also need to remove the map object. Here deleteAllPushPin() method does the same.


This is a basic Nokia Map API operation. This article also focus on how to use XmlListModel instead of LandmarkModel in Map element , handling HTTPS request from Google Places API and Creating a Map Object Dynamically using Dynamic Object Management in QML.

You can find the Windows Phone 7 version of this application here

Source Code

The full source code of the example is available here: File:NearByQML.zip

498 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.


Thank you!

We appreciate your feedback.