2 Situare - A location system for Facebook
3 Copyright (C) 2010 Ixonos Plc. Authors:
5 Sami Rämö - sami.ramo@ixonos.com
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.
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.
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,
25 #include "friendgroupitem.h"
26 #include "friendlocationitem.h"
27 #include "mapengine.h"
29 #include "user/user.h"
31 #include "frienditemshandler.h"
33 FriendItemsHandler::FriendItemsHandler(MapScene *mapScene, QObject *parent)
38 qDebug() << __PRETTY_FUNCTION__;
41 void FriendItemsHandler::addFriendItem(User *friendData)
43 qDebug() << __PRETTY_FUNCTION__;
45 FriendLocationItem *item = new FriendLocationItem(friendData->userId());
47 item->setProfileImage(friendData->profileImage(), friendData->profileImageUrl());
48 item->setPos(MapEngine::convertLatLonToSceneCoordinate(friendData->coordinates()));
49 m_friendItems.append(item);
50 m_mapScene->addItem(item);
52 connect(item, SIGNAL(friendItemClicked(QString)),
53 this, SIGNAL(friendItemClicked(QString)));
56 void FriendItemsHandler::checkAllFriendsForCollidingFriends()
58 qDebug() << __PRETTY_FUNCTION__;
60 QLinkedList<FriendLocationItem *>::iterator iter = m_friendItems.begin();
61 while (iter != m_friendItems.end()) {
62 // check only friends which are not part of group already
63 if (!(*iter)->isPartOfGroup()) {
64 checkFriendForCollidingFriends(*iter);
70 void FriendItemsHandler::checkAllGroupsForCollidingFriends()
72 qDebug() << __PRETTY_FUNCTION__;
74 // loop through all groups
75 QLinkedList<FriendGroupItem *>::iterator iter = m_friendGroupItems.begin();
76 while (iter != m_friendGroupItems.end()) {
77 checkGroupForCollidingFriends(*iter);
82 void FriendItemsHandler::checkFriendForCollidingFriends(FriendLocationItem *item)
84 // checkGroupsForCollisions() is used for checking if groups collide with another
85 // groups or friend items, so this method doesn't have to check against groups
87 qDebug() << __PRETTY_FUNCTION__;
89 FriendGroupItem *group = 0;
90 QRect itemSceneRect = item->sceneTransformedBoundingRect(m_zoomLevel);
92 // loop through all friend items
93 QLinkedList<FriendLocationItem *>::iterator iter = m_friendItems.begin();
94 while (iter != m_friendItems.end()) {
95 // but don't check myself and friends which are already part of a group
96 if (item != *iter && !(*iter)->isPartOfGroup()) {
97 if (itemSceneRect.intersects((*iter)->sceneTransformedBoundingRect(m_zoomLevel))) {
99 group = new FriendGroupItem(item);
100 m_mapScene->addItem(group);
101 m_friendGroupItems.append(group);
103 connect(group, SIGNAL(friendGroupItemClicked(QList<QString>)),
104 this, SIGNAL(friendGroupItemClicked(QList<QString>)));
106 group->joinFriend(*iter);
113 void FriendItemsHandler::checkGroupForCollidingFriends(FriendGroupItem *group)
115 qDebug() << __PRETTY_FUNCTION__;
117 QRect groupSceneRect = group->sceneTransformedBoundingRect(m_zoomLevel);
119 // loop through all friend items
120 QLinkedList<FriendLocationItem *>::iterator iter = m_friendItems.begin();
121 while (iter != m_friendItems.end()) {
122 // but don't check friends which are already part of a group
123 if (!(*iter)->isPartOfGroup()) {
124 if (groupSceneRect.intersects((*iter)->sceneTransformedBoundingRect(m_zoomLevel))) {
125 group->joinFriend(*iter);
132 void FriendItemsHandler::checkGroupForCollidingGroups(FriendGroupItem *group)
134 qDebug() << __PRETTY_FUNCTION__;
136 QRect groupSceneRect = group->sceneTransformedBoundingRect(m_zoomLevel);
138 // loop through all groups
139 QLinkedList<FriendGroupItem *>::iterator iter = m_friendGroupItems.begin();
140 while (iter != m_friendGroupItems.end()) {
141 // but don't check myself
142 if (group != *iter) {
143 if (groupSceneRect.intersects((*iter)->sceneTransformedBoundingRect(m_zoomLevel))) {
144 (*iter)->mergeWithGroup(group);
145 m_mapScene->removeItem(*iter);
147 iter = m_friendGroupItems.erase(iter);
159 void FriendItemsHandler::mergeCollidingGroups()
161 qDebug() << __PRETTY_FUNCTION__;
163 // loop through all groups
164 QLinkedList<FriendGroupItem *>::iterator iter = m_friendGroupItems.begin();
165 while (iter != m_friendGroupItems.end()) {
166 checkGroupForCollidingGroups(*iter);
171 void FriendItemsHandler::deleteFriendItem(FriendLocationItem *item)
173 qDebug() << __PRETTY_FUNCTION__;
175 disconnect(item, SIGNAL(friendItemClicked(QString)),
176 this, SIGNAL(friendItemClicked(QString)));
178 dropFriendFromAllGroups(item);
179 m_mapScene->removeItem(item);
183 void FriendItemsHandler::dropFriendFromAllGroups(FriendLocationItem *item)
185 qDebug() << __PRETTY_FUNCTION__;
187 foreach (FriendGroupItem *group, m_friendGroupItems) {
188 group->dropFriend(item);
192 void FriendItemsHandler::dropOutOfGroupFriends()
194 qDebug() << __PRETTY_FUNCTION__;
196 // loop through all group items and drop friends which doesn't collide anymore
197 // delete group if possible
198 foreach (FriendGroupItem *group, m_friendGroupItems) {
199 if (group->dropFriends(m_zoomLevel)) {
200 m_friendGroupItems.removeAll(group);
201 m_mapScene->removeItem(group);
207 void FriendItemsHandler::friendListUpdated(QList<User *> &friendsList)
209 qDebug() << __PRETTY_FUNCTION__;
211 // loop through friend items and find matching friend data. If matching data
212 // is not found then remove item
213 QLinkedList<FriendLocationItem *>::iterator iter = m_friendItems.begin();
214 while (iter != m_friendItems.end()) {
216 foreach (User * friendData, friendsList) {
217 if (friendData->userId() == (*iter)->userId()) {
223 // data for friend item was not found so item must be deleted
224 deleteFriendItem(*iter);
225 iter = m_friendItems.erase(iter);
232 // loop through new friend data, find matching friend items and update them, or add new items
233 // if old items are not found
234 foreach (User * friendData, friendsList) {
236 foreach (FriendLocationItem *friendItem, m_friendItems) {
237 if (friendData->userId() == friendItem->userId()) {
238 // friend item was found so update the data
239 updateFriendItem(friendItem, friendData);
245 // friend item was not found so new item must be added
246 addFriendItem(friendData);
250 refactorFriendItems(m_zoomLevel);
253 void FriendItemsHandler::refactorFriendItems(int zoomLevel)
255 qDebug() << __PRETTY_FUNCTION__;
257 m_zoomLevel = zoomLevel;
259 mergeCollidingGroups();
260 dropOutOfGroupFriends();
261 checkAllGroupsForCollidingFriends();
262 checkAllFriendsForCollidingFriends();
265 void FriendItemsHandler::updateFriendItem(FriendLocationItem *friendItem, User *friendData)
267 qDebug() << __PRETTY_FUNCTION__;
270 QPoint newPosition = MapEngine::convertLatLonToSceneCoordinate(friendData->coordinates());
271 if (friendItem->pos().toPoint() != newPosition)
272 friendItem->setPos(newPosition);
275 if (friendItem->profileImageUrl() != friendData->profileImageUrl())
276 friendItem->setProfileImage(friendData->profileImage(), friendData->profileImageUrl());