~ubuntu-branches/ubuntu/quantal/sflphone/quantal

« back to all changes in this revision

Viewing changes to kde/src/CallView.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-05-27 08:22:22 UTC
  • mfrom: (4.1.15 sid)
  • Revision ID: package-import@ubuntu.com-20120527082222-fs3ojksqvt0ol6rl
Tags: 1.1.0-2
* Drop unsupported CELT codec (Build-Depends)
  - Fixes "Spurious build dependency on libcelt-dev" (Closes: #674644)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 *   Copyright (C) 2009-2012 by Savoir-Faire Linux                         *
3
 
 *   Author : Emmanuel Lepage Valle <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, write to the                         *
17
 
 *   Free Software Foundation, Inc.,                                       *
18
 
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19
 
 **************************************************************************/
20
 
 
21
 
//Parent
22
 
#include "CallView.h"
23
 
 
24
 
//Qt
25
 
#include <QtGui/QInputDialog>
26
 
#include <QtGui/QTreeWidget>
27
 
#include <QtGui/QTreeWidgetItem>
28
 
#include <QtGui/QPushButton>
29
 
#include <QtGui/QSpacerItem>
30
 
#include <QtGui/QGridLayout>
31
 
#include <QtGui/QLabel>
32
 
 
33
 
//KDE
34
 
#include <KDebug>
35
 
#include <KLineEdit>
36
 
#include <KStandardDirs>
37
 
 
38
 
//SFLPhone library
39
 
#include "lib/Contact.h"
40
 
#include "lib/sflphone_const.h"
41
 
#include "lib/callmanager_interface_singleton.h"
42
 
 
43
 
//SFLPhone
44
 
#include "widgets/CallTreeItem.h"
45
 
#include "SFLPhone.h"
46
 
#include "SFLPhoneView.h"
47
 
#include "AkonadiBackend.h"
48
 
 
49
 
 
50
 
///Retrieve current and older calls from the daemon, fill history and the calls TreeView and enable drag n' drop
51
 
CallView::CallView(QWidget* parent) : QTreeWidget(parent),m_pActiveOverlay(0),m_pCallPendingTransfer(0)
52
 
{
53
 
   //Widget part
54
 
   setAcceptDrops(true);
55
 
   setDragEnabled(true);
56
 
   setAnimated(true);
57
 
   CallTreeItemDelegate *delegate = new CallTreeItemDelegate();
58
 
   setItemDelegate(delegate);
59
 
   setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
60
 
 
61
 
   m_pTransferOverlay = new CallViewOverlay(this);
62
 
   m_pTransferOverlay->setVisible(false);
63
 
   m_pTransferOverlay->resize(size());
64
 
   QLabel* lblImg = new QLabel("<img width=100 height=100  src='"+KStandardDirs::locate("data","sflphone-client-kde/transferarraw.png")+"' />");
65
 
   m_pTransferOverlay->setCornerWidget(lblImg);
66
 
 
67
 
   m_pTransferB  = new QPushButton(m_pTransferOverlay);
68
 
   m_pTransferLE = new KLineEdit(m_pTransferOverlay);
69
 
   m_pTransferB->setText("Transfer");
70
 
   m_pTransferB->setMaximumSize(70,9000);
71
 
   QGridLayout* gl = new QGridLayout(m_pTransferOverlay);
72
 
   gl->addItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Minimum),0,0,1,3);
73
 
   gl->addWidget(m_pTransferLE,1,1,1,2);
74
 
   gl->addWidget(m_pTransferB,1,4,1,2);
75
 
   gl->addItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Minimum),2,0,1,3);
76
 
 
77
 
   //User Interface even
78
 
   //              SENDER                                   SIGNAL                              RECEIVER                     SLOT                        /
79
 
   /**/connect(this              , SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)              ) , this, SLOT( itemDoubleClicked(QTreeWidgetItem*,int)) );
80
 
   /**/connect(this              , SIGNAL(itemClicked(QTreeWidgetItem*,int)                    ) , this, SLOT( itemClicked(QTreeWidgetItem*,int))       );
81
 
   /**/connect(this              , SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)) , this, SLOT( itemClicked(QTreeWidgetItem*))           );
82
 
   /**/connect(SFLPhone::model() , SIGNAL(conferenceCreated(Call*)                             ) , this, SLOT( addConference(Call*))                    );
83
 
   /**/connect(SFLPhone::model() , SIGNAL(conferenceChanged(Call*)                             ) , this, SLOT( conferenceChanged(Call*))                );
84
 
   /**/connect(SFLPhone::model() , SIGNAL(aboutToRemoveConference(Call*)                       ) , this, SLOT( conferenceRemoved(Call*))                );
85
 
   /**/connect(SFLPhone::model() , SIGNAL(callAdded(Call*,Call*)                               ) , this, SLOT( addCall(Call*,Call*))                    );
86
 
   /**/connect(m_pTransferB      , SIGNAL(clicked()                                            ) , this, SLOT( transfer())                              );
87
 
   /**/connect(m_pTransferLE     , SIGNAL(returnPressed()                                      ) , this, SLOT( transfer())                              );
88
 
   /*                                                                                                                                                   */
89
 
 
90
 
}
91
 
 
92
 
 
93
 
/*****************************************************************************
94
 
 *                                                                           *
95
 
 *                        Drag and drop related code                         *
96
 
 *                                                                           *
97
 
 ****************************************************************************/
98
 
 
99
 
///Called when someone try to drop something on the tree
100
 
void CallView::dragEnterEvent ( QDragEnterEvent *e )
101
 
{
102
 
   kDebug() << "Potential drag event enter";
103
 
   e->accept();
104
 
}
105
 
 
106
 
///When a drag position change
107
 
void CallView::dragMoveEvent  ( QDragMoveEvent  *e )
108
 
{
109
 
   e->accept();
110
 
}
111
 
 
112
 
///When a drag event is leaving the widget
113
 
void CallView::dragLeaveEvent ( QDragLeaveEvent *e )
114
 
{
115
 
   kDebug() << "Potential drag event leave";
116
 
   e->accept();
117
 
}
118
 
 
119
 
///Proxy to handle transfer mime data
120
 
void CallView::transferDropEvent(Call* call,QMimeData* data)
121
 
{
122
 
   QByteArray encodedCallId = data->data( MIME_CALLID );
123
 
   SFLPhone::model()->attendedTransfer(SFLPhone::model()->getCall(encodedCallId),call);
124
 
}
125
 
 
126
 
///Proxy to handle conversation mime data
127
 
void CallView::conversationDropEvent(Call* call,QMimeData* data)
128
 
{
129
 
   kDebug() << "Calling real drag and drop function";
130
 
   dropMimeData(SFLPhone::model()->getIndex(call), 0, data, (Qt::DropAction)0);
131
 
}
132
 
 
133
 
///A call is dropped on another call
134
 
bool CallView::callToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
135
 
{
136
 
   Q_UNUSED(index)
137
 
   Q_UNUSED(action)
138
 
   QByteArray encodedCallId      = data->data( MIME_CALLID      );
139
 
   if (!QString(encodedCallId).isEmpty()) {
140
 
      if (SFLPhone::model()->getIndex(encodedCallId))
141
 
        clearArtefact(SFLPhone::model()->getIndex(encodedCallId));
142
 
 
143
 
      if (!parent) {
144
 
         kDebug() << "Call dropped on empty space";
145
 
         if (SFLPhone::model()->getIndex(encodedCallId)->parent()) {
146
 
            kDebug() << "Detaching participant";
147
 
            SFLPhone::model()->detachParticipant(SFLPhone::model()->getCall(encodedCallId));
148
 
         }
149
 
         else
150
 
            kDebug() << "The call is not in a conversation (doing nothing)";
151
 
         return true;
152
 
      }
153
 
 
154
 
      if (SFLPhone::model()->getCall(parent)->getCallId() == QString(encodedCallId)) {
155
 
         kDebug() << "Call dropped on itself (doing nothing)";
156
 
         return true;
157
 
      }
158
 
 
159
 
      if ((parent->childCount()) && (SFLPhone::model()->getIndex(encodedCallId)->childCount())) {
160
 
         kDebug() << "Merging two conferences";
161
 
         SFLPhone::model()->mergeConferences(SFLPhone::model()->getCall(parent),SFLPhone::model()->getCall(encodedCallId));
162
 
         return true;
163
 
      }
164
 
      else if ((parent->parent()) || (parent->childCount())) {
165
 
         kDebug() << "Call dropped on a conference";
166
 
 
167
 
         if ((SFLPhone::model()->getIndex(encodedCallId)->childCount()) && (!parent->childCount())) {
168
 
            kDebug() << "Conference dropped on a call (doing nothing)";
169
 
            return true;
170
 
         }
171
 
 
172
 
         QTreeWidgetItem* call1 = SFLPhone::model()->getIndex(encodedCallId);
173
 
         QTreeWidgetItem* call2 = (parent->parent())?parent->parent():parent;
174
 
 
175
 
         if (call1->parent()) {
176
 
            kDebug() << "Call 1 is part of a conference";
177
 
            if (call1->parent() == call2) {
178
 
               kDebug() << "Call dropped on it's own conference (doing nothing)";
179
 
               return true;
180
 
            }
181
 
            else if (SFLPhone::model()->getIndex(call1)->childCount()) {
182
 
               kDebug() << "Merging two conferences";
183
 
               SFLPhone::model()->mergeConferences(SFLPhone::model()->getCall(call1),SFLPhone::model()->getCall(call2));
184
 
            }
185
 
            else if (call1->parent()) {
186
 
               kDebug() << "Moving call from a conference to an other";
187
 
               SFLPhone::model()->detachParticipant(SFLPhone::model()->getCall(encodedCallId));
188
 
            }
189
 
         }
190
 
         kDebug() << "Adding participant";
191
 
         int state = SFLPhone::model()->getCall(call1)->getState();
192
 
         if(state == CALL_STATE_INCOMING || state == CALL_STATE_DIALING || state == CALL_STATE_TRANSFER || state == CALL_STATE_TRANSF_HOLD) {
193
 
            SFLPhone::model()->getCall(call1)->actionPerformed(CALL_ACTION_ACCEPT);
194
 
         }
195
 
         state = SFLPhone::model()->getCall(call2)->getState();
196
 
         if(state == CALL_STATE_INCOMING || state == CALL_STATE_DIALING || state == CALL_STATE_TRANSFER || state == CALL_STATE_TRANSF_HOLD) {
197
 
            SFLPhone::model()->getCall(call2)->actionPerformed(CALL_ACTION_ACCEPT);
198
 
         }
199
 
         SFLPhone::model()->addParticipant(SFLPhone::model()->getCall(call1),SFLPhone::model()->getCall(call2));
200
 
         return true;
201
 
      }
202
 
      else if ((SFLPhone::model()->getIndex(encodedCallId)->childCount()) && (!parent->childCount())) {
203
 
         kDebug() << "Call dropped on it's own conference (doing nothing)";
204
 
         return true;
205
 
      }
206
 
 
207
 
      kDebug() << "Call dropped on another call";
208
 
      SFLPhone::model()->createConferenceFromCall(SFLPhone::model()->getCall(encodedCallId),SFLPhone::model()->getCall(parent));
209
 
      return true;
210
 
   }
211
 
   return false;
212
 
}
213
 
 
214
 
///A string containing a call number is dropped on a call
215
 
bool CallView::phoneNumberToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
216
 
{
217
 
   Q_UNUSED(index)
218
 
   Q_UNUSED(action)
219
 
   QByteArray encodedPhoneNumber = data->data( MIME_PHONENUMBER );
220
 
   if (!QString(encodedPhoneNumber).isEmpty()) {
221
 
      Contact* contact = AkonadiBackend::getInstance()->getContactByPhone(encodedPhoneNumber);
222
 
      QString name;
223
 
      if (contact)
224
 
         name = contact->getFormattedName();
225
 
      else
226
 
         name = "Unknow";
227
 
      Call* call2 = SFLPhone::model()->addDialingCall(name, SFLPhone::model()->getCurrentAccountId());
228
 
      call2->appendText(QString(encodedPhoneNumber));
229
 
      if (!parent) {
230
 
         //Dropped on free space
231
 
         kDebug() << "Adding new dialing call";
232
 
      }
233
 
      else if (parent->childCount() || parent->parent()) {
234
 
         //Dropped on a conversation
235
 
         QTreeWidgetItem* call = (parent->parent())?parent->parent():parent;
236
 
         SFLPhone::model()->addParticipant(SFLPhone::model()->getCall(call),call2);
237
 
      }
238
 
      else {
239
 
         //Dropped on call
240
 
         call2->actionPerformed(CALL_ACTION_ACCEPT);
241
 
         int state = SFLPhone::model()->getCall(parent)->getState();
242
 
         if(state == CALL_STATE_INCOMING || state == CALL_STATE_DIALING || state == CALL_STATE_TRANSFER || state == CALL_STATE_TRANSF_HOLD) {
243
 
            SFLPhone::model()->getCall(parent)->actionPerformed(CALL_ACTION_ACCEPT);
244
 
         }
245
 
         SFLPhone::model()->createConferenceFromCall(call2,SFLPhone::model()->getCall(parent));
246
 
      }
247
 
   }
248
 
   return false;
249
 
}
250
 
 
251
 
///A contact ID is dropped on a call
252
 
bool CallView::contactToCall(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
253
 
{
254
 
   kDebug() << "contactToCall";
255
 
   Q_UNUSED( index  )
256
 
   Q_UNUSED( action )
257
 
   QByteArray encodedContact = data->data( MIME_CONTACT );
258
 
   if (!QString(encodedContact).isEmpty()) {
259
 
      Contact* contact = AkonadiBackend::getInstance()->getContactByUid(encodedContact);
260
 
      if (contact) {
261
 
         Call* call2;
262
 
         if (contact->getPhoneNumbers().count() == 1) {
263
 
            call2 = SFLPhone::model()->addDialingCall(contact->getFormattedName(), SFLPhone::model()->getCurrentAccountId());
264
 
            call2->appendText(contact->getPhoneNumbers()[0]->getNumber());
265
 
         }
266
 
         else if (contact->getPhoneNumbers().count() > 1) {
267
 
            bool ok = false;
268
 
            QHash<QString,QString> map;
269
 
            QStringList list;
270
 
            foreach (Contact::PhoneNumber* number, contact->getPhoneNumbers()) {
271
 
               map[number->getType()+" ("+number->getNumber()+")"] = number->getNumber();
272
 
               list << number->getType()+" ("+number->getNumber()+")";
273
 
            }
274
 
            QString result = QInputDialog::getItem (this, QString("Select phone number"), QString("This contact have many phone number, please select the one you wish to call"), list, 0, false, &ok);
275
 
            if (ok) {
276
 
               call2 = SFLPhone::model()->addDialingCall(contact->getFormattedName(), SFLPhone::model()->getCurrentAccountId());
277
 
               call2->appendText(map[result]);
278
 
            }
279
 
            else {
280
 
               kDebug() << "Operation cancelled";
281
 
               return false;
282
 
            }
283
 
         }
284
 
         else {
285
 
            kDebug() << "This contact have no valid phone number";
286
 
            return false;
287
 
         }
288
 
         if (!parent) {
289
 
            //Dropped on free space
290
 
            kDebug() << "Adding new dialing call";
291
 
         }
292
 
         else if (parent->childCount() || parent->parent()) {
293
 
            //Dropped on a conversation
294
 
            QTreeWidgetItem* call = (parent->parent())?parent->parent():parent;
295
 
            SFLPhone::model()->addParticipant(SFLPhone::model()->getCall(call),call2);
296
 
         }
297
 
         else {
298
 
            //Dropped on call
299
 
            call2->actionPerformed(CALL_ACTION_ACCEPT);
300
 
            int state = SFLPhone::model()->getCall(parent)->getState();
301
 
            if(state == CALL_STATE_INCOMING || state == CALL_STATE_DIALING || state == CALL_STATE_TRANSFER || state == CALL_STATE_TRANSF_HOLD) {
302
 
               SFLPhone::model()->getCall(parent)->actionPerformed(CALL_ACTION_ACCEPT);
303
 
            }
304
 
            SFLPhone::model()->createConferenceFromCall(call2,SFLPhone::model()->getCall(parent));
305
 
         }
306
 
      }
307
 
   }
308
 
   return false;
309
 
}
310
 
 
311
 
///Action performed when an item is dropped on the TreeView
312
 
bool CallView::dropMimeData(QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action)
313
 
{
314
 
   Q_UNUSED(index)
315
 
   Q_UNUSED(action)
316
 
 
317
 
   QByteArray encodedCallId      = data->data( MIME_CALLID      );
318
 
   QByteArray encodedPhoneNumber = data->data( MIME_PHONENUMBER );
319
 
   QByteArray encodedContact     = data->data( MIME_CONTACT     );
320
 
 
321
 
   if (!QString(encodedCallId).isEmpty()) {
322
 
      kDebug() << "CallId dropped"<< QString(encodedCallId);
323
 
      callToCall(parent, index, data, action);
324
 
   }
325
 
   else if (!QString(encodedPhoneNumber).isEmpty()) {
326
 
      kDebug() << "PhoneNumber dropped"<< QString(encodedPhoneNumber);
327
 
      phoneNumberToCall(parent, index, data, action);
328
 
   }
329
 
   else if (!QString(encodedContact).isEmpty()) {
330
 
      kDebug() << "Contact dropped"<< QString(encodedContact);
331
 
      contactToCall(parent, index, data, action);
332
 
   }
333
 
   return false;
334
 
}
335
 
 
336
 
///Encode data to be tranported during the drag n' drop operation
337
 
QMimeData* CallView::mimeData( const QList<QTreeWidgetItem *> items) const
338
 
{
339
 
   kDebug() << "A call is being dragged";
340
 
   if (items.size() < 1) {
341
 
      return NULL;
342
 
   }
343
 
 
344
 
   QMimeData *mimeData = new QMimeData();
345
 
 
346
 
   //Call ID for internal call merging and spliting
347
 
   if (SFLPhone::model()->getCall(items[0])->isConference()) {
348
 
      mimeData->setData(MIME_CALLID, SFLPhone::model()->getCall(items[0])->getConfId().toAscii());
349
 
   }
350
 
   else {
351
 
      mimeData->setData(MIME_CALLID, SFLPhone::model()->getCall(items[0])->getCallId().toAscii());
352
 
   }
353
 
 
354
 
   //Plain text for other applications
355
 
   mimeData->setData(MIME_PLAIN_TEXT, QString(SFLPhone::model()->getCall(items[0])->getPeerName()+"\n"+SFLPhone::model()->getCall(items[0])->getPeerPhoneNumber()).toAscii());
356
 
 
357
 
   //TODO Comment this line if you don't want to see ugly artefact, but the caller details will not be visible while dragged
358
 
   items[0]->setText(0, SFLPhone::model()->getCall(items[0])->getPeerName() + "\n" + SFLPhone::model()->getCall(items[0])->getPeerPhoneNumber());
359
 
   return mimeData;
360
 
}
361
 
 
362
 
 
363
 
/*****************************************************************************
364
 
 *                                                                           *
365
 
 *                            Call related code                              *
366
 
 *                                                                           *
367
 
 ****************************************************************************/
368
 
 
369
 
///Add a call in the model structure, the call must exist before being added to the model
370
 
Call* CallView::addCall(Call* call, Call* parent)
371
 
{
372
 
   QTreeWidgetItem* callItem = new QTreeWidgetItem();
373
 
   SFLPhone::model()->updateIndex(call,callItem);
374
 
   insertItem(callItem,parent);
375
 
 
376
 
   setCurrentItem(callItem);
377
 
 
378
 
   connect(call, SIGNAL(isOver(Call*)), this, SLOT(destroyCall(Call*)));
379
 
   return call;
380
 
}
381
 
 
382
 
///Transfer a call
383
 
void CallView::transfer()
384
 
{
385
 
   if (m_pCallPendingTransfer) {
386
 
      SFLPhone::model()->transfer(m_pCallPendingTransfer,m_pTransferLE->text());
387
 
      m_pCallPendingTransfer = 0;
388
 
      m_pTransferLE->clear();
389
 
      m_pTransferOverlay->setVisible(false);
390
 
   }
391
 
}
392
 
 
393
 
/*****************************************************************************
394
 
 *                                                                           *
395
 
 *                            View related code                              *
396
 
 *                                                                           *
397
 
 ****************************************************************************/
398
 
 
399
 
///Show the transfer overlay
400
 
void CallView::showTransferOverlay(Call* call)
401
 
{
402
 
   if (!m_pTransferOverlay) {
403
 
      kDebug() << "Creating overlay";
404
 
   }
405
 
   m_pTransferOverlay->setVisible(true);
406
 
   m_pCallPendingTransfer = call;
407
 
   m_pActiveOverlay = m_pTransferOverlay;
408
 
   m_pTransferLE->setFocus();
409
 
   connect(call,SIGNAL(changed()),this,SLOT(hideOverlay()));
410
 
}
411
 
 
412
 
///Is there an active overlay
413
 
bool CallView::haveOverlay()
414
 
{
415
 
   return (m_pActiveOverlay && m_pActiveOverlay->isVisible());
416
 
}
417
 
 
418
 
///Remove the active overlay
419
 
void CallView::hideOverlay()
420
 
{
421
 
   if (m_pActiveOverlay)
422
 
      m_pActiveOverlay->setVisible(false);
423
 
   m_pActiveOverlay = 0;
424
 
}
425
 
 
426
 
///Be sure the size of the overlay stay the same
427
 
void CallView::resizeEvent (QResizeEvent *e)
428
 
{
429
 
   if (m_pTransferOverlay)
430
 
      m_pTransferOverlay->resize(size());
431
 
   QTreeWidget::resizeEvent(e);
432
 
}
433
 
 
434
 
///Set the TreeView header text
435
 
void CallView::setTitle(const QString& title)
436
 
{
437
 
   headerItem()->setText(0,title);
438
 
}
439
 
 
440
 
///Select an item in the TreeView
441
 
bool CallView::selectItem(Call* item)
442
 
{
443
 
   if (SFLPhone::model()->getIndex(item)) {
444
 
      setCurrentItem(SFLPhone::model()->getIndex(item));
445
 
      return true;
446
 
   }
447
 
   else
448
 
      return false;
449
 
}
450
 
 
451
 
///Return the current item
452
 
Call* CallView::getCurrentItem()
453
 
{
454
 
   if (currentItem() && SFLPhone::model()->getCall(QTreeWidget::currentItem()))
455
 
      return SFLPhone::model()->getCall(QTreeWidget::currentItem());
456
 
   else
457
 
      return false;
458
 
}
459
 
 
460
 
///Remove a TreeView item and delete it
461
 
bool CallView::removeItem(Call* item)
462
 
{
463
 
   if (indexOfTopLevelItem(SFLPhone::model()->getIndex(item)) != -1) {
464
 
      QTreeWidgetItem* parent = itemAt(indexOfTopLevelItem(SFLPhone::model()->getIndex(item)),0);
465
 
      removeItemWidget(SFLPhone::model()->getIndex(item),0);
466
 
      if (parent->childCount() == 0) //TODO this have to be done in the daemon, not here, but oops still happen too often to ignore
467
 
         removeItemWidget(parent,0);
468
 
      return true;
469
 
   }
470
 
   else
471
 
      return false;
472
 
}
473
 
 
474
 
///Return the TreeView, this
475
 
QWidget* CallView::getWidget()
476
 
{
477
 
   return this;
478
 
}
479
 
 
480
 
///Convenience wrapper around extractItem(QTreeWidgetItem*)
481
 
QTreeWidgetItem* CallView::extractItem(const QString& callId)
482
 
{
483
 
   QTreeWidgetItem* currentItem = SFLPhone::model()->getIndex(callId);
484
 
   return extractItem(currentItem);
485
 
}
486
 
 
487
 
///Extract an item from the TreeView and return it, the item is -not- deleted
488
 
QTreeWidgetItem* CallView::extractItem(QTreeWidgetItem* item)
489
 
{
490
 
   QTreeWidgetItem* parentItem = item->parent();
491
 
 
492
 
   if (parentItem) {
493
 
      if ((indexOfTopLevelItem(parentItem) == -1 ) || (parentItem->indexOfChild(item) == -1)) {
494
 
         kDebug() << "The conversation does not exist";
495
 
         return 0;
496
 
      }
497
 
 
498
 
      QTreeWidgetItem* toReturn = parentItem->takeChild(parentItem->indexOfChild(item));
499
 
 
500
 
      return toReturn;
501
 
   }
502
 
   else
503
 
      return takeTopLevelItem(indexOfTopLevelItem(item));
504
 
}
505
 
 
506
 
///Convenience wrapper around insertItem(QTreeWidgetItem*, QTreeWidgetItem*)
507
 
CallTreeItem* CallView::insertItem(QTreeWidgetItem* item, Call* parent)
508
 
{
509
 
   return insertItem(item,(parent)?SFLPhone::model()->getIndex(parent):0);
510
 
}
511
 
 
512
 
///Insert a TreeView item in the TreeView as child of parent or as a top level item, also restore the item Widget
513
 
CallTreeItem* CallView::insertItem(QTreeWidgetItem* item, QTreeWidgetItem* parent)
514
 
{
515
 
   if (!item) {
516
 
      kDebug() << "This is not a valid call";
517
 
      return 0;
518
 
   }
519
 
 
520
 
   if (!parent)
521
 
      insertTopLevelItem(0,item);
522
 
   else
523
 
      parent->addChild(item);
524
 
 
525
 
   CallTreeItem* callItem = new CallTreeItem();
526
 
   connect(callItem, SIGNAL(showChilds(CallTreeItem*)), this, SLOT(showDropOptions(CallTreeItem*)));
527
 
   connect(callItem, SIGNAL(askTransfer(Call*)), this, SLOT(showTransferOverlay(Call*)));
528
 
   connect(callItem, SIGNAL(transferDropEvent(Call*,QMimeData*)), this, SLOT(transferDropEvent(Call*,QMimeData*)));
529
 
   connect(callItem, SIGNAL(conversationDropEvent(Call*,QMimeData*)), this, SLOT(conversationDropEvent(Call*,QMimeData*)));
530
 
 
531
 
   SFLPhone::model()->updateWidget(SFLPhone::model()->getCall(item), callItem);
532
 
   callItem->setCall(SFLPhone::model()->getCall(item));
533
 
 
534
 
   setItemWidget(item,0,callItem);
535
 
 
536
 
   expandAll();
537
 
   return callItem;
538
 
}
539
 
 
540
 
///Remove a call from the interface
541
 
void CallView::destroyCall(Call* toDestroy)
542
 
{
543
 
   if (SFLPhone::model()->getIndex(toDestroy) == currentItem())
544
 
      setCurrentItem(0);
545
 
 
546
 
   if (!SFLPhone::model()->getIndex(toDestroy))
547
 
       kDebug() << "Call not found";
548
 
   else if (indexOfTopLevelItem(SFLPhone::model()->getIndex(toDestroy)) != -1)
549
 
      takeTopLevelItem(indexOfTopLevelItem(SFLPhone::model()->getIndex(toDestroy)));
550
 
   else if (SFLPhone::model()->getIndex(toDestroy)->parent()) {
551
 
      QTreeWidgetItem* parent = SFLPhone::model()->getIndex(toDestroy)->parent();
552
 
      SFLPhone::model()->getIndex(toDestroy)->parent()->removeChild(SFLPhone::model()->getIndex(toDestroy));
553
 
      if (parent->childCount() == 0) /*This should never happen, but it does*/
554
 
         takeTopLevelItem(indexOfTopLevelItem(parent));
555
 
      else if (parent->childCount() == 1) {
556
 
         addTopLevelItem(extractItem(parent->child(0)));
557
 
         takeTopLevelItem(indexOfTopLevelItem(parent));
558
 
      } //TODO make sure it just never happen and remove this logic code
559
 
   }
560
 
   else
561
 
      kDebug() << "Call not found";
562
 
}
563
 
 
564
 
/// @todo Remove the text partially covering the TreeView item widget when it is being dragged, a beter implementation is needed
565
 
void CallView::clearArtefact(QTreeWidgetItem* item)
566
 
{
567
 
   if (item)
568
 
      item->setText(0,"");
569
 
}
570
 
 
571
 
 
572
 
/*****************************************************************************
573
 
 *                                                                           *
574
 
 *                           Event related code                              *
575
 
 *                                                                           *
576
 
 ****************************************************************************/
577
 
 
578
 
void CallView::itemDoubleClicked(QTreeWidgetItem* item, int column) {
579
 
   Q_UNUSED(column)
580
 
   kDebug() << "Item doubleclicked" << SFLPhone::model()->getCall(item)->getState();
581
 
   switch(SFLPhone::model()->getCall(item)->getState()) {
582
 
      case CALL_STATE_INCOMING:
583
 
         SFLPhone::model()->getCall(item)->actionPerformed(CALL_ACTION_ACCEPT);
584
 
         break;
585
 
      case CALL_STATE_HOLD:
586
 
         SFLPhone::model()->getCall(item)->actionPerformed(CALL_ACTION_HOLD);
587
 
         break;
588
 
      case CALL_STATE_DIALING:
589
 
         SFLPhone::model()->getCall(item)->actionPerformed(CALL_ACTION_ACCEPT);
590
 
         break;
591
 
      default:
592
 
         kDebug() << "Double clicked an item with no action on double click.";
593
 
    }
594
 
}
595
 
 
596
 
void CallView::itemClicked(QTreeWidgetItem* item, int column) {
597
 
   Q_UNUSED(column)
598
 
   emit itemChanged(SFLPhone::model()->getCall(item));
599
 
   kDebug() << "Item clicked";
600
 
}
601
 
 
602
 
 
603
 
/*****************************************************************************
604
 
 *                                                                           *
605
 
 *                         Conference related code                           *
606
 
 *                                                                           *
607
 
 ****************************************************************************/
608
 
 
609
 
///Add a new conference, get the call list and update the interface as needed
610
 
Call* CallView::addConference(Call* conf)
611
 
{
612
 
   kDebug() << "Conference created";
613
 
   Call* newConf =  conf;//SFLPhone::model()->addConference(confID);//TODO ELV?
614
 
 
615
 
   QTreeWidgetItem* confItem = new QTreeWidgetItem();
616
 
   SFLPhone::model()->updateIndex(conf,confItem);
617
 
 
618
 
   insertItem(confItem,(QTreeWidgetItem*)0);
619
 
 
620
 
 
621
 
   setCurrentItem(confItem);
622
 
 
623
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
624
 
   QStringList callList = callManager.getParticipantList(conf->getConfId());
625
 
 
626
 
   foreach (QString callId, callList) {
627
 
      kDebug() << "Adding " << callId << "to the conversation";
628
 
      insertItem(extractItem(SFLPhone::model()->getIndex(callId)),confItem);
629
 
   }
630
 
 
631
 
   Q_ASSERT_X(confItem->childCount() == 0, "add conference","Conference created, but without any participants");
632
 
   return newConf;
633
 
}
634
 
 
635
 
///Executed when the daemon signal a modification in an existing conference. Update the call list and update the TreeView
636
 
bool CallView::conferenceChanged(Call* conf)
637
 
{
638
 
   kDebug() << "Conference changed";
639
 
   //if (!SFLPhone::model()->conferenceChanged(confId, state))
640
 
   //  return false;
641
 
 
642
 
   CallManagerInterface& callManager = CallManagerInterfaceSingleton::getInstance();
643
 
   QStringList callList = callManager.getParticipantList(conf->getConfId());
644
 
 
645
 
   QList<QTreeWidgetItem*> buffer;
646
 
   foreach (QString callId, callList) {
647
 
      if (SFLPhone::model()->getCall(callId)) {
648
 
         QTreeWidgetItem* item3 = extractItem(SFLPhone::model()->getIndex(callId));
649
 
         insertItem(item3, SFLPhone::model()->getIndex(conf));
650
 
         buffer << SFLPhone::model()->getIndex(callId);
651
 
      }
652
 
      else
653
 
         kDebug() << "Call " << callId << " does not exist";
654
 
   }
655
 
 
656
 
   if (SFLPhone::model()->getIndex(conf)) /*Can happen is the daemon crashed*/
657
 
      for (int j =0; j < SFLPhone::model()->getIndex(conf)->childCount();j++) {
658
 
         if (buffer.indexOf(SFLPhone::model()->getIndex(conf)->child(j)) == -1)
659
 
            insertItem(extractItem(SFLPhone::model()->getIndex(conf)->child(j)));
660
 
      }
661
 
 
662
 
   Q_ASSERT_X(SFLPhone::model()->getIndex(conf)->childCount() == 0,"changind conference","A conference can't have no participants");
663
 
 
664
 
   return true;
665
 
}
666
 
 
667
 
///Remove a conference from the model and the TreeView
668
 
void CallView::conferenceRemoved(Call* conf)
669
 
{
670
 
   kDebug() << "Attempting to remove conference";
671
 
   QTreeWidgetItem* idx = SFLPhone::model()->getIndex(conf);
672
 
   if (idx) {
673
 
   while (idx->childCount()) {
674
 
      insertItem(extractItem(SFLPhone::model()->getIndex(conf)->child(0)));
675
 
   }
676
 
   takeTopLevelItem(indexOfTopLevelItem(SFLPhone::model()->getIndex(conf)));
677
 
   //SFLPhone::model()->conferenceRemoved(confId);
678
 
   kDebug() << "Conference removed";
679
 
   }
680
 
   else {
681
 
      kDebug() << "Conference not found";
682
 
   }
683
 
}
684
 
 
685
 
///Clear the list of old calls //TODO Clear them from the daemon
686
 
void CallView::clearHistory()
687
 
{
688
 
   //SFLPhone::model()->getHistory().clear();
689
 
}
690
 
 
691
 
///Redirect keypresses to parent
692
 
void CallView::keyPressEvent(QKeyEvent* event) {
693
 
   SFLPhone::app()->view()->keyPressEvent(event);
694
 
}
695
 
 
696
 
 
697
 
/*****************************************************************************
698
 
 *                                                                           *
699
 
 *                                 Overlay                                   *
700
 
 *                                                                           *
701
 
 ****************************************************************************/
702
 
 
703
 
///Constructor
704
 
CallViewOverlay::CallViewOverlay(QWidget* parent) : QWidget(parent),m_pIcon(0),m_pTimer(0),m_enabled(true),m_black("black")
705
 
{
706
 
   m_black.setAlpha(75);
707
 
}
708
 
 
709
 
///Add a widget (usually an icon) in the corner
710
 
void CallViewOverlay::setCornerWidget(QWidget* wdg) {
711
 
   wdg->setParent      ( this                       );
712
 
   wdg->setMinimumSize ( 100         , 100          );
713
 
   wdg->resize         ( 100         , 100          );
714
 
   wdg->move           ( width()-100 , height()-100 );
715
 
   m_pIcon = wdg;
716
 
}
717
 
 
718
 
///Overload the setVisible method to trigger the timer
719
 
void CallViewOverlay::setVisible(bool enabled) {
720
 
   if (m_enabled != enabled) {
721
 
      if (m_pTimer) {
722
 
         m_pTimer->stop();
723
 
         disconnect(m_pTimer);
724
 
      }
725
 
      m_pTimer = new QTimer(this); //TODO LEAK?
726
 
      connect(m_pTimer, SIGNAL(timeout()), this, SLOT(changeVisibility()));
727
 
      m_step = 0;
728
 
      m_black.setAlpha(0);
729
 
      repaint();
730
 
      m_pTimer->start(10);
731
 
   }
732
 
   m_enabled = enabled;
733
 
   QWidget::setVisible(enabled);
734
 
}
735
 
 
736
 
///How to paint the overlay
737
 
void CallViewOverlay::paintEvent(QPaintEvent* event) {
738
 
   Q_UNUSED(event)
739
 
   QPainter customPainter(this);
740
 
   customPainter.fillRect(rect(),m_black);
741
 
}
742
 
 
743
 
///Be sure the event is always the right size
744
 
void CallViewOverlay::resizeEvent(QResizeEvent *e) {
745
 
   Q_UNUSED(e)
746
 
   if (m_pIcon) {
747
 
      m_pIcon->setMinimumSize(100,100);
748
 
      m_pIcon->move(width()-100,height()-100);
749
 
   }
750
 
}
751
 
 
752
 
///Step by step animation to fade in/out
753
 
void CallViewOverlay::changeVisibility() {
754
 
   m_step++;
755
 
   m_black.setAlpha(0.1*m_step*m_step);
756
 
   repaint();
757
 
   if (m_step >= 35)
758
 
      m_pTimer->stop();
759
 
}
 
 
b'\\ No newline at end of file'