c0c2560de651212d23cdcf44c1e1d68f89fb840c
[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 "parser.h"
23
24 #include <QtAlgorithms>
25 #include <QDebug>
26 #include <QtNetwork/QNetworkReply>
27 #include <QPixmap>
28 #include <QStringList>
29 #include <QtGlobal>
30
31 #include "database.h"
32 #include "error.h"
33 #include "network/networkaccessmanager.h"
34 #include "situarecommon.h"
35 #include "ui/avatarimage.h"
36
37 #include "situareservice.h"
38
39 SituareService::SituareService(NetworkAccessManager *networkManager, ImageFetcher *imageFetcher,
40                                QObject *parent)
41         : QObject(parent),
42         m_user(0)
43 {
44     qDebug() << __PRETTY_FUNCTION__;
45
46     m_networkManager = networkManager;
47     connect(m_networkManager, SIGNAL(finished(QNetworkReply*)),
48             this, SLOT(requestFinished(QNetworkReply*)), Qt::QueuedConnection);
49
50     m_imageFetcher = imageFetcher;
51     connect(this, SIGNAL(fetchImage(QString, QUrl)),
52             m_imageFetcher, SLOT(fetchImage(QString, QUrl)));
53     connect(m_imageFetcher, SIGNAL(imageReceived(QString,QPixmap)),
54             this, SLOT(imageReceived(QString,QPixmap)));
55     connect(m_imageFetcher, SIGNAL(error(int, int)),
56             this, SIGNAL(error(int, int)));
57
58     m_database = new Database(this);
59     m_database->openDatabase();
60     m_database->createNotificationTable();
61     m_database->createUserTable();
62     m_database->createTagTable();
63     m_database->createUserTagTable();
64 }
65
66 SituareService::~SituareService()
67 {
68     qDebug() << __PRETTY_FUNCTION__;
69
70     if(m_user) {
71         delete m_user;
72         m_user = 0;
73     }
74
75     qDeleteAll(m_friendsList.begin(), m_friendsList.end());
76     m_friendsList.clear();
77 }
78
79 void SituareService::fetchMessages()
80 {
81     qDebug() << __PRETTY_FUNCTION__;
82
83     //Request sent to server does not need the UID
84     QByteArray arr = m_database->getNotifications(613374451);
85
86     parseMessagesData(arr);
87 }
88
89 void SituareService::fetchPeopleWithSimilarInterest(const GeoCoordinate &southWestCoordinates,
90                                                     const GeoCoordinate &northEastCoordinates)
91 {
92     qDebug() << __PRETTY_FUNCTION__;
93
94     //Request sent to server does not need the UID
95     QByteArray arr = m_database->getInterestingPeople(613374451,
96                                                       southWestCoordinates,
97                                                       northEastCoordinates);
98
99     parseInterestingPeopleData(arr);
100 }
101
102 void SituareService::fetchPopularTags()
103 {
104     qDebug() << __PRETTY_FUNCTION__;
105
106     QByteArray arr = m_database->getPopularTags();
107
108     parsePopularTagsData(arr);
109 }
110
111 void SituareService::fetchLocations()
112 {
113     qDebug() << __PRETTY_FUNCTION__;
114
115     QString cookie = formCookie(API_KEY, m_credentials.expires(), m_credentials.userID(),
116                                 m_credentials.sessionKey(), m_credentials.sessionSecret(),
117                                 m_credentials.sig(), EN_LOCALE);
118
119     QUrl url = formUrl(SITUARE_URL, GET_LOCATIONS);
120     sendRequest(url, COOKIE, cookie);
121 }
122
123 void SituareService::reverseGeo(const GeoCoordinate &coordinates)
124 {
125     qDebug() << __PRETTY_FUNCTION__;
126
127     QString cookie = formCookie(API_KEY, m_credentials.expires(),m_credentials.userID(),
128                                 m_credentials.sessionKey(), m_credentials.sessionSecret(),
129                                 m_credentials.sig(), EN_LOCALE);
130
131     QString urlParameters = formUrlParameters(coordinates);
132     urlParameters.append(JSON_FORMAT);
133     QUrl url = formUrl(SITUARE_URL, REVERSE_GEO, urlParameters);
134
135     sendRequest(url, COOKIE, cookie);
136 }
137
138 void SituareService::updateLocation(const GeoCoordinate &coordinates, const QString &status,
139                                     const bool &publish)
140 {
141     qDebug() << __PRETTY_FUNCTION__;
142
143     QString urlParameters = formUrlParameters(coordinates, status, publish);
144     QUrl url = formUrl(SITUARE_URL, UPDATE_LOCATION, urlParameters);
145
146     QString cookie = formCookie(API_KEY, m_credentials.expires(), m_credentials.userID(),
147                                 m_credentials.sessionKey(), m_credentials.sessionSecret(),
148                                 m_credentials.sig(), EN_LOCALE);
149
150     sendRequest(url, COOKIE, cookie);
151 }
152
153 QString SituareService::formCookie(const QString &apiKeyValue, QString expiresValue,
154                                    QString userValue, QString sessionKeyValue,
155                                    QString sessionSecretValue, const QString &signatureValue,
156                                    const QString &localeValue)
157 {
158     qDebug() << __PRETTY_FUNCTION__;
159
160     QString cookie;
161     QString apiKey;
162     QString user;
163     QString expires;
164     QString sessionKey;
165     QString sessionSecret;
166     QString locale;
167     QString variable;
168     QString signature = EQUAL_MARK;
169     QStringList variableList;
170
171     signature.append(signatureValue);
172     apiKey.append(apiKeyValue);
173     apiKey.append(UNDERLINE_MARK);
174
175     user.append(USER);
176     user.append(EQUAL_MARK);
177     expires.append(EXPIRES);
178     expires.append(EQUAL_MARK);
179     sessionKey.append(SESSION_KEY);
180     sessionKey.append(EQUAL_MARK);
181     sessionSecret.append(SESSION_SECRET);
182     sessionSecret.append(EQUAL_MARK);
183     locale.append(LOCALE);
184     locale.append(EQUAL_MARK);
185     locale.append(localeValue);
186
187     variableList.append(expires.append(expiresValue.append(BREAK_MARK)));
188     variableList.append(sessionKey.append(sessionKeyValue.append(BREAK_MARK)));
189     variableList.append(user.append(userValue).append(BREAK_MARK));
190     variableList.append(sessionSecret.append(sessionSecretValue.append(BREAK_MARK)));
191
192     cookie.append(BREAK_MARK);
193
194     foreach(variable, variableList) {
195         cookie.append(apiKey);
196         cookie.append(variable);
197     }
198     apiKey.remove(UNDERLINE_MARK);
199     cookie.append(apiKey);
200     cookie.append(signature);
201     cookie.append(BREAK_MARK);
202     cookie.append(locale);
203
204     qDebug() << cookie;
205
206     return cookie;
207 }
208
209 QUrl SituareService::formUrl(const QString &baseUrl, const QString &phpScript,
210                              QString urlParameters)
211 {
212     qDebug() << __PRETTY_FUNCTION__;
213     QString urlString;
214
215     urlString.append(baseUrl);
216     urlString.append(phpScript);
217     if(!urlParameters.isEmpty())
218         urlString.append(urlParameters);
219
220     QUrl url = QUrl(urlString);
221
222     qDebug() << url;
223
224     return url;
225 }
226
227 QString SituareService::formUrlParameters(const GeoCoordinate &coordinates, QString status,
228                                           bool publish)
229 {
230     qDebug() << __PRETTY_FUNCTION__;
231
232     // one scene pixel is about 5.4e-6 degrees, the integer part is max three digits and one
233     // additional digit is added for maximum precision
234     const int COORDINATE_PRECISION = 10;
235
236     QString parameters;
237
238     parameters.append(QUESTION_MARK);
239     parameters.append(LATITUDE);
240     parameters.append(EQUAL_MARK);
241     parameters.append(QString::number(coordinates.latitude(), 'f', COORDINATE_PRECISION));
242     parameters.append(AMBERSAND_MARK);
243     parameters.append(LONGTITUDE);
244     parameters.append(EQUAL_MARK);
245     parameters.append(QString::number(coordinates.longitude(), 'f', COORDINATE_PRECISION));
246
247     parameters.append(AMBERSAND_MARK);
248     parameters.append(PUBLISH);
249     parameters.append(EQUAL_MARK);
250
251     if(publish)
252         parameters.append(PUBLISH_TRUE);
253     else
254         parameters.append(PUBLISH_FALSE);
255
256     if(!status.isEmpty()) {
257         parameters.append(AMBERSAND_MARK);
258         parameters.append(DATA);
259         parameters.append(EQUAL_MARK);
260         parameters.append(status);
261     }
262
263     return parameters;
264 }
265
266 void SituareService::sendMessage(const QString &receiverId, const QString &message,
267                                  const GeoCoordinate &coordinates)
268 {
269     qDebug() << __PRETTY_FUNCTION__;
270
271     if (m_database->sendMessage(613374451, receiverId.toULongLong(), message, coordinates))
272         emit updateWasSuccessful(SituareService::SuccessfulSendMessage);
273 }
274
275 void SituareService::sendRequest(const QUrl &url, const QString &cookieType, const QString &cookie)
276 {
277     qDebug() << __PRETTY_FUNCTION__;
278
279     QNetworkRequest request;
280
281     request.setUrl(url);
282     request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
283     request.setRawHeader(cookieType.toAscii(), cookie.toUtf8());
284
285     QNetworkReply *reply = m_networkManager->get(request, true);
286
287     m_currentRequests.append(reply);
288 }
289
290 void SituareService::requestFinished(QNetworkReply *reply)
291 {
292     qDebug() << __PRETTY_FUNCTION__;
293
294     //Reply from situare
295     if (m_currentRequests.contains(reply)) {
296
297         qDebug() << "BytesAvailable: " << reply->bytesAvailable();
298
299         if (reply->error()) {
300             emit error(ErrorContext::NETWORK, reply->error());
301         } else {
302             QByteArray replyArray = reply->readAll();
303             qDebug() << "Reply from: " << reply->url() << "reply " << replyArray;
304
305             if(replyArray == ERROR_LAT.toAscii()) {
306                 qDebug() << "Error: " << ERROR_LAT;
307                 emit error(ErrorContext::SITUARE, SituareError::UPDATE_FAILED);
308             } else if(replyArray == ERROR_LON.toAscii()) {
309                 qDebug() << "Error: " << ERROR_LON;
310                 emit error(ErrorContext::SITUARE, SituareError::UPDATE_FAILED);
311             } else if(replyArray.contains(ERROR_SESSION.toAscii())) {
312                 qDebug() << "Error: " << ERROR_SESSION;
313                 emit error(ErrorContext::SITUARE, SituareError::SESSION_EXPIRED);
314             } else if(replyArray.startsWith(OPENING_BRACE_MARK.toAscii())) {
315                 qDebug() << "JSON string";
316                 parseUserData(replyArray);
317             } else if(replyArray.isEmpty()) {
318                 if(reply->url().toString().contains(UPDATE_LOCATION.toAscii())) {
319                     emit updateWasSuccessful(SituareService::SuccessfulUpdateLocation);
320                 } else {
321                     // session credentials are invalid
322                     emit error(ErrorContext::SITUARE, SituareError::SESSION_EXPIRED);
323                 }
324             } else {
325                 // unknown reply
326                 emit error(ErrorContext::SITUARE, SituareError::ERROR_GENERAL);
327             }
328         }
329         m_currentRequests.removeAll(reply);
330         reply->deleteLater();
331     }
332 }
333
334 void SituareService::credentialsReady(const FacebookCredentials &credentials)
335 {
336     qDebug() << __PRETTY_FUNCTION__;
337
338     m_credentials = credentials;
339 }
340
341 void SituareService::parseInterestingPeopleData(const QByteArray &jsonReply)
342 {
343     qDebug() << __PRETTY_FUNCTION__;
344
345     QJson::Parser parser;
346     bool ok;
347
348     QVariantMap result = parser.parse(jsonReply, &ok).toMap();
349
350     if (!ok) {
351         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
352         return;
353     } else {
354         QVariant people = result["people"];
355
356         QList<User> friends;
357         QList<User> others;
358
359         foreach (QVariant personVariant, people.toMap().value("friends").toList()) {
360             User user;
361             QMap<QString, QVariant> person = personVariant.toMap();
362             user.setUserId(person["uid"].toString());
363             user.setName(person["name"].toString());
364             user.setProfileImage(AvatarImage::create(
365                     QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
366             user.setProfileImageUrl(person["image_url"].toUrl());
367             user.setTags(person["tags"].toList());
368
369             bool latOk;
370             qreal latitude = person["latitude"].toReal(&latOk);
371             bool lonOk;
372             qreal longitude = person["longitude"].toReal(&lonOk);
373
374             if (latOk && lonOk) {
375                 user.setCoordinates(GeoCoordinate(latitude, longitude));
376
377                 //This should be from the server
378                 GeoCoordinate myCoord(65.008, 25.5523);
379                 qreal meters = myCoord.distanceTo(user.coordinates());
380                 qreal value;
381                 QString unit;
382                 if (meters < 1000) {
383                     value = meters;
384                     unit = "m";
385                 } else {
386                     value = meters/1000;
387                     unit = "km";
388                 }
389                 user.setDistance(value, unit);
390             }
391
392             friends.append(user);
393
394             //Remove comment when the actual server is used
395             //emit fetchImage(user.userId(), user.profileImageUrl());
396         }
397
398         foreach (QVariant personVariant, people.toMap().value("others").toList()) {
399             User user;
400             QMap<QString, QVariant> person = personVariant.toMap();
401             user.setUserId(person["uid"].toString());
402             user.setName(person["name"].toString());
403             user.setProfileImage(AvatarImage::create(
404                     QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
405             user.setProfileImageUrl(person["image_url"].toUrl());
406             user.setTags(person["tags"].toList());
407
408             others.append(user);
409
410             //Remove comment when the actual server is used
411             //emit fetchImage(user.userId(), user.profileImageUrl());
412         }
413
414         emit interestingPeopleReceived(friends, others);
415     }
416 }
417
418 void SituareService::parseMessagesData(const QByteArray &jsonReply)
419 {
420     QJson::Parser parser;
421     bool ok;
422
423     QVariantMap result = parser.parse(jsonReply, &ok).toMap();
424
425     if (!ok) {
426         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
427         return;
428     } else {
429         QVariant messages = result["messages"];
430
431         QList<Message> received;
432         QList<Message> sent;
433
434         foreach (QVariant messageVariant, messages.toMap().value("received").toList()) {
435             Message message(Message::MessageTypeReceived);
436             QMap<QString, QVariant> messageMap = messageVariant.toMap();
437             message.setId(messageMap["id"].toString());
438             message.setSenderId(messageMap["sender_id"].toString());
439             message.setReceiverId(messageMap["receiver_id"].toString());
440             message.setSenderName(messageMap["sender_name"].toString());
441             uint timestampSeconds = messageMap["timestamp"].toUInt();
442             message.setTimestamp(QDateTime::fromTime_t(timestampSeconds));
443             message.setText(messageMap["text"].toString());
444             message.setImage(AvatarImage::create(
445                     QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
446
447             bool latOk;
448             qreal latitude = messageMap["latitude"].toReal(&latOk);
449             bool lonOk;
450             qreal longitude = messageMap["longitude"].toReal(&lonOk);
451
452             if (latOk && lonOk) {
453                 message.setAddress(messageMap["address"].toString());
454                 message.setCoordinates(GeoCoordinate(latitude, longitude));
455             }
456
457             received.append(message);
458
459             //emit fetchImage(message.id(), messageMap["image_url"].toString());
460         }
461
462         foreach (QVariant messageVariant, messages.toMap().value("sent").toList()) {
463             Message message(Message::MessageTypeSent);
464             QMap<QString, QVariant> messageMap = messageVariant.toMap();
465             message.setId(messageMap["id"].toString());
466             message.setSenderId(messageMap["sender_id"].toString());
467             message.setReceiverId(messageMap["receiver_id"].toString());
468             message.setSenderName(messageMap["sender_name"].toString());
469             uint timestampSeconds = messageMap["timestamp"].toUInt();
470             message.setTimestamp(QDateTime::fromTime_t(timestampSeconds));
471             message.setText(messageMap["text"].toString());
472             message.setImage(AvatarImage::create(
473                     QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
474
475             bool latOk;
476             qreal latitude = messageMap["latitude"].toReal(&latOk);
477             bool lonOk;
478             qreal longitude = messageMap["longitude"].toReal(&lonOk);
479
480             if (latOk && lonOk) {
481                 message.setAddress(messageMap["address"].toString());
482                 message.setCoordinates(GeoCoordinate(latitude, longitude));
483             }
484
485             sent.append(message);
486
487             //emit fetchImage(message.id(), messageMap["image_url"].toString());
488         }
489
490         emit messagesReceived(received, sent);
491     }
492 }
493
494 void SituareService::parsePopularTagsData(const QByteArray &jsonReply)
495 {
496     qDebug() << __PRETTY_FUNCTION__;
497
498     QJson::Parser parser;
499     bool ok;
500
501     QVariantMap result = parser.parse(jsonReply, &ok).toMap();
502
503     if (!ok) {
504         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
505         return;
506     } else {
507         QHash<QString, QString> popularTags;
508
509         foreach (QVariant tagVariant, result["popular_tags"].toList()) {
510             QMap<QString, QVariant> tag = tagVariant.toMap();
511             popularTags.insert(tag["id"].toString(), tag["name"].toString());
512         }
513
514         emit popularTagsReceived(popularTags);
515     }
516 }
517
518
519 void SituareService::parseUserData(const QByteArray &jsonReply)
520 {
521     qDebug() << __PRETTY_FUNCTION__;
522
523     m_defaultImage = false;
524
525     QJson::Parser parser;
526     bool ok;
527
528     QVariantMap result = parser.parse (jsonReply, &ok).toMap();
529
530     if (!ok) {
531         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
532         return;
533     } else {
534
535         if(result.contains("ErrorCode")) {
536             QVariant errorVariant = result.value("ErrorCode");
537             emit error(ErrorContext::SITUARE, errorVariant.toInt());
538             return;
539         } else if(result.contains("user")) {
540
541             QVariant userVariant = result.value("user");
542             QMap<QString, QVariant> userMap = userVariant.toMap();
543
544             GeoCoordinate coordinates(userMap["latitude"].toReal(), userMap["longitude"].toReal());
545
546             QUrl imageUrl = userMap[NORMAL_SIZE_PROFILE_IMAGE].toUrl();
547
548             QString address = userMap["address"].toString();
549             if(address.isEmpty()) {
550                 QStringList location;
551                 location.append(QString::number(coordinates.latitude()));
552                 location.append(QString::number(coordinates.longitude()));
553                 address = location.join(", ");
554             }
555
556             User user = User(address, coordinates, userMap["name"].toString(),
557                           userMap["note"].toString(), imageUrl, userMap["timestamp"].toString(),
558                           true, userMap["uid"].toString());
559
560             if(imageUrl.isEmpty()) {
561                 // user doesn't have profile image, so we need to get him a silhouette image
562                 m_defaultImage = true;
563                 user.setProfileImage(AvatarImage::create(
564                         QPixmap(":/res/images/empty_avatar_big.png"), AvatarImage::Large));
565             }
566
567             QList<User> tmpFriendsList;
568
569             foreach (QVariant friendsVariant, result["friends"].toList()) {
570               QMap<QString, QVariant> friendMap = friendsVariant.toMap();
571               QVariant distance = friendMap["distance"];
572               QMap<QString, QVariant> distanceMap = distance.toMap();
573
574               GeoCoordinate coordinates(friendMap["latitude"].toReal(),friendMap["longitude"].toReal());
575
576               QUrl imageUrl = friendMap["profile_pic"].toUrl();
577
578               QString address = friendMap["address"].toString();
579               if(address.isEmpty()) {
580                   QStringList location;
581                   location.append(QString::number(coordinates.latitude()));
582                   location.append(QString::number(coordinates.longitude()));
583                   address = location.join(", ");
584               }
585
586               User buddy = User(address, coordinates, friendMap["name"].toString(),
587                                friendMap["note"].toString(), imageUrl,
588                                friendMap["timestamp"].toString(),
589                                false, friendMap["uid"].toString(), distanceMap["units"].toString(),
590                                distanceMap["value"].toDouble());
591
592               if(imageUrl.isEmpty()) {
593                   // friend doesn't have profile image, so we need to get him a silhouette image
594                   m_defaultImage = true;
595                   buddy.setProfileImage(AvatarImage::create(
596                           QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
597               }
598
599               tmpFriendsList.append(buddy);
600             }
601
602             QHash<QString, QUrl> imageUrlList; // url list for images
603
604             // set unchanged profile images or add new images to imageUrlList for downloading
605             if(m_user) {
606                 if(m_user->profileImageUrl() != user.profileImageUrl()) {
607                     if(!user.profileImageUrl().isEmpty())
608                         imageUrlList.insert(user.userId(), user.profileImageUrl());
609                 } else {
610                     user.setProfileImage(m_user->profileImage());
611                 }
612             } else {
613                 if(!user.profileImageUrl().isEmpty())
614                     imageUrlList.insert(user.userId(), user.profileImageUrl());
615             }
616
617             // clear old user object
618             if(m_user) {
619                 delete m_user;
620                 m_user = 0;
621             }
622
623             // create new user object from temporary user object
624             m_user = new User(user);
625
626             // set unchanged profile images or add new images to imageUrlList for downloading
627             if(!m_friendsList.isEmpty()) {
628                 foreach(User tmpBuddy, tmpFriendsList) {
629                     if(!tmpBuddy.profileImageUrl().isEmpty()) {
630                         bool found = false;
631                         foreach(User *buddy, m_friendsList) {
632                             if(tmpBuddy.profileImageUrl() == buddy->profileImageUrl()) {
633                                 tmpBuddy.setProfileImage(buddy->profileImage());
634                                 found = true;
635                                 break;
636                             }
637                         }
638                         if(!found && !tmpBuddy.profileImageUrl().isEmpty())
639                             imageUrlList.insert(tmpBuddy.userId(), tmpBuddy.profileImageUrl());
640                     }
641                 }
642             } else {
643                 foreach(User buddy, tmpFriendsList) {
644                     if(!buddy.profileImageUrl().isEmpty())
645                         imageUrlList.insert(buddy.userId(), buddy.profileImageUrl());
646                 }
647             }
648
649             // clear old friendlist
650             qDeleteAll(m_friendsList.begin(), m_friendsList.end());
651             m_friendsList.clear();
652
653             // populate new friendlist with temporary friendlist's data
654             foreach(User tmpFriendItem, tmpFriendsList) {
655                 User *friendItem = new User(tmpFriendItem);
656                 m_friendsList.append(friendItem);
657             }
658             tmpFriendsList.clear();
659
660             //REMOVE WHEN NOT NEEDED! get user tags and set tags to the user
661             m_user->setTags(getTags(m_user->userId()));
662
663             emit userDataChanged(m_user, m_friendsList);
664
665             // set silhouette image to imageUrlList for downloading
666             if(m_defaultImage)
667                 imageUrlList.insert("", QUrl(SILHOUETTE_URL));
668
669             addProfileImages(imageUrlList);
670             imageUrlList.clear();
671
672         } else {
673             QVariant address = result.value("address");
674             if(!address.toString().isEmpty()) {
675                 emit reverseGeoReady(address.toString());
676             } else {
677                 QStringList coordinates;
678                 coordinates.append(result.value("lat").toString());
679                 coordinates.append(result.value("lon").toString());
680
681                 emit error(ErrorContext::SITUARE, SituareError::ADDRESS_RETRIEVAL_FAILED);
682                 emit reverseGeoReady(coordinates.join(", "));
683             }
684         }
685     }
686 }
687
688 void SituareService::imageReceived(const QString &id, const QPixmap &image)
689 {
690     qDebug() << __PRETTY_FUNCTION__;
691
692     if (m_user->userId() == id)
693         emit imageReady(id, AvatarImage::create(image, AvatarImage::Large));
694     else
695         emit imageReady(id, AvatarImage::create(image, AvatarImage::Small));
696 }
697
698 void SituareService::addProfileImages(const QHash<QString, QUrl> &imageUrlList)
699 {
700     qDebug() << __PRETTY_FUNCTION__;
701
702     QHashIterator<QString, QUrl> imageUrlListIterator(imageUrlList);
703
704     while (imageUrlListIterator.hasNext()) {
705         imageUrlListIterator.next();
706         emit fetchImage(imageUrlListIterator.key(), imageUrlListIterator.value());
707     }
708 }
709
710 void SituareService::clearUserData()
711 {
712     qDebug() << __PRETTY_FUNCTION__;
713
714     qDeleteAll(m_friendsList.begin(), m_friendsList.end());
715     m_friendsList.clear();
716
717     if(m_user) {
718         delete m_user;
719         m_user = 0;
720     }
721     emit userDataChanged(m_user, m_friendsList);
722 }
723
724 QHash<QString, QString> SituareService::getTags(const QString &userId)
725 {
726     qDebug() << __PRETTY_FUNCTION__;
727
728     return m_database->getTags(userId.toInt());
729 }
730
731 void SituareService::removeTags(const QStringList &tags)
732 {
733     qDebug() << __PRETTY_FUNCTION__;
734
735     if (m_database->removeTags(613374451, tags))
736         emit updateWasSuccessful(SituareService::SuccessfulRemoveTags);
737 }
738
739 void SituareService::removeMessage(const QString &id)
740 {
741     qDebug() << __PRETTY_FUNCTION__;
742
743     if (m_database->removeMessage(613374451, id))
744         emit updateWasSuccessful(SituareService::SuccessfulRemoveMessage);
745 }
746
747 void SituareService::addTags(const QStringList &tags)
748 {
749     qWarning() << __PRETTY_FUNCTION__ << tags.count();
750
751     foreach (QString tag, tags)
752         m_database->addTag(613374451, tag);
753
754     emit updateWasSuccessful(SituareService::SuccessfulAddTags);
755 }
756
757 void SituareService::searchPeopleByTag(const QString &tag)
758 {
759     qDebug() << __PRETTY_FUNCTION__;
760
761     QByteArray arr = m_database->getInterestingPeopleByTag(613374451, tag);
762
763     parseInterestingPeopleData(arr);
764 }