Added unit tests.
[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             friends.append(user);
378
379             //Remove comment when the actual server is used
380             //emit fetchImage(user.userId(), user.profileImageUrl());
381         }
382
383         foreach (QVariant personVariant, people.toMap().value("others").toList()) {
384             User user;
385             QMap<QString, QVariant> person = personVariant.toMap();
386             user.setUserId(person["uid"].toString());
387             user.setName(person["name"].toString());
388             user.setProfileImage(AvatarImage::create(
389                     QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
390             user.setProfileImageUrl(person["image_url"].toUrl());
391             user.setTags(person["tags"].toList());
392
393             others.append(user);
394
395             //Remove comment when the actual server is used
396             //emit fetchImage(user.userId(), user.profileImageUrl());
397         }
398
399         emit interestingPeopleReceived(friends, others);
400     }
401 }
402
403 void SituareService::parseMessagesData(const QByteArray &jsonReply)
404 {
405     QJson::Parser parser;
406     bool ok;
407
408     QVariantMap result = parser.parse(jsonReply, &ok).toMap();
409
410     if (!ok) {
411         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
412         return;
413     } else {
414         QVariant messages = result["messages"];
415
416         QList<Message> received;
417         QList<Message> sent;
418
419         foreach (QVariant messageVariant, messages.toMap().value("received").toList()) {
420             Message message(Message::MessageTypeReceived);
421             QMap<QString, QVariant> messageMap = messageVariant.toMap();
422             message.setId(messageMap["id"].toString());
423             message.setSenderId(messageMap["sender_id"].toString());
424             message.setReceiverId(messageMap["receiver_id"].toString());
425             message.setSenderName(messageMap["sender_name"].toString());
426             uint timestampSeconds = messageMap["timestamp"].toUInt();
427             message.setTimestamp(QDateTime::fromTime_t(timestampSeconds));
428             message.setText(messageMap["text"].toString());
429             message.setImage(AvatarImage::create(
430                     QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
431
432             bool latOk;
433             qreal latitude = messageMap["latitude"].toReal(&latOk);
434             bool lonOk;
435             qreal longitude = messageMap["longitude"].toReal(&lonOk);
436
437             if (latOk && lonOk) {
438                 message.setAddress(messageMap["address"].toString());
439                 message.setCoordinates(GeoCoordinate(latitude, longitude));
440             }
441
442             received.append(message);
443
444             //emit fetchImage(message.id(), messageMap["image_url"].toString());
445         }
446
447         foreach (QVariant messageVariant, messages.toMap().value("sent").toList()) {
448             Message message(Message::MessageTypeSent);
449             QMap<QString, QVariant> messageMap = messageVariant.toMap();
450             message.setId(messageMap["id"].toString());
451             message.setSenderId(messageMap["sender_id"].toString());
452             message.setReceiverId(messageMap["receiver_id"].toString());
453             message.setSenderName(messageMap["sender_name"].toString());
454             uint timestampSeconds = messageMap["timestamp"].toUInt();
455             message.setTimestamp(QDateTime::fromTime_t(timestampSeconds));
456             message.setText(messageMap["text"].toString());
457             message.setImage(AvatarImage::create(
458                     QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
459
460             bool latOk;
461             qreal latitude = messageMap["latitude"].toReal(&latOk);
462             bool lonOk;
463             qreal longitude = messageMap["longitude"].toReal(&lonOk);
464
465             if (latOk && lonOk) {
466                 message.setAddress(messageMap["address"].toString());
467                 message.setCoordinates(GeoCoordinate(latitude, longitude));
468             }
469
470             sent.append(message);
471
472             //emit fetchImage(message.id(), messageMap["image_url"].toString());
473         }
474
475         emit messagesReceived(received, sent);
476     }
477 }
478
479 void SituareService::parsePopularTagsData(const QByteArray &jsonReply)
480 {
481     qDebug() << __PRETTY_FUNCTION__;
482
483     QJson::Parser parser;
484     bool ok;
485
486     QVariantMap result = parser.parse(jsonReply, &ok).toMap();
487
488     if (!ok) {
489         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
490         return;
491     } else {
492         QHash<QString, QString> popularTags;
493
494         foreach (QVariant tagVariant, result["popular_tags"].toList()) {
495             QMap<QString, QVariant> tag = tagVariant.toMap();
496             popularTags.insert(tag["id"].toString(), tag["name"].toString());
497         }
498
499         emit popularTagsReceived(popularTags);
500     }
501 }
502
503
504 void SituareService::parseUserData(const QByteArray &jsonReply)
505 {
506     qDebug() << __PRETTY_FUNCTION__;
507
508     m_defaultImage = false;
509
510     QJson::Parser parser;
511     bool ok;
512
513     QVariantMap result = parser.parse (jsonReply, &ok).toMap();
514
515     if (!ok) {
516         emit error(ErrorContext::SITUARE, SituareError::INVALID_JSON);
517         return;
518     } else {
519
520         if(result.contains("ErrorCode")) {
521             QVariant errorVariant = result.value("ErrorCode");
522             emit error(ErrorContext::SITUARE, errorVariant.toInt());
523             return;
524         } else if(result.contains("user")) {
525
526             QVariant userVariant = result.value("user");
527             QMap<QString, QVariant> userMap = userVariant.toMap();
528
529             GeoCoordinate coordinates(userMap["latitude"].toReal(), userMap["longitude"].toReal());
530
531             QUrl imageUrl = userMap[NORMAL_SIZE_PROFILE_IMAGE].toUrl();
532
533             QString address = userMap["address"].toString();
534             if(address.isEmpty()) {
535                 QStringList location;
536                 location.append(QString::number(coordinates.latitude()));
537                 location.append(QString::number(coordinates.longitude()));
538                 address = location.join(", ");
539             }
540
541             User user = User(address, coordinates, userMap["name"].toString(),
542                           userMap["note"].toString(), imageUrl, userMap["timestamp"].toString(),
543                           true, userMap["uid"].toString());
544
545             if(imageUrl.isEmpty()) {
546                 // user doesn't have profile image, so we need to get him a silhouette image
547                 m_defaultImage = true;
548                 user.setProfileImage(AvatarImage::create(
549                         QPixmap(":/res/images/empty_avatar_big.png"), AvatarImage::Large));
550             }
551
552             QList<User> tmpFriendsList;
553
554             foreach (QVariant friendsVariant, result["friends"].toList()) {
555               QMap<QString, QVariant> friendMap = friendsVariant.toMap();
556               QVariant distance = friendMap["distance"];
557               QMap<QString, QVariant> distanceMap = distance.toMap();
558
559               GeoCoordinate coordinates(friendMap["latitude"].toReal(),friendMap["longitude"].toReal());
560
561               QUrl imageUrl = friendMap["profile_pic"].toUrl();
562
563               QString address = friendMap["address"].toString();
564               if(address.isEmpty()) {
565                   QStringList location;
566                   location.append(QString::number(coordinates.latitude()));
567                   location.append(QString::number(coordinates.longitude()));
568                   address = location.join(", ");
569               }
570
571               User buddy = User(address, coordinates, friendMap["name"].toString(),
572                                friendMap["note"].toString(), imageUrl,
573                                friendMap["timestamp"].toString(),
574                                false, friendMap["uid"].toString(), distanceMap["units"].toString(),
575                                distanceMap["value"].toDouble());
576
577               if(imageUrl.isEmpty()) {
578                   // friend doesn't have profile image, so we need to get him a silhouette image
579                   m_defaultImage = true;
580                   buddy.setProfileImage(AvatarImage::create(
581                           QPixmap(":/res/images/empty_avatar.png"), AvatarImage::Small));
582               }
583
584               tmpFriendsList.append(buddy);
585             }
586
587             QHash<QString, QUrl> imageUrlList; // url list for images
588
589             // set unchanged profile images or add new images to imageUrlList for downloading
590             if(m_user) {
591                 if(m_user->profileImageUrl() != user.profileImageUrl()) {
592                     if(!user.profileImageUrl().isEmpty())
593                         imageUrlList.insert(user.userId(), user.profileImageUrl());
594                 } else {
595                     user.setProfileImage(m_user->profileImage());
596                 }
597             } else {
598                 if(!user.profileImageUrl().isEmpty())
599                     imageUrlList.insert(user.userId(), user.profileImageUrl());
600             }
601
602             // clear old user object
603             if(m_user) {
604                 delete m_user;
605                 m_user = 0;
606             }
607
608             // create new user object from temporary user object
609             m_user = new User(user);
610
611             // set unchanged profile images or add new images to imageUrlList for downloading
612             if(!m_friendsList.isEmpty()) {
613                 foreach(User tmpBuddy, tmpFriendsList) {
614                     if(!tmpBuddy.profileImageUrl().isEmpty()) {
615                         bool found = false;
616                         foreach(User *buddy, m_friendsList) {
617                             if(tmpBuddy.profileImageUrl() == buddy->profileImageUrl()) {
618                                 tmpBuddy.setProfileImage(buddy->profileImage());
619                                 found = true;
620                                 break;
621                             }
622                         }
623                         if(!found && !tmpBuddy.profileImageUrl().isEmpty())
624                             imageUrlList.insert(tmpBuddy.userId(), tmpBuddy.profileImageUrl());
625                     }
626                 }
627             } else {
628                 foreach(User buddy, tmpFriendsList) {
629                     if(!buddy.profileImageUrl().isEmpty())
630                         imageUrlList.insert(buddy.userId(), buddy.profileImageUrl());
631                 }
632             }
633
634             // clear old friendlist
635             qDeleteAll(m_friendsList.begin(), m_friendsList.end());
636             m_friendsList.clear();
637
638             // populate new friendlist with temporary friendlist's data
639             foreach(User tmpFriendItem, tmpFriendsList) {
640                 User *friendItem = new User(tmpFriendItem);
641                 m_friendsList.append(friendItem);
642             }
643             tmpFriendsList.clear();
644
645             //REMOVE WHEN NOT NEEDED! get user tags and set tags to the user
646             m_user->setTags(getTags(m_user->userId()));
647
648             emit userDataChanged(m_user, m_friendsList);
649
650             // set silhouette image to imageUrlList for downloading
651             if(m_defaultImage)
652                 imageUrlList.insert("", QUrl(SILHOUETTE_URL));
653
654             addProfileImages(imageUrlList);
655             imageUrlList.clear();
656
657         } else {
658             QVariant address = result.value("address");
659             if(!address.toString().isEmpty()) {
660                 emit reverseGeoReady(address.toString());
661             } else {
662                 QStringList coordinates;
663                 coordinates.append(result.value("lat").toString());
664                 coordinates.append(result.value("lon").toString());
665
666                 emit error(ErrorContext::SITUARE, SituareError::ADDRESS_RETRIEVAL_FAILED);
667                 emit reverseGeoReady(coordinates.join(", "));
668             }
669         }
670     }
671 }
672
673 void SituareService::imageReceived(const QString &id, const QPixmap &image)
674 {
675     qDebug() << __PRETTY_FUNCTION__;
676
677     if (m_user->userId() == id)
678         emit imageReady(id, AvatarImage::create(image, AvatarImage::Large));
679     else
680         emit imageReady(id, AvatarImage::create(image, AvatarImage::Small));
681 }
682
683 void SituareService::addProfileImages(const QHash<QString, QUrl> &imageUrlList)
684 {
685     qDebug() << __PRETTY_FUNCTION__;
686
687     QHashIterator<QString, QUrl> imageUrlListIterator(imageUrlList);
688
689     while (imageUrlListIterator.hasNext()) {
690         imageUrlListIterator.next();
691         emit fetchImage(imageUrlListIterator.key(), imageUrlListIterator.value());
692     }
693 }
694
695 void SituareService::clearUserData()
696 {
697     qDebug() << __PRETTY_FUNCTION__;
698
699     qDeleteAll(m_friendsList.begin(), m_friendsList.end());
700     m_friendsList.clear();
701
702     if(m_user) {
703         delete m_user;
704         m_user = 0;
705     }
706     emit userDataChanged(m_user, m_friendsList);
707 }
708
709 QHash<QString, QString> SituareService::getTags(const QString &userId)
710 {
711     qDebug() << __PRETTY_FUNCTION__;
712
713     return m_database->getTags(userId.toInt());
714 }
715
716 void SituareService::removeTags(const QStringList &tags)
717 {
718     qDebug() << __PRETTY_FUNCTION__;
719
720     if (m_database->removeTags(613374451, tags))
721         emit updateWasSuccessful(SituareService::SuccessfulRemoveTags);
722 }
723
724 void SituareService::removeMessage(const QString &id)
725 {
726     qDebug() << __PRETTY_FUNCTION__;
727
728     if (m_database->removeMessage(613374451, id))
729         emit updateWasSuccessful(SituareService::SuccessfulRemoveMessage);
730 }
731
732 void SituareService::addTags(const QStringList &tags)
733 {
734     qDebug() << __PRETTY_FUNCTION__;
735
736     foreach (QString tag, tags)
737         m_database->addTag(613374451, tag);
738
739     emit updateWasSuccessful(SituareService::SuccessfulAddTags);
740 }
741
742 void SituareService::searchPeopleByTag(const QString &tag)
743 {
744     qDebug() << __PRETTY_FUNCTION__;
745
746     QByteArray arr = m_database->getInterestingPeopleByTag(613374451, tag);
747
748     parseInterestingPeopleData(arr);
749 }