~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to kde/src/implementation.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2013-2014 by Savoir-Faire Linux                         *
 
3
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>*
 
4
 *                                                                         *
 
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.                                   *
 
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 program.  If not, see <http://www.gnu.org/licenses/>. *
 
17
 **************************************************************************/
 
18
#include "implementation.h"
 
19
 
 
20
//Qt
 
21
#include <QtCore/QDebug>
 
22
#include <QtGui/QColor>
 
23
#include <QtGui/QPainter>
 
24
#include <QtGui/QBitmap>
 
25
#include <QtGui/QApplication>
 
26
 
 
27
//KDE
 
28
#include <KIcon>
 
29
#include <KColorScheme>
 
30
#include <KLocale>
 
31
#include <KStandardDirs>
 
32
 
 
33
//SFLPhone
 
34
#include <lib/contact.h>
 
35
#include <lib/phonenumber.h>
 
36
#include <lib/presencestatusmodel.h>
 
37
#include "klib/kcfg_settings.h"
 
38
 
 
39
const TypedStateMachine< const char* , Call::State > KDEPixmapManipulation::callStateIcons = {
 
40
   {  ICON_INCOMING   ,
 
41
      ICON_RINGING    ,
 
42
      ICON_CURRENT    ,
 
43
      ICON_DIALING    ,
 
44
      ICON_HOLD       ,
 
45
      ICON_FAILURE    ,
 
46
      ICON_BUSY       ,
 
47
      ICON_TRANSFER   ,
 
48
      ICON_TRANSF_HOLD,
 
49
      ""              ,
 
50
      ""              ,
 
51
      ICON_CONFERENCE}};
 
52
 
 
53
const char* KDEPixmapManipulation::icnPath[4] = {
 
54
   /* INCOMING */ ICON_HISTORY_INCOMING,
 
55
   /* OUTGOING */ ICON_HISTORY_OUTGOING,
 
56
   /* MISSED   */ ICON_HISTORY_MISSED  ,
 
57
   /* NONE     */ ""                   ,
 
58
};
 
59
 
 
60
QDebug operator<<(QDebug dbg, const Call::State& c)
 
61
{
 
62
   dbg.nospace() << QString(Call::toHumanStateName(c));
 
63
   return dbg.space();
 
64
}
 
65
 
 
66
QDebug operator<<(QDebug dbg, const Call::DaemonState& c)
 
67
{
 
68
   dbg.nospace() << static_cast<int>(c);
 
69
   return dbg.space();
 
70
}
 
71
 
 
72
QDebug operator<<(QDebug dbg, const Call::Action& c)
 
73
{
 
74
   dbg.nospace() << static_cast<int>(c);
 
75
   return dbg.space();
 
76
}
 
77
 
 
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));
 
83
   }
 
84
   else
 
85
      m_Green.setGreen(((int)m_Green.green()+20));
 
86
 
 
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));
 
91
   }
 
92
   else
 
93
      m_Red.setRed(    ((int)m_Red.red()     +20));
 
94
 
 
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));
 
98
   }
 
99
   else {
 
100
      m_Yellow.setGreen(((int)m_Yellow.green()+20));
 
101
      m_Yellow.setRed( ((int)m_Yellow.red()   +20));
 
102
   }
 
103
}
 
104
 
 
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) {
 
109
      return m_Green;
 
110
   }
 
111
   if(a->registrationStatus() == Account::State::TRYING)
 
112
      return m_Yellow;
 
113
   return m_Red;
 
114
}
 
115
 
 
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");
 
121
   }
 
122
   return QVariant();
 
123
}
 
124
 
 
125
KDEPixmapManipulation::KDEPixmapManipulation() : PixmapManipulationVisitor()
 
126
{
 
127
   
 
128
}
 
129
 
 
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())
 
134
      return preRendered;
 
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();
 
141
 
 
142
   QPixmap pxm;
 
143
   if (pxmPtr) {
 
144
      QPixmap contactPhoto(pxmPtr->scaledToWidth(size.height()-6));
 
145
      pxm = QPixmap(size);
 
146
      pxm.fill(Qt::transparent);
 
147
      QPainter painter(&pxm);
 
148
 
 
149
      //Clear the pixmap
 
150
      painter.setCompositionMode(QPainter::CompositionMode_Clear);
 
151
      painter.fillRect(0,0,size.width(),size.height(),QBrush(Qt::white));
 
152
      painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
 
153
 
 
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);
 
168
      painter.setPen(pen);
 
169
      painter.setRenderHint  (QPainter::Antialiasing, true   );
 
170
      painter.drawRoundedRect(3,3,pxm.height()-6,pxm.height()-6,radius,radius);
 
171
 
 
172
      //Draw the glow around pixmaps
 
173
      if (isTracked) {
 
174
         if (isPresent)
 
175
            pen.setColor(presentBrush);
 
176
         else
 
177
            pen.setColor(awayBrush);
 
178
         for (int i=2;i<=7;i+=2) {
 
179
            pen.setWidth(i);
 
180
            painter.setPen(pen);
 
181
            painter.setOpacity(0.3f-(((i-2)*0.8f)/10.0f));
 
182
            painter.drawRoundedRect(3,3,pxm.height()-6,pxm.height()-6,radius,radius);
 
183
         }
 
184
      }
 
185
   }
 
186
   else {
 
187
      pxm = drawDefaultUserPixmap(size,isTracked,isPresent);
 
188
   }
 
189
 
 
190
   c->setProperty(hash.toAscii(),pxm);
 
191
   return pxm;
 
192
}
 
193
 
 
194
QVariant KDEPixmapManipulation::callPhoto(const PhoneNumber* n, QSize size, bool displayPresence) {
 
195
   if (n->contact()) {
 
196
      return contactPhoto(n->contact(),size,displayPresence);
 
197
   }
 
198
   else {
 
199
      bool isTracked = displayPresence && n->isTracked();
 
200
      bool isPresent = displayPresence && n->isPresent();
 
201
 
 
202
      return drawDefaultUserPixmap(size,isTracked,isPresent);
 
203
   }
 
204
}
 
205
 
 
206
QVariant KDEPixmapManipulation::callPhoto(Call* c, QSize size, bool displayPresence) {
 
207
   if (c->peerPhoneNumber()->contact()) {
 
208
      return contactPhoto(c->peerPhoneNumber()->contact(),size,displayPresence);
 
209
   }
 
210
   else
 
211
      return QPixmap(callStateIcons[c->state()]);
 
212
}
 
213
 
 
214
QVariant KDEPixmapManipulation::numberCategoryIcon(const QPixmap* p, QSize size, bool displayPresence, bool isPresent) {
 
215
   Q_UNUSED(size)
 
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);
 
222
      return pxm;
 
223
   }
 
224
   if (p)
 
225
      return *p;
 
226
   return QPixmap(KStandardDirs::locate("data" , "sflphone-client-kde/mini/call.png"));
 
227
}
 
228
 
 
229
QPixmap KDEPixmapManipulation::drawDefaultUserPixmap(QSize size, bool displayPresence, bool isPresent) {
 
230
   //Load KDE default user pixmap
 
231
   QPixmap pxm(size);
 
232
   pxm.fill(Qt::transparent);
 
233
   QPainter painter(&pxm);
 
234
 
 
235
   painter.drawPixmap(3,3,KIcon("user-identity").pixmap(QSize(size.height()-6,size.width()-6)));
 
236
 
 
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();
 
242
      if (!init[width]) {
 
243
         r[width] = QRegion(QPixmap::fromImage(pxm.toImage().createAlphaMask()));
 
244
         ri[width] = r[width].xored(pxm.rect());
 
245
         init[width] = true;
 
246
      }
 
247
 
 
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();
 
250
 
 
251
 
 
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);
 
256
 
 
257
      //Paint only outside of the pixmap, it looks better
 
258
      painter.setClipRegion(ri[width]);
 
259
      QPainterPath p;
 
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) {
 
266
         pen.setWidth(i);
 
267
         painter.setPen(pen);
 
268
         painter.setOpacity(0.30f-(((i-2)*0.45f)/10.0f));
 
269
         painter.drawPath(p);
 
270
      }
 
271
   }
 
272
   return pxm;
 
273
}
 
274
 
 
275
void KDEPresenceSerializationVisitor::serialize() {
 
276
   PresenceStatusModel* m = PresenceStatusModel::instance();
 
277
   QStringList list;
 
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
 
285
         list << line;
 
286
   }
 
287
   ConfigurationSkeleton::setPresenceStatusList(list);
 
288
}
 
289
 
 
290
void KDEPresenceSerializationVisitor::load() {
 
291
   QStringList list = ConfigurationSkeleton::presenceStatusList();
 
292
   PresenceStatusModel* m = PresenceStatusModel::instance();
 
293
 
 
294
   //Load the default one
 
295
   if (!list.size()) {
 
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;
 
301
      m->addStatus(data);
 
302
      data = new PresenceStatusModel::StatusData();
 
303
      data->name       = i18n("Away")    ;
 
304
      data->message    = i18n("I am away");
 
305
      data->status     = false      ;
 
306
      m->addStatus(data);
 
307
      data = new PresenceStatusModel::StatusData();
 
308
      data->name       = i18n("Busy")    ;
 
309
      data->message    = i18n("I am busy");
 
310
      data->status     = false      ;
 
311
      m->addStatus(data);
 
312
      data = new PresenceStatusModel::StatusData();
 
313
      data->name       = i18n("DND")    ;
 
314
      data->message    = i18n("Please do not disturb me");
 
315
      data->status     = false      ;
 
316
      m->addStatus(data);
 
317
   }
 
318
   else {
 
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";
 
327
         m->addStatus(data);
 
328
      }
 
329
   }
 
330
}
 
331
 
 
332
KDEPresenceSerializationVisitor::~KDEPresenceSerializationVisitor()
 
333
{
 
334
   
 
335
}