#include "friendgroupitem.h"
#include "friendlocationitem.h"
+#include "mapcommon.h"
#include "mapengine.h"
#include "mapscene.h"
#include "user/user.h"
FriendItemsHandler::FriendItemsHandler(MapScene *mapScene, QObject *parent)
: QObject(parent),
- m_mapScene(mapScene)
+ m_mapScene(mapScene),
+ m_zoomLevel(0)
{
+ qDebug() << __PRETTY_FUNCTION__;
}
-FriendItemsHandler::~FriendItemsHandler()
+void FriendItemsHandler::addFriendItem(User *friendData)
{
- qDeleteAll(m_friendItems.begin(),m_friendItems.end());
- m_friendItems.clear();
+ qDebug() << __PRETTY_FUNCTION__;
+
+ FriendLocationItem *item = new FriendLocationItem(friendData->userId());
+
+ item->setProfileImage(friendData->profileImage(), friendData->profileImageUrl());
+ item->setPos(MapEngine::convertLatLonToSceneCoordinate(friendData->coordinates()));
+ m_friendItems.append(item);
+ m_mapScene->addItem(item);
+
+ connect(item, SIGNAL(locationItemClicked(QList<QString>)),
+ this, SIGNAL(locationItemClicked(QList<QString>)));
}
-void FriendItemsHandler::checkFriendsForCollisions()
+void FriendItemsHandler::checkAllFriendsForCollidingFriends()
{
- qWarning() << __PRETTY_FUNCTION__;
-
-// foreach(FriendGroupItem *item, m_friendGroupItems) {
-// m_friendGroupItems.removeAll(item);
-// m_mapScene->removeItem(item);
-// }
-
- int lastItem = m_friendItems.size() - 1;
- for (int checking = 0; checking <= lastItem; checking++) {
- QRect beginItemRect = m_friendItems.at(checking)->sceneTransformedBoundingRect(m_zoomLevel);
-
- // don't check items which are already part of a group (and thus unvisible)
- if (m_friendItems.at(checking)->isPartOfGroup())
- continue;
-
- // check all other items
- for (int another = 0; another <= lastItem; another++)
- {
- // don't check against itself
- if (checking == another)
- continue;
-
- // don't check against items which are already part of a group (and thus unvisible)
- if (m_friendItems.at(another)->isPartOfGroup())
- continue;
-
- // does items collide
- QRect iterItemRect = m_friendItems.at(another)->sceneTransformedBoundingRect(m_zoomLevel);
- if (beginItemRect.intersects(iterItemRect)) {
- qWarning() << __PRETTY_FUNCTION__ << "collision found" << checking << another;
- FriendGroupItem *group = new FriendGroupItem();
- m_friendGroupItems.append(group);
- group->setPos(m_friendItems.at(checking)->pos());
- group->joinFriend(m_friendItems.at(checking));
- group->joinFriend(m_friendItems.at(another));
- m_mapScene->addItem(group);
- break;
- }
+ qDebug() << __PRETTY_FUNCTION__;
+
+ QLinkedList<FriendLocationItem *>::iterator iter = m_friendItems.begin();
+ while (iter != m_friendItems.end()) {
+ // check only friends which are not part of group already
+ if (!(*iter)->isPartOfGroup()) {
+ checkFriendForCollidingFriends(*iter);
}
+ iter++;
}
}
-void FriendItemsHandler::checkGroupsForCollisions()
+void FriendItemsHandler::checkAllGroupsForCollidingFriends()
{
+ qDebug() << __PRETTY_FUNCTION__;
+ // loop through all groups
+ QLinkedList<FriendGroupItem *>::iterator iter = m_friendGroupItems.begin();
+ while (iter != m_friendGroupItems.end()) {
+ checkGroupForCollidingFriends(*iter);
+ iter++;
+ }
}
-void FriendItemsHandler::cleanOldFriendData(const QList<User *> &friendsList)
+void FriendItemsHandler::checkFriendForCollidingFriends(FriendLocationItem *item)
{
- bool friendGone = true;
-
- for (int i=0; i<m_friendItems.count(); i++) {
+ // checkGroupsForCollisions() is used for checking if groups collide with another
+ // groups or friend items, so this method doesn't have to check against groups
- for (int j=0; j<friendsList.count(); j++) {
+ qDebug() << __PRETTY_FUNCTION__;
- if (m_friendItems.at(i)->userId() == friendsList.at(j)->userId())
- friendGone = false;
+ FriendGroupItem *group = 0;
+
+ // loop through all friend items
+ QLinkedList<FriendLocationItem *>::iterator iter = m_friendItems.begin();
+ while (iter != m_friendItems.end()) {
+ // but don't check myself and friends which are already part of a group
+ if (item != *iter && !(*iter)->isPartOfGroup()) {
+ if (collides(item, *iter)) {
+ if (!group) {
+ group = new FriendGroupItem(item);
+ m_mapScene->addItem(group);
+ m_friendGroupItems.append(group);
+
+ connect(group, SIGNAL(locationItemClicked(QList<QString>)),
+ this, SIGNAL(locationItemClicked(QList<QString>)));
+ }
+ group->joinFriend(*iter);
+ }
}
+ iter++;
+ }
+}
- if (friendGone) {
- m_mapScene->removeItem(m_friendItems.at(i));
- m_friendItems.removeAt(i);
- }
+void FriendItemsHandler::checkGroupForCollidingFriends(FriendGroupItem *group)
+{
+ qDebug() << __PRETTY_FUNCTION__;
- friendGone = true;
+ // loop through all friend items
+ QLinkedList<FriendLocationItem *>::iterator iter = m_friendItems.begin();
+ while (iter != m_friendItems.end()) {
+ // but don't check friends which are already part of a group
+ if (!(*iter)->isPartOfGroup()) {
+ if (collides(group, *iter)) {
+ group->joinFriend(*iter);
+ }
+ }
+ iter++;
}
}
-void FriendItemsHandler::dropOutOfGroupFriends()
+void FriendItemsHandler::checkGroupForCollidingGroups(FriendGroupItem *group)
{
- // loop through all group items and drop friends which doesn't collide anymore
- foreach (FriendGroupItem *group, m_friendGroupItems)
- group->dropFriends(m_zoomLevel);
+ qDebug() << __PRETTY_FUNCTION__;
+
+ // loop through all groups
+ QLinkedList<FriendGroupItem *>::iterator iter = m_friendGroupItems.begin();
+ while (iter != m_friendGroupItems.end()) {
+ // but don't check myself
+ if (group != *iter) {
+ if (collides(group, *iter)) {
+ (*iter)->mergeWithGroup(group);
+ m_mapScene->removeItem(*iter);
+ delete *iter;
+ iter = m_friendGroupItems.erase(iter);
+ }
+ else {
+ iter++;
+ }
+ }
+ else {
+ iter++;
+ }
+ }
}
-void FriendItemsHandler::receiveFriendLocations(QList<User *> &friendsList)
+bool FriendItemsHandler::collides(BaseLocationItem *item1, BaseLocationItem *item2)
{
- qWarning() << __PRETTY_FUNCTION__;
+ QRect rect = item1->sceneTransformedBoundingRect(m_zoomLevel);
- static int receiveFriendsLocationsCounter = 0;
+ if (rect.intersects(item2->sceneTransformedBoundingRect(m_zoomLevel)))
+ return true;
- if (receiveFriendsLocationsCounter == 0) {
- receiveFriendsLocationsCounter++;
- updateFriendItemList(friendsList);
+ if (rect.left() < MAP_MIN_PIXEL_X) {
+ QRect translated = rect.translated(MAP_PIXELS_X, 0);
+ if (translated.intersects(item2->sceneTransformedBoundingRect(m_zoomLevel)))
+ return true;
}
- else {
- /// @todo VILLE: New friends are never added to list & scene
- receiveFriendsLocationsCounter++;
- updateFriendLocationsAndImages(friendsList);
- cleanOldFriendData(friendsList);
+ if (rect.right() > MAP_MAX_PIXEL_X) {
+ QRect translated = rect.translated(-MAP_PIXELS_X, 0);
+ if (translated.intersects(item2->sceneTransformedBoundingRect(m_zoomLevel)))
+ return true;
}
+
+ return false;
}
-void FriendItemsHandler::refactorFriendItems(int zoomLevel)
+void FriendItemsHandler::deleteFriendItem(FriendLocationItem *item)
{
- m_zoomLevel = zoomLevel;
+ qDebug() << __PRETTY_FUNCTION__;
- dropOutOfGroupFriends();
- checkGroupsForCollisions();
- checkFriendsForCollisions();
+ dropFriendFromAllGroups(item);
+ m_mapScene->removeItem(item);
+ delete item;
}
-void FriendItemsHandler::updateFriendItemList(const QList<User *> &friendsList)
+void FriendItemsHandler::dropFriendFromAllGroups(FriendLocationItem *item)
{
qDebug() << __PRETTY_FUNCTION__;
- qDeleteAll(m_friendItems.begin(),m_friendItems.end());
- m_friendItems.clear();
+ foreach (FriendGroupItem *group, m_friendGroupItems) {
+ group->dropFriend(item);
+ }
+}
+void FriendItemsHandler::dropOutOfGroupFriends()
+{
+ qDebug() << __PRETTY_FUNCTION__;
- for (int i=0; i<friendsList.count(); i++) {
- FriendLocationItem *friendLocation
- = new FriendLocationItem(friendsList.at(i)->profileImage(),
- friendsList.at(i)->coordinates(),0);
+ // loop through all group items and drop friends which doesn't collide anymore
+ // delete group if possible
+ foreach (FriendGroupItem *group, m_friendGroupItems) {
+ if (group->dropFriends(m_zoomLevel)) {
+ m_friendGroupItems.removeAll(group);
+ m_mapScene->removeItem(group);
+ delete group;
+ }
+ }
+}
- friendLocation->setUserId(friendsList.at(i)->userId());
- m_friendItems.append(friendLocation);
- m_mapScene->addItem(friendLocation);
+void FriendItemsHandler::friendListUpdated(QList<User *> &friendsList)
+{
+ qDebug() << __PRETTY_FUNCTION__;
- //refactorFriendItems(m_zoomLevel);
+ // loop through friend items and find matching friend data. If matching data
+ // is not found then remove item
+ QLinkedList<FriendLocationItem *>::iterator iter = m_friendItems.begin();
+ while (iter != m_friendItems.end()) {
+ bool found = false;
+ foreach (User * friendData, friendsList) {
+ if (friendData->userId() == (*iter)->userId()) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // data for friend item was not found so item must be deleted
+ deleteFriendItem(*iter);
+ iter = m_friendItems.erase(iter);
+ }
+ else {
+ iter++;
+ }
}
+
+ // loop through new friend data, find matching friend items and update them, or add new items
+ // if old items are not found
+ foreach (User * friendData, friendsList) {
+ bool found = false;
+ foreach (FriendLocationItem *friendItem, m_friendItems) {
+ if (friendData->userId() == friendItem->userId()) {
+ // friend item was found so update the data
+ updateFriendItem(friendItem, friendData);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // friend item was not found so new item must be added
+ addFriendItem(friendData);
+ }
+ }
+
+ refactorFriendItems(m_zoomLevel);
}
-void FriendItemsHandler::updateFriendLocationsAndImages(const QList<User *> &friendsList)
+void FriendItemsHandler::mergeCollidingGroups()
{
- for (int i=0; i<friendsList.count(); i++) {
+ qDebug() << __PRETTY_FUNCTION__;
- for (int j=0; j<m_friendItems.count(); j++) {
+ // loop through all groups
+ QLinkedList<FriendGroupItem *>::iterator iter = m_friendGroupItems.begin();
+ while (iter != m_friendGroupItems.end()) {
+ checkGroupForCollidingGroups(*iter);
+ iter++;
+ }
+}
- if (m_friendItems.at(j)->userId() == friendsList.at(i)->userId()) {
+void FriendItemsHandler::refactorFriendItems(int zoomLevel)
+{
+ qDebug() << __PRETTY_FUNCTION__;
- if (m_friendItems.at(j)->position()
- != MapEngine::convertLatLonToSceneCoordinate(friendsList.at(i)->coordinates()))
- m_friendItems.at(j)->setPosition(friendsList.at(i)->coordinates());
+ m_zoomLevel = zoomLevel;
- if (m_friendItems.at(j)->profileImageUrl()
- != friendsList.at(i)->profileImageUrl()) {
- m_friendItems.at(j)->setPixmap(friendsList.at(i)->profileImage());
- }
- }
- }
- }
+ mergeCollidingGroups();
+ dropOutOfGroupFriends();
+ checkAllGroupsForCollidingFriends();
+ checkAllFriendsForCollidingFriends();
}
+void FriendItemsHandler::updateFriendItem(FriendLocationItem *friendItem, User *friendData)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+ // update position
+ QPoint newPosition = MapEngine::convertLatLonToSceneCoordinate(friendData->coordinates());
+ if (friendItem->pos().toPoint() != newPosition)
+ friendItem->setPos(newPosition);
+
+ // update image
+ if (friendItem->profileImageUrl() != friendData->profileImageUrl())
+ friendItem->setProfileImage(friendData->profileImage(), friendData->profileImageUrl());
+}