~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to kde/src/delegates/historydelegate.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* 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) 2009-2014 by Savoir-Faire Linux                          *
 
3
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
 
4
 *                                                                          *
 
5
 *   This library is free software; you can redistribute it and/or          *
 
6
 *   modify it under the terms of the GNU Lesser General Public             *
 
7
 *   License as published by the Free Software Foundation; either           *
 
8
 *   version 2.1 of the License, or (at your option) any later version.     *
 
9
 *                                                                          *
 
10
 *   This library 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 GNU      *
 
13
 *   Lesser 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 "historydelegate.h"
 
19
 
 
20
//Qt
 
21
#include <QtGui/QPainter>
 
22
#include <QtGui/QApplication>
 
23
#include <QtGui/QBitmap>
 
24
#include <QtGui/QSortFilterProxyModel>
 
25
#include <QtGui/QTreeView>
 
26
#include <QtCore/QFile>
 
27
#include <QtCore/QDebug>
 
28
 
 
29
//KDE
 
30
#include <KColorScheme>
 
31
#include <KLocale>
 
32
#include <KIcon>
 
33
#include <KStandardDirs>
 
34
 
 
35
//SFLPhone
 
36
#include <lib/historymodel.h>
 
37
#include <lib/contact.h>
 
38
#include <lib/callmodel.h>
 
39
#include <lib/phonenumber.h>
 
40
#include "klib/kcfg_settings.h"
 
41
#include "widgets/playeroverlay.h"
 
42
#include "dialpaddelegate.h"
 
43
#include "../widgets/tips/ringingtip.h"
 
44
#include "klib/tipanimationwrapper.h"
 
45
#include "lib/visitors/pixmapmanipulationvisitor.h"
 
46
 
 
47
static const char* icnPath[4] = {
 
48
/* INCOMING */ ICON_HISTORY_INCOMING,
 
49
/* OUTGOING */ ICON_HISTORY_OUTGOING,
 
50
/* MISSED   */ ICON_HISTORY_MISSED  ,
 
51
/* NONE     */ ""                   ,
 
52
};
 
53
 
 
54
///Constant
 
55
#pragma GCC diagnostic ignored "-Wmissing-braces"
 
56
TypedStateMachine< const char* , Call::State > callStateIcons = {{ICON_INCOMING, ICON_RINGING, ICON_CURRENT, ICON_DIALING, ICON_HOLD, ICON_FAILURE, ICON_BUSY, ICON_TRANSFER, ICON_TRANSF_HOLD, "", "", ICON_CONFERENCE}};
 
57
 
 
58
HistoryDelegate::HistoryDelegate(QTreeView* parent) : QStyledItemDelegate(parent),m_pParent(parent),m_pDelegatedropoverlay(nullptr),m_AnimationWrapper(nullptr),m_pRingingTip(nullptr)
 
59
{
 
60
   connect(CallModel::instance(),SIGNAL(callStateChanged(Call*,Call::State)),this,SLOT(slotStopRingingAnimation()));
 
61
}
 
62
 
 
63
QSize HistoryDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const {
 
64
   if (!index.isValid())
 
65
      return QSize(-1,-1);
 
66
   const QSize sh = QStyledItemDelegate::sizeHint(option, index);
 
67
   const QFontMetrics fm(QApplication::font());
 
68
   int lineHeight = fm.height()+2;
 
69
   int rowCount = 0;
 
70
   const Call::State currentState = static_cast<Call::State>(index.data(Call::Role::CallState).toInt());
 
71
   int minimumRowHeight = (currentState == Call::State::OVER)?48:(ConfigurationSkeleton::limitMinimumRowHeight()?ConfigurationSkeleton::minimumRowHeight():0);
 
72
   if (currentState == Call::State::OVER)
 
73
      rowCount = 3;
 
74
   else {
 
75
      rowCount = ConfigurationSkeleton::displayCallPeer()
 
76
      + ConfigurationSkeleton::displayCallNumber       ()
 
77
      + ConfigurationSkeleton::displayCallSecure       ()
 
78
      + ConfigurationSkeleton::displayCallCodec        ()
 
79
      + ConfigurationSkeleton::displayCallOrganisation ()
 
80
      + ConfigurationSkeleton::displayCallDepartment   ()
 
81
      + ConfigurationSkeleton::displayCallEmail        ();
 
82
   }
 
83
   return QSize(sh.width(),((rowCount*lineHeight)<minimumRowHeight?minimumRowHeight:(rowCount*lineHeight)) + 4);
 
84
}
 
85
 
 
86
void HistoryDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
 
87
{
 
88
   Q_ASSERT(index.isValid());
 
89
 
 
90
   const bool isBookmark = index.data(Call::Role::IsBookmark).toBool();
 
91
 
 
92
   painter->save();
 
93
   int iconHeight = option.rect.height() -4;
 
94
   //Paint the "selected" or "hover" backgrounds
 
95
      //    if (option.state & QStyle::State_Selected || option.state & QStyle::State_MouseOver) {
 
96
      QStyleOptionViewItem opt2 = option;
 
97
      QPalette pal = option.palette;
 
98
      pal.setBrush(QPalette::Text,QColor(0,0,0,0));
 
99
      pal.setBrush(QPalette::HighlightedText,QColor(0,0,0,0));
 
100
      opt2.palette = pal;
 
101
      QStyledItemDelegate::paint(painter,opt2,index);
 
102
      //    }
 
103
 
 
104
   painter->setPen(QApplication::palette().color(QPalette::Active,(option.state & QStyle::State_Selected)?QPalette::HighlightedText:QPalette::Text));
 
105
   const Call::State currentState = (Call::State) index.data(Call::Role::CallState).toInt();
 
106
   if (currentState == Call::State::HOLD)
 
107
      painter->setOpacity(0.70);
 
108
 
 
109
   const PhoneNumber* n = qvariant_cast<PhoneNumber*>(index.data(Call::Role::PhoneNu));
 
110
   QPixmap pxm = n?PixmapManipulationVisitor::instance()->callPhoto(n,QSize(iconHeight+4,iconHeight+4),isBookmark).value<QPixmap>():QPixmap(QSize(iconHeight+4,iconHeight+4));
 
111
 
 
112
   //Handle history with recording
 
113
   if (index.data(Call::Role::HasRecording).toBool() && currentState == Call::State::OVER) {
 
114
      QObject* obj= qvariant_cast<Call*>(index.data(Call::Role::Object));
 
115
      Call* call  = nullptr;
 
116
      if (obj)
 
117
         call = qobject_cast<Call*>(obj);
 
118
      if (call && QFile::exists(call->recordingPath())) {
 
119
         QPainter painter(&pxm);
 
120
         QPixmap status(KStandardDirs::locate("data","sflphone-client-kde/voicemail.png"));
 
121
         status=status.scaled(QSize(24,24));
 
122
         painter.drawPixmap(pxm.width()-status.width(),pxm.height()-status.height(),status);
 
123
         if (m_pParent && m_pParent->indexWidget(index) == nullptr) {
 
124
            auto button = new PlayerOverlay(call,nullptr);
 
125
            button->setCall(call);
 
126
            m_pParent->setIndexWidget(index,button);
 
127
         }
 
128
      }
 
129
   }
 
130
   //Handle history
 
131
   else if (!isBookmark && (index.data(Call::Role::Historystate).toInt() != (int)Call::LegacyHistoryState::NONE || currentState != Call::State::OVER) && ConfigurationSkeleton::displayHistoryStatus()) {
 
132
      QPainter painter(&pxm);
 
133
      QPixmap status((currentState==Call::State::OVER)?icnPath[index.data(Call::Role::Historystate).toInt()]:callStateIcons[currentState]);
 
134
      if (!status.isNull()) {
 
135
         status=status.scaled(QSize(24,24));
 
136
         painter.drawPixmap(pxm.width()-status.width(),pxm.height()-status.height(),status);
 
137
      }
 
138
   }
 
139
   if (currentState != Call::State::OVER && index.data(Call::Role::IsRecording).toBool()) {
 
140
      const static QPixmap record(KStandardDirs::locate("data","sflphone-client-kde/record.png"));
 
141
      time_t curTime;
 
142
      ::time(&curTime);
 
143
      if (curTime%3)
 
144
         painter->drawPixmap(option.rect.x()+option.rect.width()-record.width()-2,option.rect.y()+option.rect.height()-record.height()-2,record);
 
145
   }
 
146
   int x_offset((iconHeight-pxm.width())/2),y_offset((iconHeight-pxm.height())/2);
 
147
   painter->drawPixmap(option.rect.x()+4+x_offset,option.rect.y()+y_offset+(option.rect.height()-iconHeight)/2,pxm);
 
148
 
 
149
   QFont font = painter->font();
 
150
   QFontMetrics fm(font);
 
151
   int currentHeight = option.rect.y()+fm.height()+2;
 
152
   //BEGIN history fields
 
153
   if (currentState == Call::State::OVER || isBookmark) { //History/Bookmarks
 
154
      const QPen textCol = (option.state & QStyle::State_Selected) ? Qt::white : QApplication::palette().color(QPalette::Disabled,QPalette::Text);
 
155
      font.setWeight(QFont::DemiBold);
 
156
      painter->save();
 
157
      painter->setFont(font);
 
158
      painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Qt::DisplayRole).toString());
 
159
      font.setWeight(QFont::Normal);
 
160
      painter->setFont(font);
 
161
      painter->setPen(textCol);
 
162
      currentHeight +=fm.height();
 
163
 
 
164
      //Draw INCOMING/OUTGOING/MISSED
 
165
      if (!isBookmark) {
 
166
         painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Call::Role::FormattedDate).toString());
 
167
         currentHeight +=fm.height();
 
168
         const static QPixmap* callPxm = nullptr;
 
169
         if (!callPxm)
 
170
            callPxm = new QPixmap(KStandardDirs::locate("data","sflphone-client-kde/mini/call.png"));
 
171
         painter->drawPixmap(option.rect.x()+15+iconHeight,currentHeight-12+(fm.height()-12),index.data(Call::Role::CategoryIcon).value<QPixmap>());
 
172
      }
 
173
 
 
174
// //       if (isTracked) {
 
175
// //          if (isPresent)
 
176
// //             painter->setPen(presentBrush);
 
177
// //          else
 
178
// //             painter->setPen(awayBrush);
 
179
// //       }
 
180
 
 
181
      painter->drawText(option.rect.x()+15+iconHeight+((!isBookmark)?12:0),currentHeight,index.data(Call::Role::Number).toString());
 
182
 
 
183
//       if (isTracked)
 
184
//          painter->setPen(textCol);
 
185
 
 
186
      currentHeight +=fm.height();
 
187
      painter->restore();
 
188
   }
 
189
   //END history fields
 
190
   else { //Active calls
 
191
      if (ConfigurationSkeleton::displayCallIcon()) {
 
192
         //TODO dead code
 
193
      }
 
194
      if(ConfigurationSkeleton::displayCallPeer() && !(currentState == Call::State::DIALING || (option.state & QStyle::State_Editing))) {
 
195
         font.setBold(true);
 
196
         painter->setFont(font);
 
197
         painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Qt::DisplayRole).toString());
 
198
         font.setBold(false);
 
199
         painter->setFont(font);
 
200
         currentHeight +=fm.height();
 
201
      }
 
202
 
 
203
      if (ConfigurationSkeleton::displayCallNumber() && !(currentState == Call::State::DIALING || (option.state & QStyle::State_Editing))) {
 
204
//          if (isTracked) {
 
205
//             if (isPresent)
 
206
//                painter->setPen(presentBrush);
 
207
//             else
 
208
//                painter->setPen(awayBrush);
 
209
//          }
 
210
         painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Call::Role::Number).toString());
 
211
         currentHeight +=fm.height();
 
212
      }
 
213
 
 
214
      if (ConfigurationSkeleton::displayCallSecure()) {
 
215
         painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Call::Role::Security).toString());
 
216
         currentHeight +=fm.height();
 
217
      }
 
218
 
 
219
      if (ConfigurationSkeleton::displayCallCodec()) {
 
220
         painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Call::Role::Codec).toString());
 
221
         currentHeight +=fm.height();
 
222
      }
 
223
 
 
224
      if (ConfigurationSkeleton::displayCallOrganisation()) {
 
225
         painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Call::Role::Organisation).toString());
 
226
         currentHeight +=fm.height();
 
227
      }
 
228
 
 
229
      if (ConfigurationSkeleton::displayCallDepartment()) {
 
230
         painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Call::Role::Department).toString());
 
231
         currentHeight +=fm.height();
 
232
      }
 
233
 
 
234
      if (ConfigurationSkeleton::displayCallEmail()) {
 
235
         painter->drawText(option.rect.x()+15+iconHeight,currentHeight,index.data(Call::Role::Email).toString());
 
236
         //currentHeight +=fm.height();
 
237
      }
 
238
   }
 
239
 
 
240
   if (!index.parent().isValid() && currentState != Call::State::RINGING && currentState != Call::State::INCOMING){
 
241
      const QString length = index.data(Call::Role::Length).toString();
 
242
      const int lenLen = fm.width(length);
 
243
      if (!length.isEmpty()) {
 
244
         painter->drawText(option.rect.x()+option.rect.width()-lenLen-4,option.rect.y()+(option.rect.height()/2)+(fm.height()/4),length);
 
245
      }
 
246
      DialpadDelegate::paint(painter,option,index,lenLen);
 
247
   }
 
248
   else if (!isBookmark && ((currentState == Call::State::RINGING || currentState == Call::State::INCOMING) && index.model()->rowCount() > 1)) {
 
249
      if (!m_AnimationWrapper) {
 
250
         const_cast<HistoryDelegate*>(this)->m_AnimationWrapper = new TipAnimationWrapper();
 
251
         const_cast<HistoryDelegate*>(this)->m_pRingingTip = new RingingTip();
 
252
         m_AnimationWrapper->setTip(m_pRingingTip);
 
253
      }
 
254
      if (!m_pRingingTip->isVisible())
 
255
         m_pRingingTip->setVisible(true);
 
256
      painter->save();
 
257
      painter->setRenderHint  (QPainter::Antialiasing, true   );
 
258
      painter->setOpacity(0.066);
 
259
      painter->drawImage(QRect(option.rect.x()+option.rect.width()-option.rect.height()-8,option.rect.y()+4,option.rect.height()-8,option.rect.height()-8),m_AnimationWrapper->currentImage());
 
260
      painter->restore();
 
261
   }
 
262
   else {
 
263
      //Display the dialpad if necesary
 
264
      DialpadDelegate::paint(painter,option,index);
 
265
   }
 
266
 
 
267
   //BEGIN overlay path
 
268
   if (index.data(Call::Role::DropState).toInt() != 0) {
 
269
      /*static*/ if (!m_pDelegatedropoverlay) {
 
270
         const_cast<HistoryDelegate*>(this)->m_pDelegatedropoverlay = new DelegateDropOverlay((QObject*)this);
 
271
         const_cast<HistoryDelegate*>(this)->callMap.insert(i18n("Conference")   ,new DelegateDropOverlay::OverlayButton(new QImage(KStandardDirs::locate("data","sflphone-client-kde/confBlackWhite.png")),Call::DropAction::Conference));
 
272
         const_cast<HistoryDelegate*>(this)->callMap.insert(i18n("Transfer")     ,new DelegateDropOverlay::OverlayButton(new QImage(KStandardDirs::locate("data","sflphone-client-kde/transferarrow.png")),Call::DropAction::Transfer));
 
273
         const_cast<HistoryDelegate*>(this)->historyMap.insert(i18n("Transfer")  ,new DelegateDropOverlay::OverlayButton(new QImage(KStandardDirs::locate("data","sflphone-client-kde/transferarrow.png")),Call::DropAction::Transfer));
 
274
      }
 
275
 
 
276
      if (currentState == Call::State::OVER)
 
277
         const_cast<HistoryDelegate*>(this)->m_pDelegatedropoverlay->setButtons(&const_cast<HistoryDelegate*>(this)->historyMap);
 
278
      else
 
279
         const_cast<HistoryDelegate*>(this)->m_pDelegatedropoverlay->setButtons(&const_cast<HistoryDelegate*>(this)->callMap);
 
280
      m_pDelegatedropoverlay->paintEvent(painter, option, index);
 
281
   }
 
282
   //END overlay path
 
283
 
 
284
   //BEGIN Item editor
 
285
   if (currentState == Call::State::DIALING) {
 
286
      m_pParent->edit(index);
 
287
   }
 
288
   //END item editor
 
289
   painter->restore();
 
290
}
 
291
 
 
292
void HistoryDelegate::slotStopRingingAnimation()
 
293
{
 
294
   if (m_pRingingTip && m_pRingingTip->isVisible()) {
 
295
      bool found = false;
 
296
      foreach(const Call* call,CallModel::instance()->getCallList()) {
 
297
         found = (call->state() == Call::State::RINGING || call->state() == Call::State::INCOMING);
 
298
         if (found)
 
299
            break;
 
300
      }
 
301
 
 
302
      if (!found)
 
303
         m_pRingingTip->setVisible(false);
 
304
   }
 
305
}
 
306
 
 
307
HistoryDelegate::~HistoryDelegate()
 
308
{
 
309
   if (m_AnimationWrapper)
 
310
      delete m_AnimationWrapper;
 
311
   if (m_pRingingTip)
 
312
      delete m_pRingingTip;
 
313
   if (m_pDelegatedropoverlay) {
 
314
      delete m_pDelegatedropoverlay;
 
315
      foreach (DelegateDropOverlay::OverlayButton* b, historyMap)
 
316
         delete b;
 
317
      foreach (DelegateDropOverlay::OverlayButton* b, callMap)
 
318
         delete b;
 
319
   }
 
320
}