ListView, ListItem, FriendListItem, ListItemDelegate and
[situare] / src / ui / friendlistitem.cpp
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5        Jussi Laitinen - jussi.laitinen@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 <QVBoxLayout>
23 #include <QPushButton>
24 #include <QPainter>
25 #include <QDebug>
26 #include <QPaintEvent>
27 #include <QLabel>
28 #include <QPixmap>
29 #include <QFormLayout>
30 #include <QSpacerItem>
31 #include <QStylePainter>
32 #include <math.h>
33
34 #include "friendlistitem.h"
35 #include "../user/user.h"
36 #include "imagebutton.h"
37 #include "../common.h"
38 #include "listcommon.h"
39
40 const int WALK_DISTANCE = 5;        ///< Walk distance limit for distance icon
41 const int CAR_DISTANCE = 500;       ///< Car distance limit for distance icon
42 const int AEROPLANE_DISTANCE = 5000;///< Aeroplane distance limit for distance icon
43
44 const int RECTS_MINIMUM_FACTOR_SUM = 3; ///< Rects minimum factor sum
45
46 FriendListItem::FriendListItem()
47     : m_selected(false)
48     , m_user(0)
49 {
50     qDebug() << __PRETTY_FUNCTION__;
51
52     setData(ITEM_SIZE_HINT_INDEX, QSize(ITEM_WIDTH, ITEM_MIN_HEIGHT));
53 }
54
55 void FriendListItem::calculateTextRects()
56 {
57     qDebug() << __PRETTY_FUNCTION__;
58
59     //Dummy value to get painter font metrics.
60     QPixmap p = QPixmap(ICON_WIDTH, ICON_HEIGHT);
61     QPainter painter(&p);
62     painter.setFont(NOKIA_FONT_SMALL);
63     QFontMetrics smallFontMetrics = painter.fontMetrics();
64
65     QRect distanceRect = smallFontMetrics.boundingRect(m_distanceText);
66     QRect statusTextRect = smallFontMetrics.boundingRect(m_user->note());
67     QRect updatedRect = smallFontMetrics.boundingRect(m_user->timestamp());
68     QRect locationRect = smallFontMetrics.boundingRect(m_user->address());
69
70     int statusTextRectFactor = statusTextRect.width() / LABEL_MAX_WIDTH;
71     statusTextRectFactor++;
72     m_statusTextRect = QRect(0, 0, LABEL_MAX_WIDTH, ICON_HEIGHT * statusTextRectFactor);
73     int updatedRectFactor = updatedRect.width() / LABEL_MAX_WIDTH;
74     updatedRectFactor++;
75     m_updatedRect = QRect(0, 0, LABEL_MAX_WIDTH, ICON_HEIGHT * updatedRectFactor);
76     int locationRectFactor = locationRect.width() / LABEL_MAX_WIDTH;
77     locationRectFactor++;
78     m_locationRect = QRect(0, 0, LABEL_MAX_WIDTH, ICON_HEIGHT * locationRectFactor);
79
80     m_expandedHeight = ITEM_MIN_HEIGHT + ((statusTextRectFactor + updatedRectFactor +
81                                            locationRectFactor - RECTS_MINIMUM_FACTOR_SUM)
82                                           * ICON_HEIGHT);
83
84     setData(DISTANCE_SIZE_HINT_INDEX, distanceRect);
85 }
86
87 QPointF FriendListItem::coordinates()
88 {
89     qDebug() << __PRETTY_FUNCTION__;
90
91     return m_user->coordinates();
92 }
93
94 QString FriendListItem::id() const
95 {
96     qDebug() << __PRETTY_FUNCTION__;
97
98     return m_user->userId();
99 }
100
101 void FriendListItem::setUserData(User *user)
102 {
103     qDebug() << __PRETTY_FUNCTION__;
104
105     if(user) {
106         m_user = user;
107         setData(AVATAR_IMAGE_INDEX, m_user->profileImage());
108
109         QString unit;
110         double value;
111         m_user->distance(value, unit);
112         m_distanceText = QString::number(value) + " " + unit;
113         setData(DISTANCE_TEXT_DISPLAY_INDEX, m_distanceText);
114         setDistanceIcon(value, unit);
115
116         shortenTexts();
117         calculateTextRects();
118         setText(false);
119     }
120 }
121
122 void FriendListItem::setAvatarImage(const QPixmap &image)
123 {
124     qDebug() << __PRETTY_FUNCTION__;
125
126     if(!image.isNull())
127         setData(AVATAR_IMAGE_INDEX, m_user->profileImage());
128 }
129
130 void FriendListItem::setDistanceIcon(double value, const QString &unit)
131 {
132     qDebug() << __PRETTY_FUNCTION__;
133
134     QPixmap distanceImage;
135
136     if ((unit == "m") || (value < WALK_DISTANCE))
137         distanceImage.load(":/res/images/walk_icon_gray.png");
138     else if (value < CAR_DISTANCE)
139         distanceImage.load(":/res/images/car_icon_gray.png");
140     else if (value < AEROPLANE_DISTANCE)
141         distanceImage.load(":/res/images/aeroplane_icon_gray.png");
142     else
143         distanceImage.load(":/res/images/rocket_icon_gray.png");
144
145     setData(DISTANCE_IMAGE_INDEX, distanceImage);
146 }
147
148 void FriendListItem::shortenTexts()
149 {
150     qDebug() << __PRETTY_FUNCTION__;
151
152     //Dummy value to get painter font metrics.
153     QPixmap p = QPixmap(ICON_WIDTH, ICON_HEIGHT);
154     QPainter painter(&p);
155     painter.setFont(NOKIA_FONT_NORMAL);
156     QFontMetrics nameLabelMetrics = painter.fontMetrics();
157     painter.setFont(NOKIA_FONT_SMALL);
158     QFontMetrics otherLabelsMetrics = painter.fontMetrics();
159
160     QString name = m_user->name();
161     QString updated = m_user->timestamp();
162     QString statusText = m_user->note();
163     QString location = m_user->address();
164
165     int nameIndex = name.indexOf('\n');
166     int updatedIndex = updated.indexOf('\n');
167     int statusTextIndex = statusText.indexOf('\n');
168     int locationIndex = location.indexOf('\n');
169
170     if (nameIndex > 0) {
171         name.truncate(nameIndex);
172         name.append("...");
173     }
174     if (updatedIndex > 0) {
175         updated.truncate(updatedIndex);
176         updated.append("...");
177     }
178     if (statusTextIndex > 0) {
179         statusText.truncate(statusTextIndex);
180         statusText.append("...");
181     }
182     if (locationIndex > 0) {
183         location.truncate(locationIndex);
184         location.append("...");
185     }
186
187     int distanceLabelWidth = otherLabelsMetrics.width(m_distanceText) + MARGIN;
188     m_shortenedName = nameLabelMetrics.elidedText(name, Qt::ElideRight, NAME_LABEL_MAX_WIDTH
189                                                   - distanceLabelWidth);
190     m_shortenedStatusText = otherLabelsMetrics.elidedText(statusText, Qt::ElideRight,
191                                                           LABEL_MAX_WIDTH);
192     m_shortenedUpdated = otherLabelsMetrics.elidedText(updated, Qt::ElideRight, LABEL_MAX_WIDTH);
193     m_shortenedLocation = otherLabelsMetrics.elidedText(location, Qt::ElideRight, LABEL_MAX_WIDTH);
194
195     setData(NAME_DISPLAY_INDEX, m_shortenedName);
196 }
197
198 void FriendListItem::setText(bool expanded)
199 {
200     qDebug() << __PRETTY_FUNCTION__;
201
202     if (expanded) {
203         setData(STATUS_TEXT_DISPLAY_INDEX, m_user->note());
204         setData(LOCATION_DISPLAY_INDEX, m_user->address());
205         setData(UPDATED_DISPLAY_INDEX, m_user->timestamp());
206
207         setData(STATUS_TEXT_SIZE_HINT_INDEX, m_statusTextRect);
208         setData(LOCATION_SIZE_HINT_INDEX, m_locationRect);
209         setData(UPDATED_SIZE_HINT_INDEX, m_updatedRect);
210     } else {
211         setData(STATUS_TEXT_DISPLAY_INDEX, m_shortenedStatusText);
212         setData(LOCATION_DISPLAY_INDEX, m_shortenedLocation);
213         setData(UPDATED_DISPLAY_INDEX, m_shortenedUpdated);
214
215         setData(STATUS_TEXT_SIZE_HINT_INDEX, QRect(0, 0, LABEL_MAX_WIDTH, ICON_HEIGHT));
216         setData(LOCATION_SIZE_HINT_INDEX, QRect(0, 0, LABEL_MAX_WIDTH, ICON_HEIGHT));
217         setData(UPDATED_SIZE_HINT_INDEX, QRect(0, 0, LABEL_MAX_WIDTH, ICON_HEIGHT));
218     }
219 }
220
221 bool FriendListItem::toggleSelection()
222 {
223     qDebug() << __PRETTY_FUNCTION__;
224
225     setSelected(!m_selected);
226     return m_selected;
227 }
228
229 void FriendListItem::setSelected(bool selected)
230 {
231     qDebug() << __PRETTY_FUNCTION__;
232
233     m_selected = selected;
234
235     if (m_selected) {
236         setText(true);
237         setData(ITEM_SIZE_HINT_INDEX, QSize(ITEM_WIDTH, m_expandedHeight));
238     } else {
239         setText(false);
240         setData(ITEM_SIZE_HINT_INDEX, QSize(ITEM_WIDTH, ITEM_MIN_HEIGHT));
241     }
242 }