Implemented MapRouteItem
[situare] / src / routing / routingservice.cpp
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5       Henri Lampela - henri.lampela@ixonos.com
6
7    Situare is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License
9    version 2 as published by the Free Software Foundation.
10
11    Situare is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with Situare; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
19    USA.
20 */
21
22 #include <QFile>
23 #include <QDebug>
24 #include <QtGlobal>
25 #include <QStringList>
26 #include <QNetworkReply>
27 #include <QPointF>
28
29 #include "common.h"
30 #include "network/networkaccessmanager.h"
31 #include "parser.h"
32 #include "route.h"
33 #include "routesegment.h"
34
35 #include "routingservice.h"
36
37 const int NO_ERROR = 0;
38 /// @todo REGISTER API KEY, THE FOLLOWING IS FROM CLOUDMADE EXAMPLE URL'S
39 const QString CLOUDMADE_API_KEY = "BC9A493B41014CAABB98F0471D759707";
40 /// @todo implement tokens & authentication
41
42 RoutingService::RoutingService(QObject *parent)
43         : QObject(parent)
44 {
45     qDebug() << __PRETTY_FUNCTION__;
46
47     m_networkManager = NetworkAccessManager::instance();
48     connect(m_networkManager, SIGNAL(finished(QNetworkReply*)),
49             this, SLOT(requestFinished(QNetworkReply*)), Qt::QueuedConnection);
50 }
51
52 RoutingService::~RoutingService()
53 {
54     qDebug() << __PRETTY_FUNCTION__;
55 }
56
57 void RoutingService::fetchRoute(QPointF from, QPointF to)
58 {
59     qDebug() << __PRETTY_FUNCTION__;
60
61     QString url = "http://routes.cloudmade.com/";
62     url.append(CLOUDMADE_API_KEY);
63     url.append("/api/0.3/");
64     url.append(QString::number(from.x()) + "," + QString::number(from.y()) + ",");
65     url.append(QString::number(to.x()) + "," + QString::number(to.y()));
66     url.append("/car/fastest.js?lang=en&units=km");
67
68     qWarning() << __PRETTY_FUNCTION__ << url;
69
70     sendRequest(QUrl(url));
71 }
72
73 void RoutingService::parseRouteData(const QByteArray &jsonReply)
74 {
75     qDebug() << __PRETTY_FUNCTION__;
76
77     qWarning() << __PRETTY_FUNCTION__ << jsonReply;
78
79     QJson::Parser parser;
80     bool ok;
81     QVariantMap result = parser.parse (jsonReply, &ok).toMap();
82     if (!ok) {
83         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
84         return;
85     } else {
86         if(result.value("status").toInt() == NO_ERROR) {
87             QVariant routeSummary = result.value("route_summary");
88             QMap<QString, QVariant> routeSummaryMap = routeSummary.toMap();
89
90             Route route;
91             route.setEndPointName(routeSummaryMap["end_point"].toString());
92             route.setStartPointName(routeSummaryMap["start_point"].toString());
93             route.setTotalDistance(routeSummaryMap["total_distance"].toInt());
94             route.setTotalTime(routeSummaryMap["total_time"].toInt());
95
96             foreach(QVariant routeGeometry, result["route_geometry"].toList()) {
97                 QStringList list = routeGeometry.toStringList();
98                 route.appendGeometryPoint(QPointF(list.at(1).toDouble(), list.at(0).toDouble()));
99             }
100
101             foreach(QVariant routeInstructions, result["route_instructions"].toList()) {
102                 QStringList list = routeInstructions.toStringList();
103                 RouteSegment segment;
104                 segment.setInstruction(list.at(0));
105                 segment.setLength(list.at(1).toDouble());
106                 segment.setPositionIndex(list.at(2).toInt());
107                 segment.setTime(list.at(3).toInt());
108                 segment.setLengthCaption(list.at(4));
109                 segment.setEarthDirection(list.at(5));
110                 segment.setAzimuth(list.at(6).toDouble());
111                 if (list.count() == 8) {
112                     segment.setTurnType(list.at(7));
113                     segment.setTurnAngle(list.at(8).toDouble());
114                 }
115                 route.appendSegment(segment);
116             }
117
118             emit routeParsed(route);
119         }
120     }
121 }
122
123 void RoutingService::requestFinished(QNetworkReply *reply)
124 {
125     qDebug() << __PRETTY_FUNCTION__;
126
127     if (m_currentRequests.contains(reply)) {
128
129         if (reply->error())
130             emit error(ErrorContext::NETWORK, reply->error());
131         else
132             parseRouteData(reply->readAll());
133
134         m_currentRequests.removeAll(reply);
135         reply->deleteLater();
136     }
137 }
138
139 void RoutingService::sendRequest(const QUrl &url)
140 {
141     qDebug() << __PRETTY_FUNCTION__;
142
143     QNetworkRequest request;
144
145     request.setUrl(url);
146     request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
147
148     QNetworkReply *reply = m_networkManager->get(request, true);
149
150     m_currentRequests.append(reply);
151 }