~ubuntu-branches/ubuntu/wily/psi/wily-proposed

« back to all changes in this revision

Viewing changes to src/psicontactlistviewdelegate.cpp

  • Committer: Package Import Robot
  • Author(s): Jan Niehusmann
  • Date: 2014-07-01 21:49:34 UTC
  • mfrom: (6.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20140701214934-gt4dkgm94byi4vnn
Tags: 0.15-1
* New upstream version
* set debhelper compat level to 9
* set Standards-Version to 3.9.5 (no further changes)
* add lintian override regarding license-problem-non-free-RFC
* use qconf to regenerate configure script
* implement hardening using buildflags instead of hardening-wrapper

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * psicontactlistviewdelegate.cpp
 
3
 * Copyright (C) 2009-2010  Yandex LLC (Michail Pishchagin)
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
18
 *
 
19
 */
 
20
 
 
21
#include "psicontactlistviewdelegate.h"
 
22
 
 
23
#include <QPainter>
 
24
#include <QTimer>
 
25
 
 
26
#include "psiiconset.h"
 
27
#include "psioptions.h"
 
28
#include "coloropt.h"
 
29
#include "contactlistview.h"
 
30
#include "common.h"
 
31
 
 
32
static const QString contactListFontOptionPath = "options.ui.look.font.contactlist";
 
33
static const QString slimGroupsOptionPath = "options.ui.look.contactlist.use-slim-group-headings";
 
34
static const QString outlinedGroupsOptionPath = "options.ui.look.contactlist.use-outlined-group-headings";
 
35
static const QString contactListBackgroundOptionPath = "options.ui.look.colors.contactlist.background";
 
36
static const QString showStatusMessagesOptionPath = "options.ui.contactlist.status-messages.show";
 
37
 
 
38
PsiContactListViewDelegate::PsiContactListViewDelegate(ContactListView* parent)
 
39
        : ContactListViewDelegate(parent)
 
40
        , font_(0)
 
41
        , fontMetrics_(0)
 
42
{
 
43
        alertTimer_ = new QTimer(this);
 
44
        alertTimer_->setInterval(100);
 
45
        alertTimer_->setSingleShot(false);
 
46
        connect(alertTimer_, SIGNAL(timeout()), SLOT(updateAlerts()));
 
47
 
 
48
        connect(PsiOptions::instance(), SIGNAL(optionChanged(const QString&)), SLOT(optionChanged(const QString&)));
 
49
        optionChanged(slimGroupsOptionPath);
 
50
        optionChanged(outlinedGroupsOptionPath);
 
51
        optionChanged(contactListFontOptionPath);
 
52
        optionChanged(contactListBackgroundOptionPath);
 
53
        optionChanged(showStatusMessagesOptionPath);
 
54
}
 
55
 
 
56
PsiContactListViewDelegate::~PsiContactListViewDelegate()
 
57
{
 
58
        delete font_;
 
59
        delete fontMetrics_;
 
60
}
 
61
 
 
62
int PsiContactListViewDelegate::avatarSize() const
 
63
{
 
64
        return 18;
 
65
}
 
66
 
 
67
QPixmap PsiContactListViewDelegate::statusPixmap(const QModelIndex& index) const
 
68
{
 
69
        int s = statusType(index);
 
70
        ContactListModel::Type type = ContactListModel::indexType(index);
 
71
        if (type == ContactListModel::ContactType ||
 
72
            type == ContactListModel::AccountType)
 
73
        {
 
74
                if (index.data(ContactListModel::IsAlertingRole).toBool()) {
 
75
                        if (!alertingIndexes_.contains(index)) {
 
76
                                alertingIndexes_[index] = true;
 
77
                                alertTimer_->start();
 
78
                        }
 
79
 
 
80
                        QVariant alertData = index.data(ContactListModel::AlertPictureRole);
 
81
                        QIcon alert;
 
82
                        if (alertData.isValid()) {
 
83
                                if (alertData.type() == QVariant::Icon) {
 
84
                                        alert = qvariant_cast<QIcon>(alertData);
 
85
                                }
 
86
                        }
 
87
 
 
88
                        return alert.pixmap(100, 100);
 
89
                }
 
90
        }
 
91
 
 
92
        if (type == ContactListModel::ContactType) {
 
93
                if (!index.data(ContactListModel::PresenceErrorRole).toString().isEmpty())
 
94
                        s = STATUS_ERROR;
 
95
                else if (index.data(ContactListModel::IsAgentRole).toBool())
 
96
                        s = statusType(index);
 
97
                else if (index.data(ContactListModel::AskingForAuthRole).toBool() && s == XMPP::Status::Offline)
 
98
                        s = STATUS_ASK;
 
99
                else if (!index.data(ContactListModel::AuthorizesToSeeStatusRole).toBool() && s == XMPP::Status::Offline)
 
100
                        s = STATUS_NOAUTH;
 
101
        }
 
102
 
 
103
        return PsiIconset::instance()->statusPtr(index.data(ContactListModel::JidRole).toString(), s)->pixmap();
 
104
}
 
105
 
 
106
void PsiContactListViewDelegate::drawContact(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
 
107
{
 
108
        drawBackground(painter, option, index);
 
109
 
 
110
        QRect r = option.rect;
 
111
 
 
112
        QRect avatarRect(r);
 
113
        const QPixmap statusPixmap = this->statusPixmap(index);
 
114
        avatarRect.translate(1, 1);
 
115
        avatarRect.setSize(statusPixmap.size());
 
116
        painter->drawPixmap(avatarRect.topLeft(), statusPixmap);
 
117
 
 
118
        r.setLeft(avatarRect.right() + 3);
 
119
 
 
120
        QColor textColor;
 
121
        if(index.data(ContactListModel::IsAnimRole).toBool()) {
 
122
                if(index.data(ContactListModel::PhaseRole).toBool()) {
 
123
                        textColor = ColorOpt::instance()->color("options.ui.look.colors.contactlist.status-change-animation2");
 
124
                }
 
125
                else {
 
126
                        textColor = ColorOpt::instance()->color("options.ui.look.colors.contactlist.status-change-animation1");
 
127
                }
 
128
        }
 
129
        else {
 
130
                if (statusType(index) == XMPP::Status::Away || statusType(index) == XMPP::Status::XA)
 
131
                        textColor = ColorOpt::instance()->color("options.ui.look.colors.contactlist.status.away");
 
132
                else if (statusType(index) == XMPP::Status::DND)
 
133
                        textColor = ColorOpt::instance()->color("options.ui.look.colors.contactlist.status.do-not-disturb");
 
134
                else if (statusType(index) == XMPP::Status::Offline)
 
135
                        textColor = ColorOpt::instance()->color("options.ui.look.colors.contactlist.status.offline");
 
136
                else
 
137
                        textColor = ColorOpt::instance()->color("options.ui.look.colors.contactlist.status.online");
 
138
        }
 
139
 
 
140
        QStyleOptionViewItemV2 o = option;
 
141
        o.font = *font_;
 
142
        o.fontMetrics = *fontMetrics_;
 
143
        QPalette palette = o.palette;
 
144
        palette.setColor(QPalette::Text, textColor);
 
145
        o.palette = palette;
 
146
 
 
147
        QString text = nameText(o, index);
 
148
        if (showStatusMessages_ && !statusText(index).isEmpty()) {
 
149
                text = tr("%1 (%2)").arg(text).arg(statusText(index));
 
150
        }
 
151
 
 
152
        drawText(painter, o, r, text, index);
 
153
 
 
154
#if 0
 
155
        int x;
 
156
        if (d->status_single)
 
157
                x = widthUsed();
 
158
        else {
 
159
                QFontMetrics fm(p->font());
 
160
                const QPixmap *pix = pixmap(column);
 
161
                x = fm.width(text(column)) + (pix ? pix->width() : 0) + 8;
 
162
        }
 
163
 
 
164
        if (d->u) {
 
165
                UserResourceList::ConstIterator it = d->u->priority();
 
166
                if (it != d->u->userResourceList().end()) {
 
167
                        if (d->u->isSecure((*it).name())) {
 
168
                                const QPixmap &pix = IconsetFactory::iconPixmap("psi/cryptoYes");
 
169
                                int y = (height() - pix.height()) / 2;
 
170
                                p->drawPixmap(x, y, pix);
 
171
                                x += 24;
 
172
                        }
 
173
                }
 
174
        }
 
175
#endif
 
176
}
 
177
 
 
178
void PsiContactListViewDelegate::drawGroup(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
 
179
{
 
180
        QStyleOptionViewItemV2 o = option;
 
181
        o.font = *font_;
 
182
        o.fontMetrics = *fontMetrics_;
 
183
        QPalette palette = o.palette;
 
184
        QColor background = ColorOpt::instance()->color("options.ui.look.colors.contactlist.grouping.header-background");
 
185
        QColor foreground = ColorOpt::instance()->color("options.ui.look.colors.contactlist.grouping.header-foreground");
 
186
        if (!slimGroup_)
 
187
                palette.setColor(QPalette::Base, background);
 
188
        palette.setColor(QPalette::Text, foreground);
 
189
        o.palette = palette;
 
190
 
 
191
        drawBackground(painter, o, index);
 
192
 
 
193
        QRect r = option.rect;
 
194
        if (!slimGroup_ && outlinedGroup_) {
 
195
                painter->setPen(QPen(foreground));
 
196
                QRect gr(r);
 
197
                gr.setLeft(contactList()->x());
 
198
                painter->drawRect(gr);
 
199
        }
 
200
 
 
201
        const QPixmap& pixmap = index.data(ContactListModel::ExpandedRole).toBool() ?
 
202
                                IconsetFactory::iconPtr("psi/groupOpen")->pixmap() :
 
203
                                IconsetFactory::iconPtr("psi/groupClosed")->pixmap();
 
204
 
 
205
        QRect pixmapRect(r);
 
206
        pixmapRect.translate(1, 1);
 
207
        pixmapRect.setSize(pixmap.size());
 
208
        painter->drawPixmap(pixmapRect.topLeft(), pixmap);
 
209
 
 
210
        r.setLeft(pixmapRect.right() + 3);
 
211
 
 
212
        QString text = index.data(Qt::ToolTipRole).toString();
 
213
        drawText(painter, o, r, text, index);
 
214
 
 
215
        if(slimGroup_ && !(option.state & QStyle::State_Selected)) {
 
216
                int h = r.y() + (r.height() / 2);
 
217
                int x = r.left() + fontMetrics_->width(text) + 8;
 
218
                painter->setPen(QPen(background,2));
 
219
                painter->drawLine(x, h, r.right(), h);
 
220
        }
 
221
}
 
222
 
 
223
void PsiContactListViewDelegate::drawAccount(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
 
224
{
 
225
        QStyleOptionViewItemV2 o = option;
 
226
        o.font = *font_;
 
227
        o.fontMetrics = *fontMetrics_;
 
228
        QPalette palette = o.palette;
 
229
        palette.setColor(QPalette::Base, ColorOpt::instance()->color("options.ui.look.colors.contactlist.profile.header-background"));
 
230
        QColor foreground = ColorOpt::instance()->color("options.ui.look.colors.contactlist.profile.header-foreground");
 
231
        palette.setColor(QPalette::Text, foreground);
 
232
        o.palette = palette;
 
233
 
 
234
        drawBackground(painter, o, index);
 
235
 
 
236
        QRect r = option.rect;
 
237
        if (outlinedGroup_) {
 
238
                painter->setPen(QPen(foreground));
 
239
                painter->drawRect(r);
 
240
        }
 
241
 
 
242
        QRect avatarRect(r);
 
243
        const QPixmap statusPixmap = this->statusPixmap(index);
 
244
        avatarRect.translate(1, 1);
 
245
        avatarRect.setSize(statusPixmap.size());
 
246
        painter->drawPixmap(avatarRect.topLeft(), statusPixmap);
 
247
 
 
248
        r.setLeft(avatarRect.right() + 3);
 
249
 
 
250
        QString text = nameText(o, index);
 
251
        r.setRight(r.left() + o.fontMetrics.width(text));
 
252
        drawText(painter, o, r, text, index);
 
253
 
 
254
        QPixmap sslPixmap = index.data(ContactListModel::UsingSSLRole).toBool() ?
 
255
                            IconsetFactory::iconPixmap("psi/cryptoYes") :
 
256
                            IconsetFactory::iconPixmap("psi/cryptoNo");
 
257
        QRect sslRect(option.rect);
 
258
        sslRect.setLeft(r.right() + 3);
 
259
        sslRect.translate(1, 1);
 
260
        sslRect.setSize(sslPixmap.size());
 
261
        painter->drawPixmap(sslRect.topLeft(), sslPixmap);
 
262
 
 
263
        r.setLeft(sslRect.right() + 3);
 
264
        r.setRight(option.rect.right());
 
265
 
 
266
        text = QString("(%1/%2)")
 
267
                .arg(index.data(ContactListModel::OnlineContactsRole).toInt())
 
268
                .arg(index.data(ContactListModel::TotalContactsRole).toInt());
 
269
        drawText(painter, o, r, text, index);
 
270
}
 
271
 
 
272
QRect PsiContactListViewDelegate::nameRect(const QStyleOptionViewItem& option, const QModelIndex& index) const
 
273
{
 
274
        Q_UNUSED(index);
 
275
        return option.rect;
 
276
}
 
277
 
 
278
QRect PsiContactListViewDelegate::groupNameRect(const QStyleOptionViewItem& option, const QModelIndex& index) const
 
279
{
 
280
        Q_UNUSED(index);
 
281
        return option.rect;
 
282
}
 
283
 
 
284
QRect PsiContactListViewDelegate::editorRect(const QRect& nameRect) const
 
285
{
 
286
        return nameRect;
 
287
}
 
288
 
 
289
void PsiContactListViewDelegate::optionChanged(const QString& option)
 
290
{
 
291
        if (option == contactListFontOptionPath) {
 
292
                delete font_;
 
293
                delete fontMetrics_;
 
294
 
 
295
                font_ = new QFont();
 
296
                font_->fromString(PsiOptions::instance()->getOption(contactListFontOptionPath).toString());
 
297
                fontMetrics_ = new QFontMetrics(*font_);
 
298
                contactList()->viewport()->update();
 
299
        }
 
300
        else if (option == contactListBackgroundOptionPath) {
 
301
                QPalette p = contactList()->palette();
 
302
                p.setColor(QPalette::Base, ColorOpt::instance()->color(contactListBackgroundOptionPath));
 
303
                const_cast<ContactListView*>(contactList())->setPalette(p);
 
304
                contactList()->viewport()->update();
 
305
        }
 
306
        else if (option == showStatusMessagesOptionPath) {
 
307
                showStatusMessages_ = PsiOptions::instance()->getOption(showStatusMessagesOptionPath).toBool();
 
308
                contactList()->viewport()->update();
 
309
        }
 
310
        else if(option == slimGroupsOptionPath) {
 
311
                slimGroup_ = PsiOptions::instance()->getOption(slimGroupsOptionPath).toBool();
 
312
                contactList()->viewport()->update();
 
313
        }
 
314
        else if(option == outlinedGroupsOptionPath) {
 
315
                outlinedGroup_ = PsiOptions::instance()->getOption(outlinedGroupsOptionPath).toBool();
 
316
                contactList()->viewport()->update();
 
317
        }
 
318
}
 
319
 
 
320
void PsiContactListViewDelegate::drawText(QPainter* painter, const QStyleOptionViewItem& o, const QRect& rect, const QString& text, const QModelIndex& index) const
 
321
{
 
322
        QRect r(rect);
 
323
        r.moveTop(r.top() + (r.height() - o.fontMetrics.height()) / 2);
 
324
        rect.adjusted(0, 2, 0, 0);
 
325
        ContactListViewDelegate::drawText(painter, o, r, text, index);
 
326
}
 
327
 
 
328
void PsiContactListViewDelegate::contactAlert(const QModelIndex& index)
 
329
{
 
330
        bool alerting = index.data(ContactListModel::IsAlertingRole).toBool();
 
331
        if (alerting)
 
332
                alertingIndexes_[index] = true;
 
333
        else
 
334
                alertingIndexes_.remove(index);
 
335
 
 
336
        if (alertingIndexes_.isEmpty())
 
337
                alertTimer_->stop();
 
338
        else
 
339
                alertTimer_->start();
 
340
}
 
341
 
 
342
void PsiContactListViewDelegate::clearAlerts()
 
343
{
 
344
        alertingIndexes_.clear();
 
345
        alertTimer_->stop();
 
346
}
 
347
 
 
348
void PsiContactListViewDelegate::updateAlerts()
 
349
{
 
350
        Q_ASSERT(!alertingIndexes_.isEmpty());
 
351
        if (!contactList()->isVisible())
 
352
                return; // needed?
 
353
 
 
354
        QRect contactListRect = contactList()->rect();
 
355
        QHashIterator<QModelIndex, bool> it(alertingIndexes_);
 
356
        while (it.hasNext()) {
 
357
                it.next();
 
358
                QRect r = contactList()->visualRect(it.key());
 
359
                if (contactListRect.intersects(r)) {
 
360
                        contactList()->dataChanged(it.key(), it.key());
 
361
                }
 
362
        }
 
363
}