blob: ee4dd34097c47e5a5cb2fc0779cf94cfa0c6ad8e [file] [log] [blame]
Edric Milaret627500d2015-03-27 16:41:40 -04001/***************************************************************************
Edric Milaret4bba46d2015-04-29 16:33:38 -04002 * Copyright (C) 2015 by Savoir-Faire Linux *
Edric Milaret627500d2015-03-27 16:41:40 -04003 * Author: Edric Ladent Milaret <edric.ladent-milaret@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
19#include "callwidget.h"
20#include "ui_callwidget.h"
21
Edric Milaret53f57b62015-05-11 11:02:17 -040022#include <memory>
Edric Milaret627500d2015-03-27 16:41:40 -040023
Edric Milaret627500d2015-03-27 16:41:40 -040024#include "audio/settings.h"
25#include "personmodel.h"
26#include "fallbackpersoncollection.h"
Edric Milaret67007d12015-05-07 09:40:09 -040027#include "categorizedcontactmodel.h"
Edric Milaret6a642e22015-05-27 15:06:30 -040028#include "localhistorycollection.h"
Edric Milaret1b197eb2015-06-01 15:09:56 -040029#include "media/text.h"
30#include "media/recording.h"
31#include "media/textrecording.h"
Edric Milaret627500d2015-03-27 16:41:40 -040032
Edric Milaret559bda52015-04-29 17:02:31 -040033#include "wizarddialog.h"
Edric Milaret83b248c2015-06-02 11:42:23 -040034#include "windowscontactbackend.h"
Edric Milaret627500d2015-03-27 16:41:40 -040035
36CallWidget::CallWidget(QWidget *parent) :
37 NavWidget(Main ,parent),
Edric Milaret7d40a4a2015-05-13 13:01:15 -040038 ui(new Ui::CallWidget),
39 menu_(new QMenu())
Edric Milaret627500d2015-03-27 16:41:40 -040040{
41 ui->setupUi(this);
42
Edric Milaret627500d2015-03-27 16:41:40 -040043 ui->callInvite->setVisible(false);
Edric Milareta9f937f2015-06-01 17:10:34 -040044 ui->videoWidget->setVisible(false);
Edric Milaret627500d2015-03-27 16:41:40 -040045
Edric Milaret6456baa2015-05-21 12:18:07 -040046 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -040047 videoRenderer_ = nullptr;
48
Edric Milaret3aca8e32015-06-12 10:01:40 -040049 connect(ui->videoWidget, SIGNAL(setChatVisibility(bool)),
50 ui->instantMessagingWidget, SLOT(setVisible(bool)));
51
Edric Milaretd8528fa2015-07-07 14:13:51 -040052 ui->spinnerWidget->hide();
Edric Milaretc7ab5502015-06-15 11:18:02 -040053 spinner_ = new QMovie(":/images/spinner.gif");
54 if (spinner_->isValid()) {
55 ui->spinnerLabel->setMovie(spinner_);
56 }
57
Edric Milaret627500d2015-03-27 16:41:40 -040058 try {
59 callModel_ = CallModel::instance();
60
61 connect(callModel_, SIGNAL(incomingCall(Call*)),
62 this, SLOT(callIncoming(Call*)));
63 connect(callModel_, SIGNAL(callAdded(Call*,Call*)),
64 this, SLOT(addedCall(Call*, Call*)));
65 connect(callModel_, SIGNAL(callStateChanged(Call*, Call::State)),
66 this, SLOT(callStateChanged(Call*, Call::State)));
67
Edric Milarete5afb072015-06-02 16:45:44 -040068 connect(AccountModel::instance(),
69 SIGNAL(accountStateChanged(Account*,Account::RegistrationState)),
70 this,
71 SLOT(checkRegistrationState(Account*,Account::RegistrationState)));
72
Edric Milaret67007d12015-05-07 09:40:09 -040073 connect(AccountModel::instance()
74 , SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>))
75 , this
76 , SLOT(findRingAccount(QModelIndex, QModelIndex, QVector<int>)));
77
Edric Milaret627500d2015-03-27 16:41:40 -040078 ui->callList->setModel(callModel_);
Edric Milaret029b95a2015-06-09 09:51:44 -040079 ui->callList->setSelectionModel(callModel_->selectionModel());
Edric Milaret627500d2015-03-27 16:41:40 -040080
81 CategorizedHistoryModel::instance()->
Edric Milaret6a642e22015-05-27 15:06:30 -040082 addCollection<LocalHistoryCollection>(LoadOptions::FORCE_ENABLED);
Edric Milaret627500d2015-03-27 16:41:40 -040083
Edric Milaret67007d12015-05-07 09:40:09 -040084 PersonModel::instance()->
85 addCollection<FallbackPersonCollection>(LoadOptions::FORCE_ENABLED);
86
87 PersonModel::instance()->
88 addCollection<WindowsContactBackend>(LoadOptions::FORCE_ENABLED);
89
Edric Milaret12353822015-05-14 14:41:09 -040090 ui->historyList->setModel(CategorizedHistoryModel::SortedProxy::instance()->model());
91 CategorizedHistoryModel::SortedProxy::instance()->model()->sort(0, Qt::DescendingOrder);
Edric Milaret53f57b62015-05-11 11:02:17 -040092 ui->historyList->setHeaderHidden(true);
Edric Milaret01f23842015-06-22 14:46:01 -040093 historyDelegate_ = new HistoryDelegate();
94 ui->historyList->setItemDelegate(historyDelegate_);
Edric Milaret77dd6982015-07-07 16:45:41 -040095
96 connect(CategorizedHistoryModel::SortedProxy::instance()->model(), &QSortFilterProxyModel::layoutChanged, [=]() {
97 auto idx = CategorizedHistoryModel::SortedProxy::instance()->model()->index(0,0);
98 if (idx.isValid())
99 ui->historyList->setExpanded(idx, true);
100 });
101
Edric Milaret53f57b62015-05-11 11:02:17 -0400102
Edric Milaret12353822015-05-14 14:41:09 -0400103 ui->sortComboBox->setModel(CategorizedHistoryModel::SortedProxy::instance()->categoryModel());
Edric Milaret7d40a4a2015-05-13 13:01:15 -0400104
Edric Milaret67007d12015-05-07 09:40:09 -0400105 CategorizedContactModel::instance()->setSortAlphabetical(false);
106 ui->contactView->setModel(CategorizedContactModel::instance());
Edric Milaret01f23842015-06-22 14:46:01 -0400107 contactDelegate_ = new ContactDelegate();
108 ui->contactView->setItemDelegate(contactDelegate_);
Edric Milaret53f57b62015-05-11 11:02:17 -0400109
Edric Milaret627500d2015-03-27 16:41:40 -0400110 findRingAccount();
111
112 } catch (...) {
113 qDebug() << "INIT ERROR";
114 }
115}
116
117CallWidget::~CallWidget()
118{
119 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400120 delete spinner_;
121 delete menu_;
Edric Milaret01f23842015-06-22 14:46:01 -0400122 delete historyDelegate_;
123 delete contactDelegate_;
Edric Milaret627500d2015-03-27 16:41:40 -0400124}
125
126void
Edric Milaret67007d12015-05-07 09:40:09 -0400127CallWidget::findRingAccount(QModelIndex idx1, QModelIndex idx2, QVector<int> vec)
128{
129 Q_UNUSED(idx1)
130 Q_UNUSED(idx2)
131 Q_UNUSED(vec)
132
133 auto a_count = AccountModel::instance()->rowCount();
134 auto found = false;
135 for (int i = 0; i < a_count; ++i) {
136 auto idx = AccountModel::instance()->index(i, 0);
137 auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
138 if ((Account::Protocol)protocol.toUInt() == Account::Protocol::RING) {
139 auto username = idx.data(static_cast<int>(Account::Role::Username));
140 ui->ringIdLabel->setText(
Edric Milaret68779c42015-07-09 16:53:03 -0400141 "Your Ring ID: " + username.toString());
Edric Milaret67007d12015-05-07 09:40:09 -0400142 found = true;
143 return;
144 }
145 }
146 if (not found){
147 ui->ringIdLabel->setText("NO RING ACCOUNT FOUND");
148 }
149}
150
151void
Edric Milarete5afb072015-06-02 16:45:44 -0400152CallWidget::checkRegistrationState(Account *account,
153 Account::RegistrationState state)
154{
155 Q_UNUSED(account);
156
157 QPixmap pm(20,20);
158 pm.fill();
159 QPainter p(&pm);
160 QPen pen(Qt::black, 2);
161 p.setPen(pen);
162 p.setRenderHint(QPainter::Antialiasing, true);
163
164 switch(state) {
165 case Account::RegistrationState::ERROR:
166 p.setBrush(Qt::red);
167 break;
168 case Account::RegistrationState::TRYING:
169 p.setBrush(Qt::yellow);
170 break;
171 case Account::RegistrationState::READY:
Edric Milaret023e8f12015-07-07 14:52:40 -0400172 {
Edric Milarete5afb072015-06-02 16:45:44 -0400173 p.setBrush(Qt::green);
174 auto a_count = AccountModel::instance()->rowCount();
175 for (int i = 0; i < a_count; ++i) {
176 auto idx = AccountModel::instance()->index(i, 0);
177 auto stateAcc = idx.data(
178 static_cast<int>(Account::Role::RegistrationState));
179 if (stateAcc.value<Account::RegistrationState>()
180 != Account::RegistrationState::READY) {
181 checkRegistrationState(nullptr,
182 stateAcc.value<Account::RegistrationState>());
183 return;
184 }
185 }
Edric Milaret023e8f12015-07-07 14:52:40 -0400186 }
187 break;
188 default:
Edric Milarete5afb072015-06-02 16:45:44 -0400189 break;
190 }
191 p.drawEllipse(3, 3, 16, 16);
192 ui->accountStateHintLabel->setPixmap(pm);
193 ui->accountStateHintLabel->show();
194}
195
196void
Edric Milaret67007d12015-05-07 09:40:09 -0400197CallWidget::findRingAccount()
198{
Edric Milaret559bda52015-04-29 17:02:31 -0400199
Edric Milaret627500d2015-03-27 16:41:40 -0400200 auto a_count = AccountModel::instance()->rowCount();
201 auto found = false;
202 for (int i = 0; i < a_count; ++i) {
203 auto idx = AccountModel::instance()->index(i, 0);
204 auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
205 if ((Account::Protocol)protocol.toUInt() == Account::Protocol::RING) {
Edric Milaret68779c42015-07-09 16:53:03 -0400206 auto account = AccountModel::instance()->getAccountByModelIndex(idx);
207 if (account->displayName().isEmpty())
208 account->displayName() = account->alias();
209 auto username = account->username();
Edric Milaret627500d2015-03-27 16:41:40 -0400210 ui->ringIdLabel->setText(
Edric Milaret68779c42015-07-09 16:53:03 -0400211 "Your Ring ID: " + username);
Edric Milaret627500d2015-03-27 16:41:40 -0400212 found = true;
213 return;
214 }
215 }
216 if (!found) {
Edric Milaret559bda52015-04-29 17:02:31 -0400217 WizardDialog *wizardDialog = new WizardDialog();
218 wizardDialog->exec();
219 delete wizardDialog;
Edric Milaret627500d2015-03-27 16:41:40 -0400220 }
221}
222
223void
224CallWidget::callIncoming(Call *call)
225{
Edric Milaret435cdfc2015-06-01 16:15:50 -0400226 if (!call->account()->isAutoAnswer()) {
Edric Milaretd9ebe232015-06-15 10:44:49 -0400227 ui->callLabel->setText("Call from " + call->formattedName());
Edric Milaret627500d2015-03-27 16:41:40 -0400228 ui->callInvite->setVisible(true);
Edric Milaret435cdfc2015-06-01 16:15:50 -0400229 ui->callInvite->raise();
230 }
Edric Milaret6456baa2015-05-21 12:18:07 -0400231 setActualCall(call);
Edric Milaret627500d2015-03-27 16:41:40 -0400232}
233
234void
235CallWidget::on_acceptButton_clicked()
236{
237 if (actualCall_ != nullptr)
Edric Milaret53f57b62015-05-11 11:02:17 -0400238 actualCall_->performAction(Call::Action::ACCEPT);
Edric Milaret627500d2015-03-27 16:41:40 -0400239 ui->callInvite->setVisible(false);
240}
241
242void
243CallWidget::on_refuseButton_clicked()
244{
245 if (actualCall_ == nullptr)
246 return;
247 actualCall_->performAction(Call::Action::REFUSE);
Edric Milaret6456baa2015-05-21 12:18:07 -0400248 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -0400249 ui->callInvite->setVisible(false);
250}
251
252void
Edric Milaret627500d2015-03-27 16:41:40 -0400253CallWidget::addedCall(Call* call, Call* parent) {
254 Q_UNUSED(parent);
255 if (call->direction() == Call::Direction::OUTGOING) {
Edric Milaretc7ab5502015-06-15 11:18:02 -0400256 displaySpinner(true);
Edric Milaret6456baa2015-05-21 12:18:07 -0400257 setActualCall(call);
Edric Milaret627500d2015-03-27 16:41:40 -0400258 }
259}
260
261void
Edric Milaret67007d12015-05-07 09:40:09 -0400262CallWidget::callStateChanged(Call* call, Call::State previousState)
263{
Edric Milaret627500d2015-03-27 16:41:40 -0400264 Q_UNUSED(previousState)
Edric Milaretb5b49072015-05-08 11:56:07 -0400265 if (call == nullptr)
266 return;
Edric Milaret627500d2015-03-27 16:41:40 -0400267 ui->callList->setCurrentIndex(callModel_->getIndex(actualCall_));
Edric Milaretc7ab5502015-06-15 11:18:02 -0400268 if (call->state() == Call::State::OVER
269 || call->state() == Call::State::ERROR
270 || call->state() == Call::State::FAILURE
271 || call->state() == Call::State::ABORTED) {
Edric Milaret6456baa2015-05-21 12:18:07 -0400272 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -0400273 ui->videoWidget->hide();
Edric Milaretc7ab5502015-06-15 11:18:02 -0400274 displaySpinner(false);
Edric Milaret4f630842015-06-11 16:10:29 -0400275 auto onHoldCall = callModel_->getActiveCalls().first();
Edric Milaretd8528fa2015-07-07 14:13:51 -0400276 if (onHoldCall != nullptr && onHoldCall->state() == Call::State::HOLD) {
Edric Milaret4f630842015-06-11 16:10:29 -0400277 setActualCall(onHoldCall);
278 onHoldCall->performAction(Call::Action::HOLD);
279 }
280 } else if (call->state() == Call::State::HOLD) {
281 ui->videoWidget->hide();
Edric Milaret53f57b62015-05-11 11:02:17 -0400282 } else if (call->state() == Call::State::CURRENT) {
Edric Milaretc7ab5502015-06-15 11:18:02 -0400283 displaySpinner(false);
Edric Milaret627500d2015-03-27 16:41:40 -0400284 ui->videoWidget->show();
Edric Milaret627500d2015-03-27 16:41:40 -0400285 }
Edric Milaretf25d3bd2015-06-04 10:23:24 -0400286 ui->callStateLabel->setText("Call State : " + call->toHumanStateName());
Edric Milaret627500d2015-03-27 16:41:40 -0400287}
288
289void
290CallWidget::on_callList_activated(const QModelIndex &index)
291{
292 Call *callSelected = callModel_->getCall(index);
293 if (actualCall_ != nullptr) {
294 if (callSelected == actualCall_)
295 return;
Edric Milaret72c406d2015-04-28 13:23:54 -0400296 ui->videoWidget->hide();
Edric Milaret627500d2015-03-27 16:41:40 -0400297 actualCall_->performAction(Call::Action::HOLD);
298 }
Edric Milaret6456baa2015-05-21 12:18:07 -0400299 setActualCall(callSelected);
Edric Milaret627500d2015-03-27 16:41:40 -0400300 actualCall_->performAction(Call::Action::HOLD);
Edric Milaret72c406d2015-04-28 13:23:54 -0400301 ui->videoWidget->show();
Edric Milaret627500d2015-03-27 16:41:40 -0400302}
303
304void
Edric Milaret627500d2015-03-27 16:41:40 -0400305CallWidget::atExit() {
306
307}
Edric Milaret67007d12015-05-07 09:40:09 -0400308
309void
310CallWidget::on_contactView_doubleClicked(const QModelIndex &index)
311{
Edric Milaret67007d12015-05-07 09:40:09 -0400312 QString uri;
313
Edric Milaret7d40a4a2015-05-13 13:01:15 -0400314 auto var = index.child(0,0).data(
315 static_cast<int>(Person::Role::Object));
316 if (var.isValid()) {
317 Person* person = var.value<Person*>();
318 if (person->phoneNumbers().size() > 0) {
319 uri = person->phoneNumbers().at(0)->uri();
Edric Milaret67007d12015-05-07 09:40:09 -0400320 }
321 }
322 if (not uri.isEmpty()) {
323 auto outCall = CallModel::instance()->dialingCall(uri);
324 outCall->setDialNumber(uri);
325 outCall->performAction(Call::Action::ACCEPT);
326 }
327}
Edric Milaret53f57b62015-05-11 11:02:17 -0400328
Edric Milaret6456baa2015-05-21 12:18:07 -0400329void
330CallWidget::on_historyList_doubleClicked(const QModelIndex &index)
Edric Milaret53f57b62015-05-11 11:02:17 -0400331{
Edric Milaret12353822015-05-14 14:41:09 -0400332 if (not index.isValid())
333 return;
334
Edric Milaret53f57b62015-05-11 11:02:17 -0400335 QString number = index.model()->data(index, static_cast<int>(Call::Role::Number)).toString();
336 if (not number.isEmpty()) {
337 auto outCall = CallModel::instance()->dialingCall(number);
338 outCall->setDialNumber(number);
339 outCall->performAction(Call::Action::ACCEPT);
340 }
341}
Edric Milaret6456baa2015-05-21 12:18:07 -0400342
343void
344CallWidget::setActualCall(Call* value)
345{
346 actualCall_ = value;
Edric Milaretcdc978b2015-06-04 11:25:12 -0400347 ui->instantMessagingWidget->setMediaText(actualCall_);
Edric Milaret12353822015-05-14 14:41:09 -0400348}
Edric Milaretcdc978b2015-06-04 11:25:12 -0400349
Edric Milaret12353822015-05-14 14:41:09 -0400350void
351CallWidget::on_sortComboBox_currentIndexChanged(int index)
352{
353 auto idx = CategorizedHistoryModel::SortedProxy::instance()->
354 categoryModel()->index(index, 0);
355 CategorizedHistoryModel::SortedProxy::instance()->categorySelectionModel()->
356 setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
357 ui->historyList->setModel(CategorizedHistoryModel::SortedProxy::instance()->model());
Edric Milaret6456baa2015-05-21 12:18:07 -0400358}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400359
360void
361CallWidget::displaySpinner(bool display)
362{
Edric Milaretd8528fa2015-07-07 14:13:51 -0400363 display ? ui->spinnerWidget->show() : ui->spinnerWidget->hide();
Edric Milaretc7ab5502015-06-15 11:18:02 -0400364 if (ui->spinnerLabel->movie())
365 display ? ui->spinnerLabel->movie()->start() : ui->spinnerLabel->movie()->stop();
366}
Edric Milaretd8528fa2015-07-07 14:13:51 -0400367
368void CallWidget::on_cancelButton_clicked()
369{
370 if (actualCall_)
371 actualCall_->performAction(Call::Action::REFUSE);
372}