Added new class AvatarImage.
[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 "avatarimage.h"
37
38 const QString BACKGROUND_PATH = ":/res/images/list_item.png";   ///< Background image path
39 const QString CLOCK_PATH = ":/res/images/clock.png";        ///< Clock image path
40 const QString COMPASS_PATH = ":/res/images/compass.png";    ///< Compass image path
41 const QString ENVELOPE_PATH = ":/res/images/envelope.png";  ///< Envelope image path
42
43 const int MARGIN = 5;   ///< Icon margin
44 const int IMAGE_HEIGHT = 60; ///< Friend image height
45 const int IMAGE_WIDTH = 60;  ///< Friend image width
46
47 const int ITEM_MAX_HEIGHT = 240; ///< Maximum height for item
48 const int ITEM_MAX_WIDTH = 368;  ///< Maximum width for item
49 const int ITEM_MIN_HEIGHT = 141; ///< Minimum height for item
50 const int ITEM_MIN_WIDTH = 368;  ///< Minimum width for item
51 const int LABEL_MAX_WIDTH = 247;   ///< Label maximum width
52
53 const int MOUSE_PRESS_AREA_WIDTH = 20;  ///< Area width for item height toggling
54 const int MOUSE_PRESS_AREA_HEIGHT = 20; ///< Area height for item height toggling
55
56 const QFont NOKIA_FONT_NORMAL = QFont("Nokia Sans", 18, QFont::Normal);    ///< Normal font
57 const QFont NOKIA_FONT_SMALL = QFont("Nokia Sans", 13, QFont::Normal);     ///< Small font
58
59 const QColor COLOR_GRAY = QColor(152, 152, 152);
60
61 FriendListItem::FriendListItem(QWidget *parent)
62     : QWidget(parent)
63     , m_expanded(false)
64     , m_user(0)
65 {
66     qDebug() << __PRETTY_FUNCTION__;
67
68     QVBoxLayout *layout = new QVBoxLayout(this);
69     layout->setContentsMargins(MARGIN, 0, MARGIN*2, MARGIN*2);
70     layout->setSpacing(0);
71     this->setLayout(layout);
72
73     QHBoxLayout *topLayout = new QHBoxLayout();
74     topLayout->setMargin(0);
75     topLayout->setSpacing(0);
76
77     QHBoxLayout *bottomLayout = new QHBoxLayout();
78     bottomLayout->setMargin(0);
79     bottomLayout->setSpacing(0);
80
81     QFormLayout *infoLayout = new QFormLayout();
82     infoLayout->setMargin(0);
83     infoLayout->setSpacing(0);
84
85     QLabel *clockLabel = new QLabel();
86     clockLabel->setPixmap(QPixmap(CLOCK_PATH));
87     clockLabel->setContentsMargins(0, 0, MARGIN, 0);
88     QLabel *envelopeLabel = new QLabel();
89     envelopeLabel->setPixmap(QPixmap(ENVELOPE_PATH));
90     envelopeLabel->setContentsMargins(0, 0, MARGIN, 0);
91     QLabel *compassLabel = new QLabel();
92     compassLabel->setPixmap(QPixmap(COMPASS_PATH));
93     compassLabel->setContentsMargins(0, 0, MARGIN, 0);
94
95     m_imageLabel = new QLabel();
96     m_imageLabel->setFixedSize(IMAGE_WIDTH, IMAGE_HEIGHT);
97
98     m_nameLabel = new QLabel();
99     m_nameLabel->setFixedHeight(IMAGE_HEIGHT);
100
101     m_distanceLabel = new QLabel();
102     m_distanceLabel->setFixedHeight(IMAGE_HEIGHT);
103     //m_distanceLabel->setAlignment(Qt::AlignHCenter | Qt::AlignRight);
104 //    m_distanceLabel->setMinimumWidth(IMAGE_WIDTH + 15);
105 //    m_distanceLabel->setMaximumWidth(IMAGE_WIDTH + 15);
106
107     QLabel *button = new QLabel();
108     button->setPixmap(QPixmap("res/images/show_position.png"));
109     button->setFixedSize(IMAGE_WIDTH, IMAGE_HEIGHT);
110
111     m_updatedLabel = new QLabel();
112     m_updatedLabel->setWordWrap(true);
113     m_statusTextLabel = new QLabel();
114     m_statusTextLabel->setWordWrap(true);
115     m_locationLabel = new QLabel();
116     m_locationLabel->setWordWrap(true);
117
118     infoLayout->addRow(envelopeLabel, m_statusTextLabel);
119     infoLayout->addRow(compassLabel, m_locationLabel);
120     infoLayout->addRow(clockLabel, m_updatedLabel);
121
122     topLayout->addWidget(m_imageLabel);
123     topLayout->addWidget(m_nameLabel, 1);
124     topLayout->addWidget(m_distanceLabel);
125
126     bottomLayout->addWidget(button, 0, Qt::AlignTop);
127     bottomLayout->addLayout(infoLayout);
128
129     layout->addLayout(topLayout, 0);
130     layout->addLayout(bottomLayout, 1);
131
132     setMinimumSize(ITEM_MIN_WIDTH, ITEM_MIN_HEIGHT);
133     setMaximumSize(ITEM_MIN_WIDTH, ITEM_MAX_HEIGHT);
134
135     setFont(NOKIA_FONT_SMALL);
136     m_nameLabel->setFont(NOKIA_FONT_NORMAL);
137     QPalette itemPalette = palette();
138     itemPalette.setColor(QPalette::Foreground, COLOR_GRAY);
139     setPalette(itemPalette);
140     QPalette namePalette = m_nameLabel->palette();
141     namePalette.setColor(QPalette::Foreground, Qt::white);
142     m_nameLabel->setPalette(namePalette);
143
144     m_backgroundTopImage.load(":/res/images/list_item_top.png");
145     m_backgroundMiddleImage.load(":/res/images/list_item_middle.png");
146     m_backgroundBottomImage.load(":/res/images/list_item_bottom.png");
147 }
148
149 void FriendListItem::setData(User *user)
150 {
151     qDebug() << __PRETTY_FUNCTION__;
152
153     if (user) {
154         m_user = user;
155         shortenTexts();
156         m_imageLabel->setPixmap(AvatarImage::make(m_user->profileImage()));
157         QString unit;
158         double value;
159         user->distance(value, unit);
160         m_distanceLabel->setText(QString::number(value) + " " + unit);
161         setText(false);
162     }
163 }
164
165 void FriendListItem::shortenTexts()
166 {
167     qDebug() << __PRETTY_FUNCTION__;
168
169     QFontMetrics nameLabelMetrics = m_nameLabel->fontMetrics();
170     QFontMetrics otherLabelsMetrics = m_updatedLabel->fontMetrics();
171
172     QString name = m_user->name();
173     QString updated = m_user->timestamp();
174     QString statusText = m_user->note();
175     QString location = m_user->address();
176
177     int nameIndex = name.indexOf('\n');
178     int updatedIndex = updated.indexOf('\n');
179     int statusTextIndex = statusText.indexOf('\n');
180     int locationIndex = location.indexOf('\n');
181
182     if (nameIndex > 0) {
183         name.truncate(nameIndex);
184         name.append("...");
185     }
186     if (updatedIndex > 0) {
187         updated.truncate(updatedIndex);
188         updated.append("...");
189     }
190     if (statusTextIndex > 0) {
191         statusText.truncate(statusTextIndex);
192         statusText.append("...");
193     }
194     if (locationIndex > 0) {
195         location.truncate(locationIndex);
196         location.append("...");
197     }
198
199
200     m_shortenedName = nameLabelMetrics.elidedText(name, Qt::ElideRight, LABEL_MAX_WIDTH + 30);
201     m_shortenedUpdated = otherLabelsMetrics.elidedText(updated, Qt::ElideRight, LABEL_MAX_WIDTH);
202     m_shortenedStatusText = otherLabelsMetrics.elidedText(statusText, Qt::ElideRight,
203                                                           LABEL_MAX_WIDTH);
204     m_shortenedLocation = otherLabelsMetrics.elidedText(location, Qt::ElideRight, LABEL_MAX_WIDTH);
205 }
206
207 void FriendListItem::setText(bool expanded)
208 {
209     qDebug() << __PRETTY_FUNCTION__;
210
211     if (expanded) {
212         setUpdatesEnabled(false);
213         m_nameLabel->setText(m_shortenedName);
214         m_updatedLabel->setText(m_user->timestamp());
215         m_statusTextLabel->setText(m_user->note());
216         m_locationLabel->setText(m_user->address());
217         setUpdatesEnabled(true);
218     }
219     else {
220         setUpdatesEnabled(false);
221         m_nameLabel->setText(m_shortenedName);
222         m_updatedLabel->setText(m_shortenedUpdated);
223         m_statusTextLabel->setText(m_shortenedStatusText);
224         m_locationLabel->setText(m_shortenedLocation);
225         setUpdatesEnabled(true);
226     }
227 }
228
229 void FriendListItem::mousePressEvent(QMouseEvent *event)
230 {
231     qDebug() << __PRETTY_FUNCTION__ << " " << event->pos();
232
233     m_mousePosition = event->pos();
234 }
235
236 void FriendListItem::mouseReleaseEvent(QMouseEvent *event)
237 {
238     qDebug() << __PRETTY_FUNCTION__ << " " << event->pos();
239
240     if ((abs(m_mousePosition.y() - event->pos().y()) <= MOUSE_PRESS_AREA_WIDTH) &&
241         (abs(m_mousePosition.x() - event->pos().x()) <= MOUSE_PRESS_AREA_HEIGHT)) {
242         if (m_expanded) {
243             setText(false);
244             m_expanded = false;
245         }
246         else {
247             setText(true);
248             m_expanded = true;
249         }
250     }
251 }
252
253 void FriendListItem::paintEvent(QPaintEvent *event)
254 {
255     qDebug() << __PRETTY_FUNCTION__ << " " << event->rect();
256
257     QPainter painter(this);
258
259     QRect topRect = QRect(0, 0, event->rect().width(), 20);
260     QRect middleRect = QRect(0, topRect.bottom(), event->rect().width(),
261                              height() - 20 - 15);
262     QRect bottomRect = QRect(topRect.left(), middleRect.bottom(), event->rect().width(),
263                              15);
264
265     painter.drawPixmap(topRect, m_backgroundTopImage);
266     painter.drawPixmap(middleRect, m_backgroundMiddleImage);
267     painter.drawPixmap(bottomRect, m_backgroundBottomImage);
268 }