2
* psicontactlistviewdelegate.cpp
3
* Copyright (C) 2009-2010 Yandex LLC (Michail Pishchagin)
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.
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.
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
21
#include "psicontactlistviewdelegate.h"
26
#include "psiiconset.h"
27
#include "psioptions.h"
29
#include "contactlistview.h"
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";
38
PsiContactListViewDelegate::PsiContactListViewDelegate(ContactListView* parent)
39
: ContactListViewDelegate(parent)
43
alertTimer_ = new QTimer(this);
44
alertTimer_->setInterval(100);
45
alertTimer_->setSingleShot(false);
46
connect(alertTimer_, SIGNAL(timeout()), SLOT(updateAlerts()));
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);
56
PsiContactListViewDelegate::~PsiContactListViewDelegate()
62
int PsiContactListViewDelegate::avatarSize() const
67
QPixmap PsiContactListViewDelegate::statusPixmap(const QModelIndex& index) const
69
int s = statusType(index);
70
ContactListModel::Type type = ContactListModel::indexType(index);
71
if (type == ContactListModel::ContactType ||
72
type == ContactListModel::AccountType)
74
if (index.data(ContactListModel::IsAlertingRole).toBool()) {
75
if (!alertingIndexes_.contains(index)) {
76
alertingIndexes_[index] = true;
80
QVariant alertData = index.data(ContactListModel::AlertPictureRole);
82
if (alertData.isValid()) {
83
if (alertData.type() == QVariant::Icon) {
84
alert = qvariant_cast<QIcon>(alertData);
88
return alert.pixmap(100, 100);
92
if (type == ContactListModel::ContactType) {
93
if (!index.data(ContactListModel::PresenceErrorRole).toString().isEmpty())
95
else if (index.data(ContactListModel::IsAgentRole).toBool())
96
s = statusType(index);
97
else if (index.data(ContactListModel::AskingForAuthRole).toBool() && s == XMPP::Status::Offline)
99
else if (!index.data(ContactListModel::AuthorizesToSeeStatusRole).toBool() && s == XMPP::Status::Offline)
103
return PsiIconset::instance()->statusPtr(index.data(ContactListModel::JidRole).toString(), s)->pixmap();
106
void PsiContactListViewDelegate::drawContact(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
108
drawBackground(painter, option, index);
110
QRect r = option.rect;
113
const QPixmap statusPixmap = this->statusPixmap(index);
114
avatarRect.translate(1, 1);
115
avatarRect.setSize(statusPixmap.size());
116
painter->drawPixmap(avatarRect.topLeft(), statusPixmap);
118
r.setLeft(avatarRect.right() + 3);
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");
126
textColor = ColorOpt::instance()->color("options.ui.look.colors.contactlist.status-change-animation1");
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");
137
textColor = ColorOpt::instance()->color("options.ui.look.colors.contactlist.status.online");
140
QStyleOptionViewItemV2 o = option;
142
o.fontMetrics = *fontMetrics_;
143
QPalette palette = o.palette;
144
palette.setColor(QPalette::Text, textColor);
147
QString text = nameText(o, index);
148
if (showStatusMessages_ && !statusText(index).isEmpty()) {
149
text = tr("%1 (%2)").arg(text).arg(statusText(index));
152
drawText(painter, o, r, text, index);
156
if (d->status_single)
159
QFontMetrics fm(p->font());
160
const QPixmap *pix = pixmap(column);
161
x = fm.width(text(column)) + (pix ? pix->width() : 0) + 8;
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);
178
void PsiContactListViewDelegate::drawGroup(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
180
QStyleOptionViewItemV2 o = option;
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");
187
palette.setColor(QPalette::Base, background);
188
palette.setColor(QPalette::Text, foreground);
191
drawBackground(painter, o, index);
193
QRect r = option.rect;
194
if (!slimGroup_ && outlinedGroup_) {
195
painter->setPen(QPen(foreground));
197
gr.setLeft(contactList()->x());
198
painter->drawRect(gr);
201
const QPixmap& pixmap = index.data(ContactListModel::ExpandedRole).toBool() ?
202
IconsetFactory::iconPtr("psi/groupOpen")->pixmap() :
203
IconsetFactory::iconPtr("psi/groupClosed")->pixmap();
206
pixmapRect.translate(1, 1);
207
pixmapRect.setSize(pixmap.size());
208
painter->drawPixmap(pixmapRect.topLeft(), pixmap);
210
r.setLeft(pixmapRect.right() + 3);
212
QString text = index.data(Qt::ToolTipRole).toString();
213
drawText(painter, o, r, text, index);
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);
223
void PsiContactListViewDelegate::drawAccount(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
225
QStyleOptionViewItemV2 o = option;
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);
234
drawBackground(painter, o, index);
236
QRect r = option.rect;
237
if (outlinedGroup_) {
238
painter->setPen(QPen(foreground));
239
painter->drawRect(r);
243
const QPixmap statusPixmap = this->statusPixmap(index);
244
avatarRect.translate(1, 1);
245
avatarRect.setSize(statusPixmap.size());
246
painter->drawPixmap(avatarRect.topLeft(), statusPixmap);
248
r.setLeft(avatarRect.right() + 3);
250
QString text = nameText(o, index);
251
r.setRight(r.left() + o.fontMetrics.width(text));
252
drawText(painter, o, r, text, index);
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);
263
r.setLeft(sslRect.right() + 3);
264
r.setRight(option.rect.right());
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);
272
QRect PsiContactListViewDelegate::nameRect(const QStyleOptionViewItem& option, const QModelIndex& index) const
278
QRect PsiContactListViewDelegate::groupNameRect(const QStyleOptionViewItem& option, const QModelIndex& index) const
284
QRect PsiContactListViewDelegate::editorRect(const QRect& nameRect) const
289
void PsiContactListViewDelegate::optionChanged(const QString& option)
291
if (option == contactListFontOptionPath) {
296
font_->fromString(PsiOptions::instance()->getOption(contactListFontOptionPath).toString());
297
fontMetrics_ = new QFontMetrics(*font_);
298
contactList()->viewport()->update();
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();
306
else if (option == showStatusMessagesOptionPath) {
307
showStatusMessages_ = PsiOptions::instance()->getOption(showStatusMessagesOptionPath).toBool();
308
contactList()->viewport()->update();
310
else if(option == slimGroupsOptionPath) {
311
slimGroup_ = PsiOptions::instance()->getOption(slimGroupsOptionPath).toBool();
312
contactList()->viewport()->update();
314
else if(option == outlinedGroupsOptionPath) {
315
outlinedGroup_ = PsiOptions::instance()->getOption(outlinedGroupsOptionPath).toBool();
316
contactList()->viewport()->update();
320
void PsiContactListViewDelegate::drawText(QPainter* painter, const QStyleOptionViewItem& o, const QRect& rect, const QString& text, const QModelIndex& index) const
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);
328
void PsiContactListViewDelegate::contactAlert(const QModelIndex& index)
330
bool alerting = index.data(ContactListModel::IsAlertingRole).toBool();
332
alertingIndexes_[index] = true;
334
alertingIndexes_.remove(index);
336
if (alertingIndexes_.isEmpty())
339
alertTimer_->start();
342
void PsiContactListViewDelegate::clearAlerts()
344
alertingIndexes_.clear();
348
void PsiContactListViewDelegate::updateAlerts()
350
Q_ASSERT(!alertingIndexes_.isEmpty());
351
if (!contactList()->isVisible())
354
QRect contactListRect = contactList()->rect();
355
QHashIterator<QModelIndex, bool> it(alertingIndexes_);
356
while (it.hasNext()) {
358
QRect r = contactList()->visualRect(it.key());
359
if (contactListRect.intersects(r)) {
360
contactList()->dataChanged(it.key(), it.key());