First version of imagefetcher. Added imagefetcher.cpp/.h
[situare] / src / situareservice / situareservice.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 <QDebug>
23 #include <QtGlobal>
24 #include <QStringList>
25 #include "situareservice.h"
26 #include "situarecommon.h"
27 #include "../cookiehandler/cookiehandler.h"
28 #include "parser.h"
29
30 SituareService::SituareService(QObject *parent, QNetworkAccessManager *manager)
31         : QObject(parent), m_networkManager(manager)
32 {
33     qDebug() << __PRETTY_FUNCTION__;
34
35     connect(&m_facebookAuthentication, SIGNAL(credentialsReady()), SLOT(credentialsReady()));
36
37     connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), SLOT(requestFinished(QNetworkReply*)));
38
39     m_imageFetcher = new ImageFetcher(new QNetworkAccessManager(this), this);
40     connect(this, SIGNAL(fetchImage(QUrl)), m_imageFetcher, SLOT(fetchImage(QUrl)));
41     connect(m_imageFetcher, SIGNAL(imageReceived(QUrl,QImage)), this,
42             SLOT(imageReceived(QUrl, QImage)));
43
44     m_credentials = m_facebookAuthentication.loginCredentials();
45 }
46
47 SituareService::~SituareService()
48 {
49     qDebug() << __PRETTY_FUNCTION__;
50
51     delete m_networkManager;
52 }
53
54 void SituareService::fetchLocations()
55 {
56     qDebug() << __PRETTY_FUNCTION__;
57
58     CookieHandler cookieHandler;
59
60     QString cookie = cookieHandler.formCookie(API_KEY, m_credentials.expires(), m_credentials.userID(),
61                                               m_credentials.sessionKey(), m_credentials.sessionSecret(),
62                                               m_credentials.sig(), EN_LOCALE);
63
64     QUrl url = formUrl(SITUARE_URL, GET_LOCATIONS);
65
66     sendRequest(url, COOKIE, cookie);
67 }
68
69 void SituareService::reverseGeo(const QPointF &coordinates)
70 {
71     qDebug() << __PRETTY_FUNCTION__;
72
73     CookieHandler cookieHandler;
74
75     QString cookie = cookieHandler.formCookie(API_KEY, m_credentials.expires(), m_credentials.userID(),
76                                               m_credentials.sessionKey(), m_credentials.sessionSecret(),
77                                               m_credentials.sig(), EN_LOCALE);
78
79     QString urlParameters = formUrlParameters(coordinates);
80     QUrl url = formUrl(SITUARE_URL, REVERSE_GEO, urlParameters);
81
82     sendRequest(url, COOKIE, cookie);
83 }
84
85 void SituareService::updateLocation(const QPointF &coordinates, const QString &status,
86                                     const bool &publish)
87 {
88     qDebug() << __PRETTY_FUNCTION__;
89
90     CookieHandler cookieHandler;
91
92     QString cookie = cookieHandler.formCookie(API_KEY, m_credentials.expires(), m_credentials.userID(),
93                                               m_credentials.sessionKey(), m_credentials.sessionSecret(),
94                                               m_credentials.sig(), EN_LOCALE);
95
96
97     QString publishValue;
98     if(publish) {
99         publishValue = PUBLISH_TRUE;
100     }
101     else {
102         publishValue = PUBLISH_FALSE;
103     }
104     QString urlParameters = formUrlParameters(coordinates, status, publishValue);
105     QUrl url = formUrl(SITUARE_URL, UPDATE_LOCATION, urlParameters);
106
107     sendRequest(url, COOKIE, cookie);
108 }
109
110 QUrl SituareService::formUrl(const QString &baseUrl, const QString &phpScript, QString urlParameters)
111 {
112     qDebug() << __PRETTY_FUNCTION__;
113     QString urlString;
114
115     urlString.append(baseUrl);
116     urlString.append(phpScript);
117     if(urlParameters != NULL)
118         urlString.append(urlParameters);
119
120     QUrl url = QUrl(urlString);
121
122     qDebug() << url;
123
124     return url;
125 }
126
127 QString SituareService::formUrlParameters(const QPointF &coordinates, QString status, QString publish)
128 {
129     QString parameters;
130
131     parameters.append(QUESTION_MARK);
132     parameters.append(LATITUDE);
133     parameters.append(EQUAL_MARK);
134     parameters.append(QString::number(coordinates.x()));
135     parameters.append(AMBERSAND_MARK);
136     parameters.append(LONGTITUDE);
137     parameters.append(EQUAL_MARK);
138     parameters.append(QString::number(coordinates.y()));
139
140     if(publish.compare(PUBLISH_TRUE) == 0) {
141         parameters.append(AMBERSAND_MARK);
142         parameters.append(PUBLISH);
143         parameters.append(EQUAL_MARK);
144         parameters.append(PUBLISH_TRUE);
145     }
146     else if(publish.compare(PUBLISH_FALSE) == 0) {
147         parameters.append(AMBERSAND_MARK);
148         parameters.append(PUBLISH);
149         parameters.append(EQUAL_MARK);
150         parameters.append(PUBLISH_FALSE);
151     }
152
153     if(status != NULL) {
154         parameters.append(AMBERSAND_MARK);
155         parameters.append(DATA);
156         parameters.append(EQUAL_MARK);
157         parameters.append(status);
158     }
159
160     return parameters;
161 }
162
163 void SituareService::sendRequest(const QUrl &url, const QString &cookieType, const QString &cookie)
164 {
165     qDebug() << __PRETTY_FUNCTION__ << "url: " << url;
166
167     QNetworkRequest request;
168
169     request.setUrl(url);
170     request.setRawHeader(cookieType.toAscii(), cookie.toUtf8());
171
172     QNetworkReply *reply = m_networkManager->get(request);
173
174     m_currentRequests.append(reply);
175 }
176
177 void SituareService::requestFinished(QNetworkReply *reply)
178 {
179     qDebug() << __PRETTY_FUNCTION__;
180
181     QUrl url = reply->url();
182     qDebug() << "BytesAvailable: " << reply->bytesAvailable();
183     if (reply->error()) {
184         qDebug() << reply->errorString();
185         emit error(reply->errorString());
186         // ToDo: some general http error handling etc, signal UI?
187     }
188     else {
189         qint64 max = reply->size();
190         QByteArray replyArray = reply->read(max);
191         qDebug() << "Reply from: " << url << "reply " << replyArray;
192         // ToDo: results handling includes Situare's errors
193         // works like situare's error handling i.e. both lat & lon are missing/wrong
194         // -> we get only error for wrong lon
195         if(replyArray == ERROR_LAT.toAscii()) {
196             qDebug() << "Error: " << ERROR_LAT;
197             // ToDo: signal UI?
198             emit error(replyArray);
199         }
200         else if(replyArray == ERROR_LON.toAscii()) {
201             qDebug() << "Error: " << ERROR_LON;
202             // ToDo: signal UI?
203             emit error(replyArray);
204         }
205         else if(replyArray.contains(ERROR_SESSION.toAscii())) {
206             qDebug() << "Error: " << ERROR_SESSION;
207             // ToDo: signal UI?
208             emit error(replyArray);
209         }
210         else if(replyArray.startsWith(OPENING_BRACE_MARK.toAscii())) {
211             qDebug() << "JSON string";
212             parseUserData(replyArray);
213         }
214         else if(replyArray == "") {
215             qDebug() << "No error, update was successful";
216         }
217         else {
218             // Street address ready
219             QString address(replyArray);
220             emit reverseGeoReady(address);
221         }
222     }
223     m_currentRequests.removeAll(reply);
224     reply->deleteLater();
225 }
226
227 void SituareService::credentialsReady()
228 {
229     qDebug() << __PRETTY_FUNCTION__;
230     m_credentials = m_facebookAuthentication.loginCredentials();
231 }
232
233 void SituareService::parseUserData(const QByteArray &jsonReply)
234 {
235     qDebug() << __PRETTY_FUNCTION__;
236
237     QJson::Parser parser;
238     bool ok;
239
240     QVariantMap result = parser.parse (jsonReply, &ok).toMap();
241     if (!ok) {
242
243         qFatal("An error occurred during parsing");
244         exit (1);
245     }
246
247     QList<User *> friendsList;
248
249     QVariant userVariant = result.value("user");
250     QMap<QString, QVariant> userMap = userVariant.toMap();
251
252     QPointF coordinates(userMap["longitude"].toReal(), userMap["latitude"].toReal());
253
254     QUrl imageUrl = userMap["profile_pic"].toUrl();
255
256     User user = User(userMap["address"].toString(), coordinates, userMap["name"].toString(),
257                   userMap["note"].toString(), imageUrl, userMap["timestamp"].toString(),
258                   true, userMap["uid"].toString());
259
260     foreach (QVariant friendsVariant, result["friends"].toList()) {
261       QMap<QString, QVariant> friendMap = friendsVariant.toMap();
262       QVariant distance = friendMap["distance"];
263       QMap<QString, QVariant> distanceMap = distance.toMap();
264
265       QPointF coordinates(friendMap["longitude"].toReal(), friendMap["latitude"].toReal());
266
267       QUrl imageUrl = friendMap["profile_pic"].toUrl();
268
269       User *user = new User(friendMap["address"].toString(), coordinates, friendMap["name"].toString(),
270                             friendMap["note"].toString(), imageUrl, friendMap["timestamp"].toString(),
271                             false, friendMap["uid"].toString(), distanceMap["units"].toString(),
272                             distanceMap["value"].toDouble());
273
274       friendsList.append(user);
275     }
276     emit userDataChanged(user, friendsList);
277 }
278
279 void SituareService::imageReceived(const QUrl &url, const QImage &image)
280 {
281     qDebug() << __PRETTY_FUNCTION__;
282     qDebug() << "Image URL: " << url << " size :" << image.size();
283     //ToDo: where now?
284 }