Search interesting people from server instead of db
[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       Sami Rämö - sami.ramo@ixonos.com
7
8    Situare is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License
10    version 2 as published by the Free Software Foundation.
11
12    Situare is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Situare; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
20    USA.
21 */
22
23 #include <qjson/parser.h>
24
25 #include <QDebug>
26 #include <QtNetwork/QNetworkReply>
27 #include <QPixmap>
28 #include <QStringList>
29 #include <QtAlgorithms>
30 #include <QtGlobal>
31
32 #include "database.h"
33 #include "../error.h"
34 #include "network/networkaccessmanager.h"
35 #include "situarecommon.h"
36 #include "ui/avatarimage.h"
37
38 #include "situareservice.h"
39
40 SituareService::SituareService(NetworkAccessManager *networkManager, ImageFetcher *imageFetcher,
41                                QObject *parent)
42         : QObject(parent),
43         m_user(0)
44 {
45     qDebug() << __PRETTY_FUNCTION__;
46
47     m_networkManager = networkManager;
48     connect(m_networkManager, SIGNAL(finished(QNetworkReply*)),
49             this, SLOT(requestFinished(QNetworkReply*)), Qt::QueuedConnection);
50
51     m_imageFetcher = imageFetcher;
52     connect(this, SIGNAL(fetchImage(QString, QUrl)),
53             m_imageFetcher, SLOT(fetchImage(QString, QUrl)));
54     connect(m_imageFetcher, SIGNAL(imageReceived(QString,QPixmap)),
55             this, SLOT(imageReceived(QString,QPixmap)));
56     connect(m_imageFetcher, SIGNAL(error(int, int)),
57             this, SIGNAL(error(int, int)));
58
59     m_database = new Database(this);
60     m_database->openDatabase();
61     m_database->createNotificationTable();
62     m_database->createUserTable();
63     m_database->createTagTable();
64     m_database->createUserTagTable();
65 }
66
67 SituareService::~SituareService()
68 {
69     qDebug() << __PRETTY_FUNCTION__;
70
71     if(m_user) {
72         delete m_user;
73         m_user = 0;
74     }
75
76     qDeleteAll(m_friendsList.begin(), m_friendsList.end());
77     m_friendsList.clear();
78 }
79
80 void SituareService::addProfileImages(const QHash<QString, QUrl> &imageUrlList)
81 {
82     qDebug() << __PRETTY_FUNCTION__;
83
84     QHashIterator<QString, QUrl> imageUrlListIterator(imageUrlList);
85
86     while (imageUrlListIterator.hasNext()) {
87         imageUrlListIterator.next();
88         emit fetchImage(imageUrlListIterator.key(), imageUrlListIterator.value());
89     }
90 }
91
92 void SituareService::addTags(const QStringList &tags)
93 {
94     qDebug() << __PRETTY_FUNCTION__;
95
96     QHash<QString, QString> parameters;
97     parameters.insert("tags", tags.join(","));
98
99     buildRequest(ADD_TAGS, parameters);
100 }
101
102 void SituareService::appendAccessToken(QString &requestUrl)
103 {
104     qDebug() << __PRETTY_FUNCTION__;
105
106     requestUrl.append(m_session);
107 }
108
109 void SituareService::buildRequest(const QString &script, const QHash<QString, QString> &parameters)
110 {
111     qDebug() << __PRETTY_FUNCTION__;
112
113     const QString PARAMETER_KEY_API = "api";
114     const QString PARAMETER_VALUE_API = "2.0";
115
116     QString url = SITUARE_URL;
117     url.append(script);
118     url.append("?");
119
120     // append default api version parameter if not yet specified
121     if (!parameters.contains(PARAMETER_KEY_API))
122         url.append(PARAMETER_KEY_API + "=" + PARAMETER_VALUE_API + "&");
123
124     // append parameters
125     if (!parameters.isEmpty()) {
126         QHash<QString, QString>::const_iterator i = parameters.constBegin();
127         while (i != parameters.constEnd()) {
128             url.append(i.key());
129             url.append("=");
130             url.append(i.value());
131             url.append("&");
132             i++;
133         }
134     }
135
136     /// @todo BUG: Url parameter strings are not url escaped
137
138 //    qWarning() << __PRETTY_FUNCTION__ << "request url with parameters:" << url;
139
140     if (!m_session.isEmpty()) {
141         appendAccessToken(url);
142         sendRequest(url);
143     } else {
144         emit error(ErrorContext::SITUARE, SituareError::SESSION_EXPIRED);
145     }
146 }
147
148 void SituareService::clearUserData()
149 {
150     qDebug() << __PRETTY_FUNCTION__;
151
152     qDeleteAll(m_friendsList.begin(), m_friendsList.end());
153     m_friendsList.clear();
154
155     if(m_user) {
156         delete m_user;
157         m_user = 0;
158     }
159     emit userDataChanged(m_user, m_friendsList);
160 }
161
162 QString SituareService::degreesToString(double degrees)
163 {
164     qDebug() << __PRETTY_FUNCTION__;
165
166     // one scene pixel is about 5.4e-6 degrees, the integer part is max three digits and one
167     // additional digit is added for maximum precision
168     const int PRECISION = 10;
169
170     return QString::number(degrees, 'f', PRECISION);
171 }
172
173 void SituareService::fetchMessages()
174 {
175     qDebug() << __PRETTY_FUNCTION__;
176
177     buildRequest(GET_MESSAGES, QHash<QString, QString>());
178 }
179
180 void SituareService::fetchPeopleWithSimilarInterest(const qreal distance)
181 {
182     qDebug() << __PRETTY_FUNCTION__;
183
184     const int TO_KM_DIVIDER = 1000;
185     QHash<QString, QString> parameters;
186     parameters.insert("distance", degreesToString(distance / TO_KM_DIVIDER));
187
188     buildRequest(GET_PEOPLE_WITH_SIMILAR_INTEREST, parameters);
189 }
190
191 void SituareService::fetchPopularTags()
192 {
193     qDebug() << __PRETTY_FUNCTION__;
194
195     buildRequest(GET_POPULAR_TAGS, QHash<QString, QString>());
196 }
197
198 void SituareService::fetchLocations()
199 {
200     qDebug() << __PRETTY_FUNCTION__;
201
202     QHash<QString, QString> parameters;
203     parameters.insert("extra_user_data", NORMAL_SIZE_PROFILE_IMAGE);
204
205     buildRequest(GET_LOCATIONS, parameters);
206 }
207
208 SituareService::RequestName SituareService::getRequestName(const QUrl &url) const
209 {
210     qDebug() << __PRETTY_FUNCTION__;
211
212     if (url.toString().contains(GET_LOCATIONS))
213         return SituareService::RequestGetLocations;
214     else if (url.toString().contains(UPDATE_LOCATION))
215         return SituareService::RequestUpdateLocation;
216     else if (url.toString().contains(REVERSE_GEO))
217         return SituareService::RequestReverseGeo;
218     else if (url.toString().contains(GET_MESSAGES))
219         return SituareService::RequestGetMessages;
220     else if (url.toString().contains(REMOVE_MESSAGE))
221         return SituareService::RequestRemoveMessage;
222     else if (url.toString().contains(SEND_MESSAGE))
223         return SituareService::RequestSendMessage;
224     else if (url.toString().contains(GET_PEOPLE_WITH_SIMILAR_INTEREST))
225         return SituareService::RequestGetPeopleWithSimilarInterest;
226     else if (url.toString().contains(GET_POPULAR_TAGS))
227         return SituareService::RequestGetPopularTags;
228     else if (url.toString().contains(ADD_TAGS))
229         return SituareService::RequestAddTags;
230     else if (url.toString().contains(GET_TAGS))
231         return SituareService::RequestGetTags;
232     else if (url.toString().contains(REMOVE_TAGS))
233         return SituareService::RequestRemoveTags;
234     else if (url.toString().contains(SEARCH_PEOPLE_WITH_TAG))
235         return SituareService::RequestGetPeopleWithTag;
236     else
237         return SituareService::RequestUnknown;
238 }
239
240 void SituareService::getTags()
241 {
242     qDebug() << __PRETTY_FUNCTION__;
243
244     QHash<QString, QString> parameters;
245     buildRequest(GET_TAGS, parameters);
246 }
247
248 void SituareService::imageReceived(const QString &id, const QPixmap &image)
249 {
250     qDebug() << __PRETTY_FUNCTION__;
251
252     if (m_user->userId() == id)
253         emit imageReady(QString(), AvatarImage::create(image, AvatarImage::Large));
254     else
255         emit imageReady(id, AvatarImage::create(image, AvatarImage::Small));
256 }
257
258 void SituareService::parseInterestingPeopleData(const QVariant &interestingPeopleData)
259 {
260     qDebug() << __PRETTY_FUNCTION__;
261
262     QVariant people = interestingPeopleData.toMap();
263
264     QList<User> friends;
265     QList<User> others;
266
267     foreach (QVariant personVariant, people.toMap().value("friends").toList()) {
268         User user;
269         QMap<QString, QVariant> person = personVariant.toMap();
270         user.setUserId(person["uid"].toString());
271         user.setName(person["name"].toString());
272         user.setProfileImage(AvatarImage::create(
273                 QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
274         user.setProfileImageUrl(person["pic_square"].toUrl());
275         user.setTimestamp(person["timestamp"].toString());
276         user.setTags(person["tags"].toString());
277         user.setAddress(person["address"].toString());
278         user.setNote(person["note"].toString());
279
280         bool latOk;
281         qreal latitude = person["lat"].toReal(&latOk);
282         bool lonOk;
283         qreal longitude = person["lon"].toReal(&lonOk);
284
285         if (latOk && lonOk) {
286             user.setCoordinates(GeoCoordinate(latitude, longitude));
287
288             qreal meters = person["distance"].toReal() * 1000;
289             qreal value;
290             QString unit;
291             if (meters < 1000) {
292                 value = meters;
293                 unit = "m";
294             } else {
295                 value = meters/1000;
296                 unit = "km";
297             }
298             user.setDistance(value, unit);
299         }
300
301         friends.append(user);
302
303         //Remove comment when the actual server is used
304         //emit fetchImage(user.userId(), user.profileImageUrl());
305     }
306
307     foreach (QVariant personVariant, people.toMap().value("others").toList()) {
308         User user;
309         QMap<QString, QVariant> person = personVariant.toMap();
310         user.setUserId(person["uid"].toString());
311         user.setName(person["name"].toString());
312         user.setProfileImage(AvatarImage::create(
313                 QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
314         user.setProfileImageUrl(person["pic_square"].toUrl());
315         user.setTimestamp(person["timestamp"].toString());
316         user.setTags(person["tags"].toString());
317
318         others.append(user);
319
320         emit fetchImage(user.userId(), user.profileImageUrl());
321     }
322
323     emit interestingPeopleReceived(friends, others);
324 }
325
326 void SituareService::parseReply(const QByteArray &jsonReply, RequestName requestName)
327 {
328     qDebug() << __PRETTY_FUNCTION__ << jsonReply;
329
330     QJson::Parser parser;
331     bool ok;
332
333     QVariantMap result = parser.parse(jsonReply, &ok).toMap();
334
335     if (!ok) {
336         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
337     } else {
338         QVariant resultStatus = result["ResultStatus"];
339         QVariant resultData = result["ResultData"];
340
341         if (resultStatus.toString() == "ERROR") {
342             QVariantMap errorData = resultData.toMap();
343             emit error(ErrorContext::SITUARE, errorData["ErrorCode"].toInt());
344         } else if (resultStatus.toString() == "OK") {
345             if (requestName == SituareService::RequestGetLocations)
346                 parseUserData(resultData);
347             else if (requestName == SituareService::RequestUpdateLocation)
348                 emit updateWasSuccessful(SituareService::SuccessfulUpdateLocation);
349             else if (requestName == SituareService::RequestRemoveMessage)
350                 emit updateWasSuccessful(SituareService::SuccessfulRemoveMessage);
351             else if (requestName == SituareService::RequestReverseGeo)
352                 parseReverseGeoData(resultData);
353             else if (requestName == SituareService::RequestGetMessages)
354                 parseMessagesData(resultData);
355             else if (requestName == SituareService::RequestSendMessage)
356                 emit updateWasSuccessful((SituareService::SuccessfulSendMessage));
357             else if (requestName == SituareService::RequestGetPeopleWithSimilarInterest)
358                 parseInterestingPeopleData(resultData);
359             else if (requestName == SituareService::RequestGetPopularTags)
360                 parsePopularTagsData(resultData);
361             else if (requestName == SituareService::RequestAddTags)
362                 emit updateWasSuccessful(SituareService::SuccessfulAddTags);
363             else if (requestName == SituareService::RequestGetTags)
364                 parseUserTagsData(resultData);
365             else if (requestName == SituareService::RequestRemoveTags)
366                 emit updateWasSuccessful(SituareService::SuccessfulRemoveTags);
367             else if (requestName == SituareService::RequestGetPeopleWithTag)
368                 parseInterestingPeopleData(resultData);
369         }
370     }
371 }
372
373 void SituareService::parseReverseGeoData(const QVariant &reverseGeoData)
374 {
375     qDebug() << __PRETTY_FUNCTION__;
376
377     QVariantMap result = reverseGeoData.toMap();
378
379     if (result.contains("address") && !result["address"].toString().isEmpty()) {
380         emit reverseGeoReady(result["address"].toString());
381     } else {
382         QStringList coordinates;
383         coordinates.append(result["lat"].toString());
384         coordinates.append(result["lon"].toString());
385         emit error(ErrorContext::SITUARE, SituareError::ADDRESS_RETRIEVAL_FAILED);
386         emit reverseGeoReady(coordinates.join(", "));
387     }
388 }
389
390 void SituareService::parseUserData(const QVariant &userData)
391 {
392     qDebug() << __PRETTY_FUNCTION__;
393
394     m_defaultImage = false;
395
396     QVariantMap result = userData.toMap();
397
398     if (result.contains("user")) {
399
400         QVariant userVariant = result.value("user");
401         QMap<QString, QVariant> userMap = userVariant.toMap();
402
403         GeoCoordinate coordinates(userMap["latitude"].toReal(), userMap["longitude"].toReal());
404
405         QUrl imageUrl = userMap[NORMAL_SIZE_PROFILE_IMAGE].toUrl();
406
407         if(imageUrl.isEmpty()) {
408             // user doesn't have profile image, so we need to get him a silhouette image
409             m_defaultImage = true;
410         }
411
412         QString address = userMap["address"].toString();
413         if(address.isEmpty()) {
414             QStringList location;
415             location.append(QString::number(coordinates.latitude()));
416             location.append(QString::number(coordinates.longitude()));
417             address = location.join(", ");
418         }
419
420         User user = User(address, coordinates, userMap["name"].toString(),
421                       userMap["note"].toString(), imageUrl, userMap["timestamp"].toString(),
422                       true, userMap["uid"].toString());
423
424         if(imageUrl.isEmpty()) {
425             // user doesn't have profile image, so we need to get him a silhouette image
426             m_defaultImage = true;
427             user.setProfileImage(AvatarImage::create(
428                     QPixmap(":/res/images/empty_avatar_big.png"), AvatarImage::Large));
429         }
430
431         QList<User> tmpFriendsList;
432
433         foreach (QVariant friendsVariant, result["friends"].toList()) {
434           QMap<QString, QVariant> friendMap = friendsVariant.toMap();
435           QVariant distance = friendMap["distance"];
436           QMap<QString, QVariant> distanceMap = distance.toMap();
437
438           GeoCoordinate coordinates(friendMap["latitude"].toReal(),friendMap["longitude"].toReal());
439
440           QUrl imageUrl = friendMap["profile_pic"].toUrl();
441
442           if(imageUrl.isEmpty()) {
443               // friend doesn't have profile image, so we need to get him a silhouette image
444               m_defaultImage = true;
445           }
446
447           QString address = friendMap["address"].toString();
448           if(address.isEmpty()) {
449               QStringList location;
450               location.append(QString::number(coordinates.latitude()));
451               location.append(QString::number(coordinates.longitude()));
452               address = location.join(", ");
453           }
454
455           User buddy = User(address, coordinates, friendMap["name"].toString(),
456                            friendMap["note"].toString(), imageUrl,
457                            friendMap["timestamp"].toString(),
458                            false, friendMap["uid"].toString(), distanceMap["units"].toString(),
459                            distanceMap["value"].toDouble());
460
461           if(imageUrl.isEmpty()) {
462               // friend doesn't have profile image, so we need to get him a silhouette image
463               m_defaultImage = true;
464               buddy.setProfileImage(AvatarImage::create(
465                       QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
466           }
467
468           tmpFriendsList.append(buddy);
469         }
470
471         QHash<QString, QUrl> imageUrlList; // url list for images
472
473         // set unchanged profile images or add new images to imageUrlList for downloading
474         if(m_user) {
475             if(m_user->profileImageUrl() != user.profileImageUrl()) {
476                 if(!user.profileImageUrl().isEmpty())
477                     imageUrlList.insert(user.userId(), user.profileImageUrl());
478             } else {
479                 user.setProfileImage(m_user->profileImage());
480             }
481         } else {
482             if(!user.profileImageUrl().isEmpty())
483                 imageUrlList.insert(user.userId(), user.profileImageUrl());
484         }
485
486         // clear old user object
487         if(m_user) {
488             delete m_user;
489             m_user = 0;
490         }
491
492         // create new user object from temporary user object
493         m_user = new User(user);
494
495         // set unchanged profile images or add new images to imageUrlList for downloading
496         if(!m_friendsList.isEmpty()) {
497             foreach(User tmpBuddy, tmpFriendsList) {
498                 if(!tmpBuddy.profileImageUrl().isEmpty()) {
499                     bool found = false;
500                     foreach(User *buddy, m_friendsList) {
501                         if(tmpBuddy.profileImageUrl() == buddy->profileImageUrl()) {
502                             tmpBuddy.setProfileImage(buddy->profileImage());
503                             found = true;
504                             break;
505                         }
506                     }
507                     if(!found && !tmpBuddy.profileImageUrl().isEmpty())
508                         imageUrlList.insert(tmpBuddy.userId(), tmpBuddy.profileImageUrl());
509                 }
510             }
511         } else {
512             foreach(User buddy, tmpFriendsList) {
513                 if(!buddy.profileImageUrl().isEmpty())
514                     imageUrlList.insert(buddy.userId(), buddy.profileImageUrl());
515             }
516         }
517
518         // clear old friendlist
519         qDeleteAll(m_friendsList.begin(), m_friendsList.end());
520         m_friendsList.clear();
521
522         // populate new friendlist with temporary friendlist's data
523         foreach(User tmpFriendItem, tmpFriendsList) {
524             User *friendItem = new User(tmpFriendItem);
525             m_friendsList.append(friendItem);
526         }
527         tmpFriendsList.clear();
528
529         emit userDataChanged(m_user, m_friendsList);
530
531         // set silhouette image to imageUrlList for downloading
532         if(m_defaultImage)
533             imageUrlList.insert("", QUrl(SILHOUETTE_URL));
534
535         addProfileImages(imageUrlList);
536         imageUrlList.clear();
537     }
538 }
539
540 void SituareService::parseMessagesData(const QVariant &messagesData)
541 {
542     QVariantMap result = messagesData.toMap();
543
544     QList<Message> received;
545     QList<Message> sent;
546
547     foreach (QVariant messageVariant, result["received"].toList()) {
548         Message message(Message::MessageTypeReceived);
549         QMap<QString, QVariant> messageMap = messageVariant.toMap();
550         message.setId(messageMap["mid"].toString());
551         message.setSenderId(messageMap["sid"].toString());
552         message.setReceiverId(messageMap["rid"].toString());
553         message.setSenderName(messageMap["name"].toString());
554         uint timestampSeconds = messageMap["timestamp"].toUInt();
555         message.setTimestamp(QDateTime::fromTime_t(timestampSeconds));
556         message.setText(messageMap["message"].toString());
557         message.setImage(AvatarImage::create(
558                 QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
559
560         bool latOk;
561         qreal latitude = messageMap["lat"].toReal(&latOk);
562         bool lonOk;
563         qreal longitude = messageMap["lon"].toReal(&lonOk);
564
565         if (latOk && lonOk) {
566             message.setAddress(messageMap["address"].toString());
567             message.setCoordinates(GeoCoordinate(latitude, longitude));
568         }
569
570         received.append(message);
571
572         emit fetchImage(message.id(), messageMap["pic_square"].toString());
573     }
574
575     foreach (QVariant messageVariant, result["sent"].toList()) {
576         Message message(Message::MessageTypeSent);
577         QMap<QString, QVariant> messageMap = messageVariant.toMap();
578         message.setId(messageMap["mid"].toString());
579         message.setSenderId(messageMap["sid"].toString());
580         message.setReceiverId(messageMap["rid"].toString());
581         message.setSenderName(messageMap["name"].toString());
582         uint timestampSeconds = messageMap["timestamp"].toUInt();
583         message.setTimestamp(QDateTime::fromTime_t(timestampSeconds));
584         message.setText(messageMap["message"].toString());
585         message.setImage(AvatarImage::create(
586                 QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
587
588         bool latOk;
589         qreal latitude = messageMap["lat"].toReal(&latOk);
590         bool lonOk;
591         qreal longitude = messageMap["lon"].toReal(&lonOk);
592
593         if (latOk && lonOk) {
594             message.setAddress(messageMap["address"].toString());
595             message.setCoordinates(GeoCoordinate(latitude, longitude));
596         }
597
598         sent.append(message);
599
600         emit fetchImage(message.id(), messageMap["pic_square"].toString());
601     }
602
603     emit messagesReceived(received, sent);
604 }
605
606 void SituareService::parsePopularTagsData(const QVariant &popularTagsData)
607 {
608     qDebug() << __PRETTY_FUNCTION__;
609
610     QVariantMap result = popularTagsData.toMap();
611     QHash<QString, QString> popularTags;
612
613     foreach (QVariant tagVariant, result["popular_tags"].toList()) {
614         QMap<QString, QVariant> tag = tagVariant.toMap();
615         popularTags.insert(tag["tid"].toString(), tag["name"].toString());
616     }
617
618     emit popularTagsReceived(popularTags);
619 }
620
621 void SituareService::parseUserTagsData(const QVariant &userTagsData)
622 {
623     qDebug() << __PRETTY_FUNCTION__;
624
625     QVariantMap result = userTagsData.toMap();
626     QHash<QString, QString> userTags;
627
628     foreach (QVariant tagVariant, result["user_tags"].toList()) {
629         QMap<QString, QVariant> tag = tagVariant.toMap();
630         userTags.insert(tag["tid"].toString(), tag["name"].toString());
631     }
632
633     emit userTagsReceived(userTags);
634 }
635
636 void SituareService::removeMessage(const QString &id)
637 {
638     qDebug() << __PRETTY_FUNCTION__;
639
640     QHash<QString, QString> parameters;
641     parameters.insert("mid", id);
642
643     buildRequest(REMOVE_MESSAGE, parameters);
644 }
645
646
647 void SituareService::removeTags(const QStringList &tags)
648 {
649     qDebug() << __PRETTY_FUNCTION__;
650
651     QHash<QString, QString> parameters;
652     parameters.insert("tags", tags.join(","));
653
654     buildRequest(REMOVE_TAGS, parameters);
655 }
656
657 void SituareService::requestFinished(QNetworkReply *reply)
658 {
659     qDebug() << __PRETTY_FUNCTION__;
660
661     //Reply from situare
662     if (m_currentRequests.contains(reply)) {
663         if (reply->error())
664             emit error(ErrorContext::NETWORK, reply->error());
665         else
666             parseReply(reply->readAll(), getRequestName(reply->url()));
667
668         m_currentRequests.removeAll(reply);
669         reply->deleteLater();
670     }
671 }
672
673 void SituareService::reverseGeo(const GeoCoordinate &coordinates)
674 {
675     qDebug() << __PRETTY_FUNCTION__;
676
677     QHash<QString, QString> parameters;
678     parameters.insert("lat", degreesToString(coordinates.latitude()));
679     parameters.insert("lon", degreesToString(coordinates.longitude()));
680     parameters.insert("format", "json");
681
682     buildRequest(REVERSE_GEO, parameters);
683 }
684
685 void SituareService::searchPeopleByTag(const QString &tag)
686 {
687     qDebug() << __PRETTY_FUNCTION__;
688
689     QHash<QString, QString> parameters;
690     parameters.insert("tag",tag);
691
692     buildRequest(SEARCH_PEOPLE_WITH_TAG, parameters);
693 }
694
695 void SituareService::sendMessage(const QString &receiverId, const QString &message,
696                                  const GeoCoordinate &coordinates)
697 {
698     qDebug() << __PRETTY_FUNCTION__;
699
700     QHash<QString, QString> parameters;
701     parameters.insert("rid", receiverId);
702     parameters.insert("message", message);
703
704     if (coordinates.isValid()) {
705         parameters.insert("lat", degreesToString(coordinates.latitude()));
706         parameters.insert("lon", degreesToString(coordinates.longitude()));
707     }
708
709     buildRequest(SEND_MESSAGE, parameters);
710 }
711
712 void SituareService::sendRequest(const QString &requestUrl)
713 {
714     qDebug() << __PRETTY_FUNCTION__ << "requestUrl" << requestUrl;
715
716     // make and send the request
717     QNetworkRequest request;
718     request.setUrl(QUrl(requestUrl));
719     request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
720     QNetworkReply *reply = m_networkManager->get(request, true);
721     m_currentRequests.append(reply);
722 }
723
724 void SituareService::updateSession(const QString &session)
725 {
726     qDebug() << __PRETTY_FUNCTION__;
727
728     m_session = session;
729
730     if (m_session.isEmpty())
731         clearUserData();
732 }
733
734 void SituareService::updateLocation(const GeoCoordinate &coordinates, const QString &status,
735                                     const bool &publish)
736 {
737     qDebug() << __PRETTY_FUNCTION__;
738
739     QHash<QString, QString> parameters;
740     parameters.insert("lat", degreesToString(coordinates.latitude()));
741     parameters.insert("lon", degreesToString(coordinates.longitude()));
742     parameters.insert("publish", publish ? "true" : "false");
743     parameters.insert("data", status); ///< @todo if !empty ???
744
745     buildRequest(UPDATE_LOCATION, parameters);
746 }