×
Namespaces

Variants
Actions
(Difference between revisions)

QML Geohelper Plugin

From Nokia Developer Wiki
Jump to: navigation, search
somnathbanik (Talk | contribs)
hamishwillee (Talk | contribs)
m (Text replace - "<code cpp>" to "<code cpp-qt>")
 
(7 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 
[[Category:Qt]][[Category:Qt Mobility]][[Category:Qt Quick]][[Category:Symbian]]
 
[[Category:Qt]][[Category:Qt Mobility]][[Category:Qt Quick]][[Category:Symbian]]
__NOTOC__
+
{{ArticleMetaData <!-- v1.2 -->
__NOEDITSECTION__
+
|sourcecode= <!-- Link to example source code (e.g. [[Media:The Code Example ZIP.zip]]) -->
{{CodeSnippet
+
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
|id=...
+
|devices= N8, E7, C7
|platform=Symbian 3
+
|sdk= <!-- SDK(s) built and tested against (e.g. [http://linktosdkdownload/ Nokia Qt SDK 1.1]) -->
|devices=N8, E7, C7
+
|platform= Symbian 3
|category=QML
+
|devicecompatability= <!-- Compatible devices (e.g.: All* (must have GPS) ) -->
 +
|dependencies= <!-- Any other/external dependencies e.g.: Google Maps Api v1.0 -->
 +
|signing= <!-- Empty or one of Self-Signed, DevCert, Manufacturer -->
 +
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 +
|keywords= QML, Geocoding, Location, Maps, Map objects, JSON stringify
 +
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 +
|translated-by= <!-- [[User:XXXX]] -->
 +
|translated-from-title= <!-- Title only -->
 +
|translated-from-id= <!-- Id of translated revision -->
 +
|review-by= <!-- After re-review: [[User:username]] -->
 +
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 +
|update-by= <!-- After significant update: [[User:username]]-->
 +
|update-timestamp= <!-- After significant update: YYYYMMDD -->
 +
|creationdate= 29.04.2011
 +
|author= [[User:Jahartik]]
 +
<!-- The following are not in current metadata -->
 
|subcategory= Location
 
|subcategory= Location
|creationdate=29.04.2011
 
|keywords=QML, Geocoding, Location, Maps, Map objects, JSON stringify
 
 
}}
 
}}
  
Line 26: Line 39:
 
==Preconditions==
 
==Preconditions==
  
Qt 4.7.1 or newer and Qt mobility 1.1.0 or newer installed
+
[http://qt.nokia.com/downloads Qt SDK ]4.7.1 or newer and [http://qt.nokia.com/products/qt-addons/mobility Qt mobility ]1.1.0 or newer installed
 +
 
  
 
==Pro file ==
 
==Pro file ==
Line 32: Line 46:
 
The following capabilities and libraries are required:
 
The following capabilities and libraries are required:
  
<code cpp>
+
<code cpp-qt>
 
CAPABILITY:  
 
CAPABILITY:  
 
symbian:TARGET.CAPABILITY = NetworkServices Location ReadUserData WriteUserData
 
symbian:TARGET.CAPABILITY = NetworkServices Location ReadUserData WriteUserData
Line 43: Line 57:
 
'''geohelper.h''' applying this macro to definitions of member functions to allow them to be invoked via the''' meta-object system'''
 
'''geohelper.h''' applying this macro to definitions of member functions to allow them to be invoked via the''' meta-object system'''
  
<code cpp>
+
<code cpp-qt>
  
 
#ifndef GEOHELPER_H
 
#ifndef GEOHELPER_H
Line 138: Line 152:
 
geohelper source code  
 
geohelper source code  
  
<code cpp>
+
<code cpp-qt>
 
#include "geohelper.h"
 
#include "geohelper.h"
  
Line 559: Line 573:
 
To register the C++ type in the QML system with the name GeoHelper include following code in your main.cpp file
 
To register the C++ type in the QML system with the name GeoHelper include following code in your main.cpp file
  
<code>  
+
<code cpp-qt>  
 
qmlRegisterType<GeoHelper>("GeoHelper",1,0,"GeoHelper");
 
qmlRegisterType<GeoHelper>("GeoHelper",1,0,"GeoHelper");
 
</code>  
 
</code>  
  
 
Import geohelper plugin in QML
 
Import geohelper plugin in QML
<code>  
+
<code cpp-qt>  
 
import GeoHelper 1.0
 
import GeoHelper 1.0
 
</code>  
 
</code>  
  
 
Example use QML
 
Example use QML
<code>  
+
<code cpp-qt>  
 
GeoHelper {  
 
GeoHelper {  
 
id: geohelper…
 
id: geohelper…
 
----
 
----
mapid.center = mapid.toCoordinate(Qt.point(x, y))  
+
Geohelper developer APIs
geohelper.findAddress(mapid.center.latitude, mapid.center.longitude)
+
 
 +
Constructor and destructor
 +
GeoHelper(QObject *parent = 0);
 +
~GeoHelper();
 +
 
 +
Public slots:
 +
void findRoute(double fromLatitude, double fromLongitude, double toLatitude, double toLongitude);
 +
void findAddress(double latitude, double longitude);
 +
void findCoordinates(QString street, QString city, QString country = QString("FINLAND"));
 +
void clearMap();
 +
void removeFromMap(QString id);
 +
void drawPolyline(QString id, QString coordinateArr);
 +
void drawImage(QString id, double latitude, double longitude, QString imagepath, int xOffset, int yOffset);
 +
void drawText(QString id, double latitude, double longitude, QString text);
 +
void findObjectsInCoordinates(double latitude, double longitude);
 +
 
 +
Public signals
 +
void searchError(const QString &error);
 +
void routingError(const QString &error);
 +
void searchReply(const QString &reply);
 +
void routingReply(const QString &reply);
 +
void geomapobjectSelected(QString id, bool selected);
 +
void debugMsg(const QString &reply);
 +
 
 
</code>
 
</code>

Latest revision as of 04:18, 11 October 2012

Article Metadata
Tested with
Devices(s): N8, E7, C7
Compatibility
Platform(s): Symbian 3
Symbian
Article
Keywords: QML, Geocoding, Location, Maps, Map objects, JSON stringify
Created: jahartik (29 Apr 2011)
Last edited: hamishwillee (11 Oct 2012)



Contents

[edit] Overview

Geohelper plug-in to expose Qt mobility location geoservice APIs to QML environment

Geohelper source code includes also workaround to manage several map objects: Map object “copy” to construct the map's objects list again. This is because the objects list does not have a method to remove a single object, see method void GeoHelper::removeFromMap(QString id)

This snippet can be self-signed.

[edit] Preconditions

Qt SDK 4.7.1 or newer and Qt mobility 1.1.0 or newer installed


[edit] Pro file

The following capabilities and libraries are required:

CAPABILITY: 
symbian:TARGET.CAPABILITY = NetworkServices Location ReadUserData WriteUserData
CONFIG += mobility
MOBILITY = location

[edit] Header file

geohelper.h applying this macro to definitions of member functions to allow them to be invoked via the meta-object system

#ifndef GEOHELPER_H
#define GEOHELPER_H
 
#include <QObject>
#include <QMap>
 
#include <QGeoServiceProvider>
#include <QGeoMappingManager>
#include <QGeoSearchManager>
#include <QGeoRoutingManager>
 
#include <QDeclarativeEngine>
#include <QGeoRouteReply>
#include <QGeoRouteRequest>
 
#include <QGeoCoordinate>
 
#include <QDeclarativeItem>
#include <QGeoMapPolylineObject>
#include <QGeoMapPixmapObject>
#include <QGeoMapTextObject>
 
 
QTM_USE_NAMESPACE
 
 
class GeoHelper : public QObject
{
Q_OBJECT
Q_PROPERTY(QDeclarativeItem* map READ map WRITE setMap)
public:
explicit GeoHelper(QObject *parent = 0);
~GeoHelper();
 
QDeclarativeItem *map() const {return mapitem; }
void setMap(QDeclarativeItem *map) { mapitem = map; listRef = QDeclarativeListReference(mapitem, "objects");};
 
Q_INVOKABLE void findRoute(double fromLatitude, double fromLongitude, double toLatitude, double toLongitude);
Q_INVOKABLE void findAddress(double latitude, double longitude);
Q_INVOKABLE void findCoordinates(QString street, QString city, QString country = QString("FINLAND"));
Q_INVOKABLE void clearMap();
Q_INVOKABLE void removeFromMap(QString id);
Q_INVOKABLE void drawPolyline(QString id, QString coordinateArr);
Q_INVOKABLE void drawImage(QString id, double latitude, double longitude, QString imagepath, int xOffset, int yOffset);
Q_INVOKABLE void drawText(QString id, double latitude, double longitude, QString text);
Q_INVOKABLE void findObjectsInCoordinates(double latitude, double longitude);
 
 
signals:
void searchError(const QString &error);
void routingError(const QString &error);
 
void searchReply(const QString &reply);
void routingReply(const QString &reply);
 
void geomapobjectSelected(QString id, bool selected);
 
void debugMsg(const QString &reply);
 
 
private slots:
void searchErrorSlot(QGeoSearchReply *reply, QGeoSearchReply::Error error, QString errorString = QString());
void searchFinishedSlot(QGeoSearchReply *reply);
 
void routingErrorSlot(QGeoRouteReply *reply, QGeoRouteReply::Error error, QString errorString);
void routingFinishedSlot(QGeoRouteReply * reply);
 
 
 
private:
 
QGeoServiceProvider* provider;
QGeoMappingManager* mappingManager;
QGeoSearchManager* searchManager;
QGeoRoutingManager* routingManager;
QDeclarativeContext* context;
QDeclarativeItem* mapitem;
 
 
QMap<QString, QGeoMapObject *> mapobjects;
QDeclarativeListReference listRef;
 
};
 
#endif // GEOHELPER_H


[edit] Source file

geohelper source code

#include "geohelper.h"
 
#include <QScriptEngine>
#include <QScriptValue>
#include <QScriptValueIterator>
 
#include <QDeclarativeListReference>
#include <QGeoMapRouteObject>
 
 
GeoHelper::GeoHelper(QObject *parent) :
QObject(parent)
{
provider = new QGeoServiceProvider("nokia");
mappingManager = provider->mappingManager();
searchManager = provider->searchManager();
routingManager = provider->routingManager();
mapitem = NULL;
 
QObject::connect(searchManager, SIGNAL(error(QGeoSearchReply *, QGeoSearchReply::Error, QString)), this, SLOT(searchErrorSlot(QGeoSearchReply *, QGeoSearchReply::Error, QString)));
QObject::connect(searchManager, SIGNAL(finished(QGeoSearchReply*)), this, SLOT(searchFinishedSlot(QGeoSearchReply*)));
 
QObject::connect(routingManager, SIGNAL(error(QGeoRouteReply*, QGeoRouteReply::Error, QString)), this, SLOT(routingErrorSlot(QGeoRouteReply*, QGeoRouteReply::Error, QString)));
QObject::connect(routingManager, SIGNAL(finished(QGeoRouteReply*)), this, SLOT(routingFinishedSlot(QGeoRouteReply*)));
}
 
GeoHelper::~GeoHelper()
{
clearMap();
 
if (provider)
{
delete provider;
provider = NULL;
}
}
 
 
void GeoHelper::searchErrorSlot(QGeoSearchReply *reply, QGeoSearchReply::Error error, QString errorString)
{
emit searchError(errorString);
}
 
void GeoHelper::searchFinishedSlot(QGeoSearchReply *reply)
{
if (reply->error() == QGeoSearchReply::NoError)
{
QScriptEngine scriptEngine;
QScriptValue replyObject = scriptEngine.newArray();
 
QList<QGeoPlace> places = reply->places();
for (int i = 0; i < places.count(); i++)
{
QScriptValue placeObject = scriptEngine.newObject();
 
QScriptValue coordinateObject = scriptEngine.newObject();
QGeoCoordinate coordinate = places[i].coordinate();
coordinateObject.setProperty("latitude", QScriptValue(coordinate.latitude()));
coordinateObject.setProperty("longitude", QScriptValue(coordinate.longitude()));
placeObject.setProperty("coordinate", coordinateObject);
 
QScriptValue addressObject = scriptEngine.newObject();
QGeoAddress address = places[i].address();
 
if (!address.isEmpty())
{
addressObject.setProperty("country", address.country());
addressObject.setProperty("countryCode", address.countryCode());
addressObject.setProperty("state", address.state());
addressObject.setProperty("county", address.county());
addressObject.setProperty("city", address.city());
addressObject.setProperty("district", address.district());
addressObject.setProperty("street", address.street());
addressObject.setProperty("postcode", address.postcode());
 
}
 
placeObject.setProperty("address", addressObject);
replyObject.setProperty(i, placeObject);
}
 
 
QScriptValue fun = scriptEngine.evaluate("(function(a) { return JSON.stringify(a); })");
QScriptValueList args;
args << replyObject;
QScriptValue result = fun.call(QScriptValue(), args);
 
emit searchReply(result.toString());
}
 
 
}
 
void GeoHelper::routingErrorSlot(QGeoRouteReply *reply, QGeoRouteReply::Error error, QString errorString)
{
emit routingError(errorString);
}
 
 
void GeoHelper::routingFinishedSlot(QGeoRouteReply * reply)
{
 
if (reply->error() == QGeoRouteReply::NoError)
{
QScriptEngine scriptEngine;
QScriptValue replyObject = scriptEngine.newArray();
 
QList<QGeoCoordinate> waypoints = reply->request().waypoints();
double lat1 = 0;
double lon1 = 0;
double lat2 = 0;
double lon2 = 0;
 
if (waypoints.count() > 0)
{
/*
QString msg = QString("lat %1, lon %2 => lat %3, lon %4").
arg(waypoints.at(0).latitude()).arg(waypoints.at(0).longitude()).
arg(waypoints.at((waypoints.count()-1)).latitude()).arg(waypoints.at((waypoints.count()-1)).longitude());
emit routingError(msg);
*/

lat1 = waypoints.at(0).latitude();
lon1 = waypoints.at(0).longitude();
lat2 = waypoints.at((waypoints.count()-1)).latitude();
lon2 = waypoints.at((waypoints.count()-1)).longitude();
 
}
 
 
for (int i = 0; i < reply->routes().size(); ++i)
{
QScriptValue routeObject = scriptEngine.newObject();
QGeoRoute route = reply->routes().at(i);
 
routeObject.setProperty("distance", QScriptValue(route.distance()));
routeObject.setProperty("travelTime", QScriptValue(route.travelTime()));
routeObject.setProperty("lat1", QScriptValue(lat1));
routeObject.setProperty("lon1", QScriptValue(lon1));
routeObject.setProperty("lat2", QScriptValue(lat2));
routeObject.setProperty("lon2", QScriptValue(lon2));
 
 
QScriptValue pathObject = scriptEngine.newArray();
QList<QGeoCoordinate> path = route.path();
for (int p = 0; p < path.length(); p++)
{
QScriptValue coordinateObject = scriptEngine.newObject();
coordinateObject.setProperty("latitude", QScriptValue(path[p].latitude()));
coordinateObject.setProperty("longitude", QScriptValue(path[p].longitude()));
pathObject.setProperty(p, coordinateObject);
 
}
 
routeObject.setProperty("path", pathObject);
 
replyObject.setProperty(i, routeObject);
 
}
 
QScriptValue fun = scriptEngine.evaluate("(function(a) { return JSON.stringify(a); })");
QScriptValueList args;
args << replyObject;
QScriptValue result = fun.call(QScriptValue(), args);
 
emit routingReply(result.toString());
 
}
}
 
// ------------- Q_INVOKABLE METHODS -------
 
void GeoHelper::removeFromMap(QString id)
{
if (mapobjects.contains(id))
{
 
QGeoMapObject *obj = mapobjects.take(id);
if (obj != NULL)
{
delete obj;
obj = NULL;
}
 
// Now we have to construct the map's objects list again
// this is because the objects list does not have a method
// to remove a single object.
for (int i = 0; i < listRef.count(); i++)
listRef.at(i)->deleteLater();
 
listRef.clear();
 
QStringList keys = mapobjects.keys();
foreach (QString id, keys)
{
emit debugMsg("lisaa uudestaan " + id);
QGeoMapObject *obj = mapobjects.value(id);
if (obj != NULL)
{
if (obj->type() == QGeoMapObject::PolylineType)
{
QGeoMapPolylineObject *newobj = new QGeoMapPolylineObject;
newobj->setPath(((QGeoMapPolylineObject *)obj)->path());
newobj->setPen(QPen(QBrush(Qt::blue), 4));
newobj->setObjectName(obj->objectName());
 
listRef.append(newobj);
}
else if (obj->type() == QGeoMapObject::PixmapType)
{
QGeoMapPixmapObject *newobj = new QGeoMapPixmapObject;
newobj->setCoordinate(((QGeoMapPixmapObject *)obj)->coordinate());
newobj->setPixmap(((QGeoMapPixmapObject *)obj)->pixmap());
newobj->setOffset(QPoint(-10,-34));
newobj->setObjectName(obj->objectName());
 
listRef.append(newobj);
}
}
}
}
}
 
void GeoHelper::clearMap()
{
 
QStringList keys = mapobjects.keys();
foreach (QString id, keys)
{
QGeoMapObject *obj = mapobjects.take(id);
if (obj != NULL)
{
delete obj;
obj = NULL;
}
}
 
mapobjects.clear();
 
for (int i = 0; i < listRef.count(); i++)
listRef.at(i)->deleteLater();
 
listRef.clear();
}
 
void GeoHelper::drawPolyline(QString id, QString coordinateArr)
{
/*
[
{"latitude":61.4735985,"longitude":23.7550697},
{"latitude":61.4735985,"longitude":23.7550697}
]
 
*/

 
 
if (mapitem != NULL)
{
removeFromMap(id);
 
QScriptValue sc;
QScriptEngine engine;
sc = engine.evaluate("(" + QString(coordinateArr) + ")");
 
if (sc.isArray())
{
 
QScriptValueIterator it(sc);
QList<QGeoCoordinate> coordinates;
 
while (it.hasNext())
{
it.next();
if (it.value().property("latitude").toString() != "" && it.value().property("longitude").toString() != "")
{
coordinates << QGeoCoordinate(it.value().property("latitude").toNumber(),it.value().property("longitude").toNumber());
}
}
 
QGeoMapPolylineObject *obj = new QGeoMapPolylineObject;
obj->setPath(coordinates);
obj->setPen(QPen(QBrush(Qt::blue), 4));
obj->setObjectName(id);
 
listRef.append(obj);
 
// keep a copy to construct the map objects list again
QGeoMapPolylineObject *copyobj = new QGeoMapPolylineObject;
copyobj->setPath(coordinates);
copyobj->setPen(QPen(QBrush(Qt::blue), 4));
copyobj->setObjectName(id);
mapobjects.insert(id,copyobj);
 
 
 
}
}
}
 
void GeoHelper::drawImage(QString id, double latitude, double longitude, QString imagepath, int xOffset, int yOffset)
{
 
if (mapitem != NULL)
{
 
//emit debugMsg(QString("offset: %1, %2").arg(xOffset).arg(yOffset));
 
removeFromMap(id);
QGeoMapPixmapObject *obj = new QGeoMapPixmapObject;
obj->setCoordinate(QGeoCoordinate(latitude,longitude));
obj->setPixmap(imagepath);
obj->setOffset(QPoint(xOffset,yOffset));
//obj->setOffset(QPoint(-10,-34));
obj->setObjectName(id);
 
listRef.append(obj);
 
// keep a copy to construct the map objects list again
QGeoMapPixmapObject *copyobj = new QGeoMapPixmapObject;
copyobj->setCoordinate(QGeoCoordinate(latitude,longitude));
copyobj->setPixmap(imagepath);
copyobj->setOffset(QPoint(xOffset,yOffset));
//copyobj->setOffset(QPoint(-10,-34));
copyobj->setObjectName(id);
mapobjects.insert(id,copyobj);
 
 
}
 
}
 
 
 
QBrush usebrush(Qt::darkRed);
QPen usepen(usebrush,1);
QFont usefont("Terminal", 12);
 
 
 
void GeoHelper::drawText(QString id, double latitude, double longitude, QString text)
{
 
if (mapitem != NULL)
{
 
//emit debugMsg(QString("offset: %1, %2").arg(xOffset).arg(yOffset));
 
removeFromMap(id);
QGeoMapTextObject *obj = new QGeoMapTextObject;
obj->setCoordinate(QGeoCoordinate(latitude,longitude));
obj->setText(text);
obj->setFont(usefont);
obj->setOffset(QPoint(20,-10));
obj->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
obj->setBrush(usebrush);
obj->setPen(usepen);
obj->setObjectName(id);
 
listRef.append(obj);
 
// keep a copy to construct the map objects list again
QGeoMapTextObject *copyobj = new QGeoMapTextObject;
copyobj->setCoordinate(QGeoCoordinate(latitude,longitude));
copyobj->setText(text);
copyobj->setFont(usefont);
copyobj->setOffset(QPoint(20,-10));
copyobj->setAlignment(Qt::AlignLeft | Qt::AlignBottom);
copyobj->setBrush(usebrush);
copyobj->setPen(usepen);
copyobj->setObjectName(id);
mapobjects.insert(id,copyobj);
 
}
 
}
 
void GeoHelper::findObjectsInCoordinates(double latitude, double longitude)
{
QGeoCoordinate coord(latitude, longitude);
 
for (int i = 0; i < listRef.count(); i++)
{
if ( ((QGeoMapObject *)listRef.at(i))->contains(coord))
{
emit geomapobjectSelected(listRef.at(i)->objectName(), true);
}
}
 
}
 
void GeoHelper::findRoute(double fromLatitude, double fromLongitude, double toLatitude, double toLongitude)
{
QGeoRouteRequest *geoRouteRequest = new QGeoRouteRequest(QGeoCoordinate(fromLatitude, fromLongitude), QGeoCoordinate(toLatitude, toLongitude));
routingManager->calculateRoute(*geoRouteRequest);
}
 
void GeoHelper::findAddress(double latitude, double longitude)
{
QGeoCoordinate location(latitude,longitude);
searchManager->reverseGeocode(location);
}
 
void GeoHelper::findCoordinates(QString street, QString city, QString country)
{
/*
NOTE! This geocode method is not capable to handle the number of the street address.
But the use of the plain search alternative seems to work.
QGeoAddress address;
address.setStreet(street);
address.setCity(city);
address.setCountry(country);
searchManager->geocode(address);
*/

QString str = QString("%1,%2,%3").arg(street).arg(city).arg(country);
searchManager->search(str, QGeoSearchManager::SearchGeocode);
}

To register the C++ type in the QML system with the name GeoHelper include following code in your main.cpp file

qmlRegisterType<GeoHelper>("GeoHelper",1,0,"GeoHelper");

Import geohelper plugin in QML

import GeoHelper 1.0

Example use QML

GeoHelper { 
id: geohelper…
----
Geohelper developer APIs
 
Constructor and destructor
GeoHelper(QObject *parent = 0);
~GeoHelper();
 
Public slots:
void findRoute(double fromLatitude, double fromLongitude, double toLatitude, double toLongitude);
void findAddress(double latitude, double longitude);
void findCoordinates(QString street, QString city, QString country = QString("FINLAND"));
void clearMap();
void removeFromMap(QString id);
void drawPolyline(QString id, QString coordinateArr);
void drawImage(QString id, double latitude, double longitude, QString imagepath, int xOffset, int yOffset);
void drawText(QString id, double latitude, double longitude, QString text);
void findObjectsInCoordinates(double latitude, double longitude);
 
Public signals
void searchError(const QString &error);
void routingError(const QString &error);
void searchReply(const QString &reply);
void routingReply(const QString &reply);
void geomapobjectSelected(QString id, bool selected);
void debugMsg(const QString &reply);
This page was last modified on 11 October 2012, at 04:18.
115 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.

×