1
/***************************************************************************
2
* Copyright (C) 2013-2014 by Savoir-Faire Linux *
3
* Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>*
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 3 of the License, or *
8
* (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 program. If not, see <http://www.gnu.org/licenses/>. *
17
**************************************************************************/
18
#include "implementation.h"
21
#include <QtCore/QDebug>
22
#include <QtGui/QColor>
23
#include <QtGui/QPainter>
24
#include <QtGui/QBitmap>
25
#include <QtGui/QApplication>
29
#include <KColorScheme>
31
#include <KStandardDirs>
34
#include <lib/contact.h>
35
#include <lib/phonenumber.h>
36
#include <lib/presencestatusmodel.h>
37
#include "klib/kcfg_settings.h"
39
const TypedStateMachine< const char* , Call::State > KDEPixmapManipulation::callStateIcons = {
53
const char* KDEPixmapManipulation::icnPath[4] = {
54
/* INCOMING */ ICON_HISTORY_INCOMING,
55
/* OUTGOING */ ICON_HISTORY_OUTGOING,
56
/* MISSED */ ICON_HISTORY_MISSED ,
60
QDebug operator<<(QDebug dbg, const Call::State& c)
62
dbg.nospace() << QString(Call::toHumanStateName(c));
66
QDebug operator<<(QDebug dbg, const Call::DaemonState& c)
68
dbg.nospace() << static_cast<int>(c);
72
QDebug operator<<(QDebug dbg, const Call::Action& c)
74
dbg.nospace() << static_cast<int>(c);
78
ColorVisitor::ColorVisitor(QPalette pal) : m_Pal(pal) {
79
m_Green = QColor(m_Pal.color(QPalette::Base));
80
if (m_Green.green()+20 >= 255) {
81
m_Green.setRed ( ((int)m_Green.red() -20));
82
m_Green.setBlue( ((int)m_Green.blue() -20));
85
m_Green.setGreen(((int)m_Green.green()+20));
87
m_Red = QColor(m_Pal.color(QPalette::Base));
88
if (m_Red.red()+20 >= 255) {
89
m_Red.setGreen( ((int)m_Red.green() -20));
90
m_Red.setBlue( ((int)m_Red.blue() -20));
93
m_Red.setRed( ((int)m_Red.red() +20));
95
m_Yellow = QColor(m_Pal.color(QPalette::Base));
96
if (m_Yellow.red()+20 >= 255 || m_Green.green()+20 >= 255) {
97
m_Yellow.setBlue(((int)m_Yellow.blue() -20));
100
m_Yellow.setGreen(((int)m_Yellow.green()+20));
101
m_Yellow.setRed( ((int)m_Yellow.red() +20));
105
QVariant ColorVisitor::getColor(const Account* a) {
106
if(a->registrationStatus() == Account::State::UNREGISTERED || !a->isEnabled())
107
return m_Pal.color(QPalette::Base);
108
if(a->registrationStatus() == Account::State::REGISTERED || a->registrationStatus() == Account::State::READY) {
111
if(a->registrationStatus() == Account::State::TRYING)
116
QVariant ColorVisitor::getIcon(const Account* a) {
117
if (a->state() == Account::AccountEditState::MODIFIED)
118
return KIcon("document-save");
119
else if (a->state() == Account::AccountEditState::OUTDATED) {
120
return KIcon("view-refresh");
125
KDEPixmapManipulation::KDEPixmapManipulation() : PixmapManipulationVisitor()
130
QVariant KDEPixmapManipulation::contactPhoto(Contact* c, QSize size, bool displayPresence) {
131
const QString hash = QString("photo2%1%2%3").arg(size.width()).arg(size.height()).arg(c->isPresent());
132
QVariant preRendered = c->property(hash.toAscii());
133
if (preRendered.isValid())
135
const int radius = (size.height() > 35) ? 7 : 5;
136
const QPixmap* pxmPtr = c->photo();
137
bool isTracked = displayPresence && c->isTracked();
138
bool isPresent = displayPresence && c->isPresent();
139
static QColor presentBrush = KStatefulBrush( KColorScheme::Window, KColorScheme::PositiveText ).brush(QPalette::Normal).color();
140
static QColor awayBrush = KStatefulBrush( KColorScheme::Window, KColorScheme::NegativeText ).brush(QPalette::Normal).color();
144
QPixmap contactPhoto(pxmPtr->scaledToWidth(size.height()-6));
146
pxm.fill(Qt::transparent);
147
QPainter painter(&pxm);
150
painter.setCompositionMode(QPainter::CompositionMode_Clear);
151
painter.fillRect(0,0,size.width(),size.height(),QBrush(Qt::white));
152
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
154
//Add corner radius to the Pixmap
155
QRect pxRect = contactPhoto.rect();
156
QBitmap mask(pxRect.size());
157
QPainter customPainter(&mask);
158
customPainter.setRenderHint (QPainter::Antialiasing, true );
159
customPainter.fillRect (pxRect , Qt::white );
160
customPainter.setBackground (Qt::black );
161
customPainter.setBrush (Qt::black );
162
customPainter.drawRoundedRect(pxRect,radius,radius);
163
contactPhoto.setMask(mask);
164
painter.drawPixmap(3,3,contactPhoto);
165
painter.setBrush(Qt::NoBrush);
166
QPen pen(QApplication::palette().color(QPalette::Disabled,QPalette::Text));
167
pen.setWidth(isTracked?1:2);
169
painter.setRenderHint (QPainter::Antialiasing, true );
170
painter.drawRoundedRect(3,3,pxm.height()-6,pxm.height()-6,radius,radius);
172
//Draw the glow around pixmaps
175
pen.setColor(presentBrush);
177
pen.setColor(awayBrush);
178
for (int i=2;i<=7;i+=2) {
181
painter.setOpacity(0.3f-(((i-2)*0.8f)/10.0f));
182
painter.drawRoundedRect(3,3,pxm.height()-6,pxm.height()-6,radius,radius);
187
pxm = drawDefaultUserPixmap(size,isTracked,isPresent);
190
c->setProperty(hash.toAscii(),pxm);
194
QVariant KDEPixmapManipulation::callPhoto(const PhoneNumber* n, QSize size, bool displayPresence) {
196
return contactPhoto(n->contact(),size,displayPresence);
199
bool isTracked = displayPresence && n->isTracked();
200
bool isPresent = displayPresence && n->isPresent();
202
return drawDefaultUserPixmap(size,isTracked,isPresent);
206
QVariant KDEPixmapManipulation::callPhoto(Call* c, QSize size, bool displayPresence) {
207
if (c->peerPhoneNumber()->contact()) {
208
return contactPhoto(c->peerPhoneNumber()->contact(),size,displayPresence);
211
return QPixmap(callStateIcons[c->state()]);
214
QVariant KDEPixmapManipulation::numberCategoryIcon(const QPixmap* p, QSize size, bool displayPresence, bool isPresent) {
216
if (displayPresence) {
217
QPixmap pxm = p?(*p):QPixmap(KStandardDirs::locate("data" , "sflphone-client-kde/mini/call.png"));
218
QPainter painter(&pxm);
219
painter.setOpacity(0.3);
220
painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
221
painter.fillRect(pxm.rect(),isPresent?Qt::green:Qt::red);
226
return QPixmap(KStandardDirs::locate("data" , "sflphone-client-kde/mini/call.png"));
229
QPixmap KDEPixmapManipulation::drawDefaultUserPixmap(QSize size, bool displayPresence, bool isPresent) {
230
//Load KDE default user pixmap
232
pxm.fill(Qt::transparent);
233
QPainter painter(&pxm);
235
painter.drawPixmap(3,3,KIcon("user-identity").pixmap(QSize(size.height()-6,size.width()-6)));
237
//Create a region where the pixmap is not fully transparent
238
if (displayPresence) {
239
static QHash<int,QRegion> r,ri;
240
static QHash<int,bool> init;
241
const int width = size.width();
243
r[width] = QRegion(QPixmap::fromImage(pxm.toImage().createAlphaMask()));
244
ri[width] = r[width].xored(pxm.rect());
248
static QColor presentBrush = KStatefulBrush( KColorScheme::Window, KColorScheme::PositiveText ).brush(QPalette::Normal).color();
249
static QColor awayBrush = KStatefulBrush( KColorScheme::Window, KColorScheme::NegativeText ).brush(QPalette::Normal).color();
252
painter.setOpacity(0.05);
253
painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
254
painter.fillRect(pxm.rect(),isPresent?Qt::green:Qt::red);
255
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
257
//Paint only outside of the pixmap, it looks better
258
painter.setClipRegion(ri[width]);
260
p.addRegion(r[width]);
261
QPen pen = painter.pen();
262
pen.setColor(isPresent?presentBrush:awayBrush);
263
painter.setBrush(Qt::NoBrush);
264
painter.setRenderHint (QPainter::Antialiasing, true );
265
for (int i=2;i<=9;i+=2) {
268
painter.setOpacity(0.30f-(((i-2)*0.45f)/10.0f));
275
void KDEPresenceSerializationVisitor::serialize() {
276
PresenceStatusModel* m = PresenceStatusModel::instance();
278
for (int i=0;i<m->rowCount();i++) {
279
QString line = QString("%1///%2///%3///%4///%5")
280
.arg(m->data(m->index(i,(int)PresenceStatusModel::Columns::Name),Qt::DisplayRole).toString())
281
.arg(m->data(m->index(i,(int)PresenceStatusModel::Columns::Message),Qt::DisplayRole).toString())
282
.arg(qvariant_cast<QColor>(m->data(m->index(i,(int)PresenceStatusModel::Columns::Message),Qt::BackgroundColorRole)).name()) //Color
283
.arg(m->data(m->index(i,(int)PresenceStatusModel::Columns::Status),Qt::CheckStateRole) == Qt::Checked) //Status
284
.arg(m->data(m->index(i,(int)PresenceStatusModel::Columns::Default),Qt::CheckStateRole) == Qt::Checked); //Default
287
ConfigurationSkeleton::setPresenceStatusList(list);
290
void KDEPresenceSerializationVisitor::load() {
291
QStringList list = ConfigurationSkeleton::presenceStatusList();
292
PresenceStatusModel* m = PresenceStatusModel::instance();
294
//Load the default one
296
PresenceStatusModel::StatusData* data = new PresenceStatusModel::StatusData();
297
data->name = i18n("Online") ;
298
data->message = i18n("I am available");
299
data->status = true ;
300
data->defaultStatus = true;
302
data = new PresenceStatusModel::StatusData();
303
data->name = i18n("Away") ;
304
data->message = i18n("I am away");
305
data->status = false ;
307
data = new PresenceStatusModel::StatusData();
308
data->name = i18n("Busy") ;
309
data->message = i18n("I am busy");
310
data->status = false ;
312
data = new PresenceStatusModel::StatusData();
313
data->name = i18n("DND") ;
314
data->message = i18n("Please do not disturb me");
315
data->status = false ;
319
foreach(const QString& line, list) {
320
QStringList fields = line.split("///");
321
PresenceStatusModel::StatusData* data = new PresenceStatusModel::StatusData();
322
data->name = fields[(int)PresenceStatusModel::Columns::Name ];
323
data->message = fields[(int)PresenceStatusModel::Columns::Message];
324
data->color = QColor(fields[(int)PresenceStatusModel::Columns::Color]);
325
data->status = fields[(int)PresenceStatusModel::Columns::Status] == "1";
326
data->defaultStatus = fields[(int)PresenceStatusModel::Columns::Default] == "1";
332
KDEPresenceSerializationVisitor::~KDEPresenceSerializationVisitor()