1 /*
2  * %kadu copyright begin%
3  * Copyright 2012 Wojciech Treter (juzefwt@gmail.com)
4  * Copyright 2012, 2014 Bartosz Brachaczek (b.brachaczek@gmail.com)
5  * Copyright 2011, 2013, 2014 Rafał Przemysław Malinowski (rafal.przemyslaw.malinowski@gmail.com)
6  * %kadu copyright end%
7  * Copyright 2010 Dariusz Markowicz
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <QtCore/QModelIndex>
24 #include <QtGui/QPainter>
25 #include <QtGui/QPainterPath>
26 #include <QtGui/QPixmap>
27 #include <QtGui/QPixmapCache>
28 #include <QtWidgets/QStyleOptionViewItem>
29 
30 #include "contacts/contact.h"
31 #include "gui/widgets/talkable-delegate-configuration.h"
32 #include "model/roles.h"
33 
34 #include "avatar-painter.h"
35 
AvatarPainter(TalkableDelegateConfiguration * configuration,const QStyleOptionViewItemV4 & option,const QRect & avatarRect,const QModelIndex & index)36 AvatarPainter::AvatarPainter(TalkableDelegateConfiguration *configuration, const QStyleOptionViewItemV4 &option, const QRect &avatarRect, const QModelIndex &index) :
37 		Configuration(configuration), Option(option), AvatarRect(avatarRect), Index(index)
38 {
39 	Avatar = Index.data(AvatarRole).value<QPixmap>();
40 }
41 
greyOut()42 bool AvatarPainter::greyOut()
43 {
44 	if (!Configuration->avatarGreyOut())
45 		return false;
46 
47 	Contact contact = Index.data(ContactRole).value<Contact>();
48 	return contact.currentStatus().isDisconnected();
49 }
50 
cacheKey()51 QString AvatarPainter::cacheKey()
52 {
53 	return QString("msi-%1-%2,%3,%4")
54 			.arg(Avatar.cacheKey())
55 			.arg(greyOut())
56 			.arg(Configuration->avatarBorder())
57 			.arg(Option.state & QStyle::State_Selected ? 1 : 0);
58 }
59 
getOrCreateCacheItem()60 QPixmap AvatarPainter::getOrCreateCacheItem()
61 {
62 	QString key = cacheKey();
63 
64 	QPixmap cached;
65 	if (QPixmapCache::find(key, &cached))
66 		return cached;
67 
68 	QPixmap item = QPixmap(AvatarRect.size());
69 	item.fill(QColor(0, 0, 0, 0));
70 
71 	QPainter cachePainter;
72 	cachePainter.begin(&item);
73 	doPaint(&cachePainter, item.size());
74 	cachePainter.end();
75 
76 	QPixmapCache::insert(key, item);
77 
78 	return item;
79 }
80 
paintFromCache(QPainter * painter)81 void AvatarPainter::paintFromCache(QPainter *painter)
82 {
83 	QPixmap cached = getOrCreateCacheItem();
84 
85 	painter->drawPixmap(AvatarRect, cached);
86 }
87 
cropped()88 QPixmap AvatarPainter::cropped()
89 {
90 	int minDimension = Avatar.height() < Avatar.width()
91 		? Avatar.height()
92 		: Avatar.width();
93 
94 	int x = (Avatar.width() - minDimension) / 2;
95 	int y = (Avatar.height() - minDimension) / 2;
96 
97 	QImage cropped = Avatar.toImage().copy(x, y, minDimension, minDimension);
98 
99 	return QPixmap::fromImage(cropped);
100 }
101 
doPaint(QPainter * painter,const QSize & size)102 void AvatarPainter::doPaint(QPainter *painter, const QSize &size)
103 {
104 	QPixmap displayAvatar;
105 	QPixmap croppedAvatar = cropped();
106 
107 	if (croppedAvatar.height() > size.height() || croppedAvatar.width() > size.width())
108 		displayAvatar = croppedAvatar.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
109 	else
110 		displayAvatar = croppedAvatar;
111 
112 	QRect displayRect = displayAvatar.rect();
113 	displayRect.moveTop((size.height() - displayRect.height()) / 2);
114 	displayRect.moveLeft((size.width() - displayRect.width()) / 2);
115 
116 	// grey out offline contacts' avatar
117 	displayAvatar = greyOut()
118 		? QIcon(displayAvatar).pixmap(displayAvatar.size(), QIcon::Disabled)
119 		: displayAvatar;
120 
121 	int radius = 3;
122 	QPainterPath displayRectPath;
123 	displayRectPath.addRoundedRect(displayRect, radius, radius);
124 
125 	painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
126 	painter->setClipPath(displayRectPath);
127 	painter->drawPixmap(displayRect, displayAvatar);
128 	painter->setClipping(false);
129 
130 	// draw avatar border
131 	if (Configuration->avatarBorder())
132 		painter->drawRoundedRect(displayRect, radius, radius);
133 }
134 
paint(QPainter * painter)135 void AvatarPainter::paint(QPainter *painter)
136 {
137 	if (!Configuration->showAvatars() || AvatarRect.isEmpty() || Avatar.isNull())
138 		return;
139 
140 	paintFromCache(painter);
141 }
142