blob: db70b97ce4d4332dc2194b511b60e4c103a8f541 [file] [log] [blame]
Edric Milaret627500d2015-03-27 16:41:40 -04001/***************************************************************************
Nicolas Jager45bf7c02016-01-20 09:53:02 -05002 * Copyright (C) 2015-2016 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 Milaret43f3c1e2015-07-16 17:52:47 -040022#include <QClipboard>
23
Edric Milaret53f57b62015-05-11 11:02:17 -040024#include <memory>
Edric Milaret627500d2015-03-27 16:41:40 -040025
Edric Milaret43f3c1e2015-07-16 17:52:47 -040026//ERROR is defined in windows.h
27#include "utils.h"
28#undef ERROR
Edric Milareta0ebd062016-01-13 12:18:23 -050029#undef interface
Edric Milaret43f3c1e2015-07-16 17:52:47 -040030
Edric Milaret627500d2015-03-27 16:41:40 -040031#include "audio/settings.h"
32#include "personmodel.h"
Edric Milaret43f3c1e2015-07-16 17:52:47 -040033#include "person.h"
Edric Milaret627500d2015-03-27 16:41:40 -040034#include "fallbackpersoncollection.h"
Edric Milaret67007d12015-05-07 09:40:09 -040035#include "categorizedcontactmodel.h"
Edric Milaret6a642e22015-05-27 15:06:30 -040036#include "localhistorycollection.h"
Edric Milaret1b197eb2015-06-01 15:09:56 -040037#include "media/text.h"
38#include "media/recording.h"
Edric Milaret00a32252016-01-19 10:37:13 -050039#include "media/recordingmodel.h"
Edric Milareted0b2802015-10-01 15:10:02 -040040#include "recentmodel.h"
Edric Milaretab12d022015-12-04 16:09:44 -050041#include "contactmethod.h"
Edric Milareta0ebd062016-01-13 12:18:23 -050042#include "globalinstances.h"
Edric Milareted0b2802015-10-01 15:10:02 -040043
Edric Milaret559bda52015-04-29 17:02:31 -040044#include "wizarddialog.h"
Edric Milaret83b248c2015-06-02 11:42:23 -040045#include "windowscontactbackend.h"
Edric Milaret43f3c1e2015-07-16 17:52:47 -040046#include "contactpicker.h"
Edric Milaret2afd2bf2015-07-21 17:12:25 -040047#include "contactmethodpicker.h"
Edric Milaret2cf34292015-06-22 16:27:03 -040048#include "globalsystemtray.h"
Edric Milareted0b2802015-10-01 15:10:02 -040049#include "historydelegate.h"
50#include "contactdelegate.h"
51#include "smartlistdelegate.h"
Edric Milaretab12d022015-12-04 16:09:44 -050052#include "imdelegate.h"
Edric Milareta0ebd062016-01-13 12:18:23 -050053#include "pixbufmanipulator.h"
Edric Milaret627500d2015-03-27 16:41:40 -040054
Nicolas Jager97a21b42015-12-03 16:55:45 -050055CallWidget::CallWidget(QWidget* parent) :
Edric Milareted0b2802015-10-01 15:10:02 -040056 NavWidget(END ,parent),
Edric Milaret7d40a4a2015-05-13 13:01:15 -040057 ui(new Ui::CallWidget),
Edric Milaretab12d022015-12-04 16:09:44 -050058 menu_(new QMenu()),
59 imDelegate_(new ImDelegate())
Edric Milaret627500d2015-03-27 16:41:40 -040060{
Nicolas Jager97a21b42015-12-03 16:55:45 -050061 setMouseTracking(true);
62
Edric Milaret627500d2015-03-27 16:41:40 -040063 ui->setupUi(this);
64
Nicolas Jagerca850292016-01-17 14:11:10 -050065 welcomePageAnim_ = new QPropertyAnimation(ui->welcomePage, "pos", this);
66 messagingPageAnim_ = new QPropertyAnimation(ui->messagingPage, "pos", this);
67
Edric Milaret6456baa2015-05-21 12:18:07 -040068 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -040069 videoRenderer_ = nullptr;
70
Edric Milaret3aca8e32015-06-12 10:01:40 -040071 connect(ui->videoWidget, SIGNAL(setChatVisibility(bool)),
72 ui->instantMessagingWidget, SLOT(setVisible(bool)));
73
Edric Milareted0b2802015-10-01 15:10:02 -040074 QPixmap logo(":/images/logo-ring-standard-coul.png");
75 ui->ringLogo->setPixmap(logo.scaledToHeight(100, Qt::SmoothTransformation));
76 ui->ringLogo->setAlignment(Qt::AlignHCenter);
77
Edric Milareta0ebd062016-01-13 12:18:23 -050078 GlobalInstances::setPixmapManipulator(std::unique_ptr<Interfaces::PixbufManipulator>(new Interfaces::PixbufManipulator()));
79
Edric Milaret627500d2015-03-27 16:41:40 -040080 try {
Edric Milareta3e47282015-10-23 15:20:30 -040081 callModel_ = &CallModel::instance();
Edric Milaret627500d2015-03-27 16:41:40 -040082
83 connect(callModel_, SIGNAL(incomingCall(Call*)),
84 this, SLOT(callIncoming(Call*)));
85 connect(callModel_, SIGNAL(callAdded(Call*,Call*)),
86 this, SLOT(addedCall(Call*, Call*)));
87 connect(callModel_, SIGNAL(callStateChanged(Call*, Call::State)),
88 this, SLOT(callStateChanged(Call*, Call::State)));
89
Edric Milareta3e47282015-10-23 15:20:30 -040090 connect(&AccountModel::instance()
Edric Milaret67007d12015-05-07 09:40:09 -040091 , SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>))
92 , this
93 , SLOT(findRingAccount(QModelIndex, QModelIndex, QVector<int>)));
94
Edric Milaretfa05d972016-01-13 16:22:04 -050095 RecentModel::instance().peopleProxy()->setFilterRole(static_cast<int>(Ring::Role::Name));
96 RecentModel::instance().peopleProxy()->setFilterCaseSensitivity(Qt::CaseInsensitive);
Edric Milareta3e47282015-10-23 15:20:30 -040097 ui->smartList->setModel(RecentModel::instance().peopleProxy());
Edric Milareted0b2802015-10-01 15:10:02 -040098 connect(ui->smartList->selectionModel(),
99 SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
100 this,
101 SLOT(smartListSelectionChanged(QItemSelection,QItemSelection)));
Nicolas Jager97a21b42015-12-03 16:55:45 -0500102
103 connect(ui->smartList, &QTreeView::entered, this, &CallWidget::on_entered);
104
Edric Milareted0b2802015-10-01 15:10:02 -0400105 smartListDelegate_ = new SmartListDelegate();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500106 ui->smartList->setSmartListItemDelegate(smartListDelegate_);
Edric Milaret627500d2015-03-27 16:41:40 -0400107
Edric Milareta3e47282015-10-23 15:20:30 -0400108 PersonModel::instance().
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400109 addCollection<WindowsContactBackend>(LoadOptions::FORCE_ENABLED);
110
Edric Milareta3e47282015-10-23 15:20:30 -0400111 CategorizedContactModel::instance().setSortAlphabetical(false);
112 CategorizedContactModel::instance().setUnreachableHidden(true);
113 ui->contactView->setModel(&CategorizedContactModel::instance());
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400114 contactDelegate_ = new ContactDelegate();
115 ui->contactView->setItemDelegate(contactDelegate_);
116
Edric Milareta3e47282015-10-23 15:20:30 -0400117 CategorizedHistoryModel::instance().
Edric Milaret6a642e22015-05-27 15:06:30 -0400118 addCollection<LocalHistoryCollection>(LoadOptions::FORCE_ENABLED);
Edric Milaret627500d2015-03-27 16:41:40 -0400119
Edric Milareta3e47282015-10-23 15:20:30 -0400120 ui->historyList->setModel(CategorizedHistoryModel::SortedProxy::instance().model());
121 CategorizedHistoryModel::SortedProxy::instance().model()->sort(0, Qt::DescendingOrder);
Edric Milaret53f57b62015-05-11 11:02:17 -0400122 ui->historyList->setHeaderHidden(true);
Edric Milaret01f23842015-06-22 14:46:01 -0400123 historyDelegate_ = new HistoryDelegate();
124 ui->historyList->setItemDelegate(historyDelegate_);
Edric Milaret77dd6982015-07-07 16:45:41 -0400125
Edric Milareta3e47282015-10-23 15:20:30 -0400126 connect(CategorizedHistoryModel::SortedProxy::instance().model(), &QSortFilterProxyModel::layoutChanged, [=]() {
127 auto idx = CategorizedHistoryModel::SortedProxy::instance().model()->index(0,0);
Edric Milaret77dd6982015-07-07 16:45:41 -0400128 if (idx.isValid())
129 ui->historyList->setExpanded(idx, true);
130 });
131
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400132 ui->historyList->setContextMenuPolicy(Qt::CustomContextMenu);
133 connect(ui->historyList, &QListView::customContextMenuRequested, [=](const QPoint& pos){
134 if (ui->historyList->currentIndex().parent().isValid()) {
135 QPoint globalPos = ui->historyList->mapToGlobal(pos);
136 QMenu menu;
137
138 ContactMethod* contactMethod = ui->historyList->currentIndex()
139 .data(static_cast<int>(Call::Role::ContactMethod)).value<ContactMethod*>();
140
Edric Milaret53ac6e52015-09-14 13:37:06 -0400141 auto copyAction = new QAction(tr("Copy number"), this);
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400142 menu.addAction(copyAction);
143 connect(copyAction, &QAction::triggered, [=]() {
144 QApplication::clipboard()->setText(contactMethod->uri());
145 });
Edric Milaretbe0aa5a2015-07-31 15:08:39 -0400146 if (not contactMethod->contact() || contactMethod->contact()->isPlaceHolder()) {
Edric Milaret53ac6e52015-09-14 13:37:06 -0400147 auto addExisting = new QAction(tr("Add to contact"), this);
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400148 menu.addAction(addExisting);
149 connect(addExisting, &QAction::triggered, [=]() {
Edric Milaretbe0aa5a2015-07-31 15:08:39 -0400150 ContactPicker contactPicker(contactMethod);
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400151 contactPicker.move(globalPos.x(), globalPos.y() - (contactPicker.height()/2));
Edric Milaretbe0aa5a2015-07-31 15:08:39 -0400152 contactPicker.exec();
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400153 });
154 }
155 menu.exec(globalPos);
156 }
157 });
Edric Milaret53f57b62015-05-11 11:02:17 -0400158
Edric Milaret627500d2015-03-27 16:41:40 -0400159 findRingAccount();
Edric Milareta0ebd062016-01-13 12:18:23 -0500160 setupOutOfCallIM();
161 setupSmartListMenu();
Edric Milaret627500d2015-03-27 16:41:40 -0400162
Edric Milaret80e0b212015-10-16 10:07:43 -0400163 } catch (const std::exception& e) {
164 qDebug() << "INIT ERROR" << e.what();
Edric Milaret627500d2015-03-27 16:41:40 -0400165 }
166}
167
168CallWidget::~CallWidget()
169{
170 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400171 delete menu_;
Edric Milaret01f23842015-06-22 14:46:01 -0400172 delete contactDelegate_;
Edric Milaretab12d022015-12-04 16:09:44 -0500173 delete imDelegate_;
Nicolas Jagerca850292016-01-17 14:11:10 -0500174 delete welcomePageAnim_;
175 delete messagingPageAnim_;
Edric Milaret627500d2015-03-27 16:41:40 -0400176}
177
178void
Edric Milareta0ebd062016-01-13 12:18:23 -0500179CallWidget::setupOutOfCallIM()
180{
181 ui->listMessageView->setItemDelegate(imDelegate_);
182 ui->listMessageView->setContextMenuPolicy(Qt::ActionsContextMenu);
183
184 auto copyAction = new QAction(tr("Copy"), this);
185 ui->listMessageView->addAction(copyAction);
186 connect(copyAction, &QAction::triggered, [=]() {
187 auto idx = ui->listMessageView->currentIndex();
188 if (idx.isValid()) {
189 auto text = ui->listMessageView->model()->data(idx);
190 QApplication::clipboard()->setText(text.value<QString>());
191 }
192 });
193 auto displayDate = new QAction(tr("Display date"), this);
194 displayDate->setCheckable(true);
195 ui->listMessageView->addAction(displayDate);
196 auto displayAuthor = new QAction(tr("Display author"), this);
197 displayAuthor->setCheckable(true);
198 ui->listMessageView->addAction(displayAuthor);
199 auto lamdba = [=](){
200 int opts = 0;
201 displayAuthor->isChecked() ? opts |= ImDelegate::DisplayOptions::AUTHOR : opts;
202 displayDate->isChecked() ? opts |= ImDelegate::DisplayOptions::DATE : opts;
203 imDelegate_->setDisplayOptions(static_cast<ImDelegate::DisplayOptions>(opts));
204 };
205 connect(displayAuthor, &QAction::triggered, lamdba);
206 connect(displayDate, &QAction::triggered, lamdba);
Edric Milaret00a32252016-01-19 10:37:13 -0500207
208 connect(&::Media::RecordingModel::instance(),
209 SIGNAL(newTextMessage(::Media::TextRecording*, ContactMethod*)),
210 this,
211 SLOT(onIncomingMessage(::Media::TextRecording*, ContactMethod*)));
212}
213
214void
215CallWidget::onIncomingMessage(::Media::TextRecording* t, ContactMethod* cm) {
216 Q_UNUSED(cm)
217
218 if (!QApplication::focusWidget()) {
219 auto idx = t->instantTextMessagingModel()->
220 index(t->instantTextMessagingModel()->rowCount()-1, 0);
221 GlobalSystemTray::instance()
222 .showMessage("Ring",
223 QString(tr("Message incoming from %1")).arg(
224 idx.data((int)Media::TextRecording::Role::AuthorDisplayname).toString()));
225 QApplication::alert(this, 5000);
226 }
Edric Milareta0ebd062016-01-13 12:18:23 -0500227}
228
229void
230CallWidget::setupSmartListMenu() {
231 ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
232 connect(ui->smartList, &QListView::customContextMenuRequested, [=](const QPoint& pos){
233 auto idx = ui->smartList->currentIndex();
234 if (not idx.isValid())
235 return;
236 QPoint globalPos = ui->smartList->mapToGlobal(pos);
237 QMenu menu;
238
239 ContactMethod* contactMethod = RecentModel::instance()
240 .getContactMethods(RecentModel::instance().peopleProxy()->mapToSource(idx)).at(0);
241 if (not contactMethod)
242 return;
243 auto copyAction = new QAction(tr("Copy number"), this);
244 menu.addAction(copyAction);
245 connect(copyAction, &QAction::triggered, [=]() {
246 QApplication::clipboard()->setText(contactMethod->uri());
247 });
248 if (not contactMethod->contact() || contactMethod->contact()->isPlaceHolder()) {
249 auto addExisting = new QAction(tr("Add to contact"), this);
250 menu.addAction(addExisting);
251 connect(addExisting, &QAction::triggered, [=]() {
252 ContactPicker contactPicker(contactMethod);
253 contactPicker.move(globalPos.x(), globalPos.y() - (contactPicker.height()/2));
254 contactPicker.exec();
255 });
256 }
257 menu.exec(globalPos);
258 });
259}
260
261void
Edric Milaret67007d12015-05-07 09:40:09 -0400262CallWidget::findRingAccount(QModelIndex idx1, QModelIndex idx2, QVector<int> vec)
263{
264 Q_UNUSED(idx1)
265 Q_UNUSED(idx2)
266 Q_UNUSED(vec)
267
Edric Milareta3e47282015-10-23 15:20:30 -0400268 auto a_count = AccountModel::instance().rowCount();
Edric Milaret67007d12015-05-07 09:40:09 -0400269 auto found = false;
270 for (int i = 0; i < a_count; ++i) {
Edric Milareta3e47282015-10-23 15:20:30 -0400271 auto idx = AccountModel::instance().index(i, 0);
Edric Milaret67007d12015-05-07 09:40:09 -0400272 auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
273 if ((Account::Protocol)protocol.toUInt() == Account::Protocol::RING) {
274 auto username = idx.data(static_cast<int>(Account::Role::Username));
Edric Milareted0b2802015-10-01 15:10:02 -0400275 ui->ringIdLabel->setText(username.toString());
Edric Milaret67007d12015-05-07 09:40:09 -0400276 found = true;
277 return;
278 }
279 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500280 if (not found) {
Edric Milaret53ac6e52015-09-14 13:37:06 -0400281 ui->ringIdLabel->setText(tr("NO RING ACCOUNT FOUND"));
Edric Milaret67007d12015-05-07 09:40:09 -0400282 }
283}
284
285void
286CallWidget::findRingAccount()
287{
Edric Milaret559bda52015-04-29 17:02:31 -0400288
Edric Milareta3e47282015-10-23 15:20:30 -0400289 auto a_count = AccountModel::instance().rowCount();
Edric Milaret627500d2015-03-27 16:41:40 -0400290 auto found = false;
291 for (int i = 0; i < a_count; ++i) {
Edric Milareta3e47282015-10-23 15:20:30 -0400292 auto idx = AccountModel::instance().index(i, 0);
Edric Milaret627500d2015-03-27 16:41:40 -0400293 auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
294 if ((Account::Protocol)protocol.toUInt() == Account::Protocol::RING) {
Edric Milareta3e47282015-10-23 15:20:30 -0400295 auto account = AccountModel::instance().getAccountByModelIndex(idx);
Edric Milaret68779c42015-07-09 16:53:03 -0400296 if (account->displayName().isEmpty())
297 account->displayName() = account->alias();
298 auto username = account->username();
Edric Milareted0b2802015-10-01 15:10:02 -0400299 ui->ringIdLabel->setText(username);
Edric Milaret627500d2015-03-27 16:41:40 -0400300 found = true;
301 return;
302 }
303 }
304 if (!found) {
Edric Milareted0b2802015-10-01 15:10:02 -0400305 ui->ringIdLabel->setText(tr("NO RING ACCOUNT FOUND"));
Edric Milaret559bda52015-04-29 17:02:31 -0400306 WizardDialog *wizardDialog = new WizardDialog();
307 wizardDialog->exec();
308 delete wizardDialog;
Edric Milaret627500d2015-03-27 16:41:40 -0400309 }
310}
311
312void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500313CallWidget::callIncoming(Call* call)
Edric Milaret627500d2015-03-27 16:41:40 -0400314{
Edric Milaret00a32252016-01-19 10:37:13 -0500315 if (!QApplication::focusWidget()) {
316 GlobalSystemTray::instance()
317 .showMessage("Ring",
318 QString(tr("Call incoming from %1")).arg(call->formattedName()));
Edric Milaret2cf34292015-06-22 16:27:03 -0400319 QApplication::alert(this, 5000);
320 }
321
Edric Milaret435cdfc2015-06-01 16:15:50 -0400322 if (!call->account()->isAutoAnswer()) {
Nicolas Jager97a21b42015-12-03 16:55:45 -0500323 ui->callerIdLabel->setText(QString(tr("%1", "%1 is the name of the caller"))
Edric Milareta0ebd062016-01-13 12:18:23 -0500324 .arg(call->formattedName()));
Edric Milareted0b2802015-10-01 15:10:02 -0400325 ui->stackedWidget->setCurrentWidget(ui->callInvitePage);
Edric Milaret435cdfc2015-06-01 16:15:50 -0400326 }
Edric Milaret6456baa2015-05-21 12:18:07 -0400327 setActualCall(call);
Edric Milaret627500d2015-03-27 16:41:40 -0400328}
329
330void
331CallWidget::on_acceptButton_clicked()
332{
333 if (actualCall_ != nullptr)
Edric Milaret53f57b62015-05-11 11:02:17 -0400334 actualCall_->performAction(Call::Action::ACCEPT);
Edric Milareted0b2802015-10-01 15:10:02 -0400335 ui->stackedWidget->setCurrentWidget(ui->videoPage);
Edric Milaret627500d2015-03-27 16:41:40 -0400336}
337
338void
339CallWidget::on_refuseButton_clicked()
340{
341 if (actualCall_ == nullptr)
342 return;
343 actualCall_->performAction(Call::Action::REFUSE);
Edric Milaret6456baa2015-05-21 12:18:07 -0400344 setActualCall(nullptr);
Edric Milareted0b2802015-10-01 15:10:02 -0400345 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Edric Milaret627500d2015-03-27 16:41:40 -0400346}
347
348void
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400349CallWidget::addedCall(Call* call, Call* parent)
350{
Edric Milaret627500d2015-03-27 16:41:40 -0400351 Q_UNUSED(parent);
352 if (call->direction() == Call::Direction::OUTGOING) {
Edric Milaret6456baa2015-05-21 12:18:07 -0400353 setActualCall(call);
Nicolas Jager45bf7c02016-01-20 09:53:02 -0500354 ui->stackedWidget->setCurrentWidget(ui->outboundCallPage);
Edric Milaret627500d2015-03-27 16:41:40 -0400355 }
356}
357
358void
Edric Milaret67007d12015-05-07 09:40:09 -0400359CallWidget::callStateChanged(Call* call, Call::State previousState)
360{
Edric Milaret627500d2015-03-27 16:41:40 -0400361 Q_UNUSED(previousState)
Edric Milaret4b1be4a2016-01-15 16:49:20 -0500362 if (call == nullptr
363 || call != actualCall_)
Edric Milaretb5b49072015-05-08 11:56:07 -0400364 return;
Edric Milareted0b2802015-10-01 15:10:02 -0400365
Edric Milaret4b1be4a2016-01-15 16:49:20 -0500366 if (call->state() == Call::State::OVER) {
Edric Milaret6456baa2015-05-21 12:18:07 -0400367 setActualCall(nullptr);
Edric Milaretc54e2272015-10-01 10:14:00 -0400368 ui->instantMessagingWidget->setMediaText(nullptr);
Edric Milareted0b2802015-10-01 15:10:02 -0400369 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Edric Milareta0ebd062016-01-13 12:18:23 -0500370 //TODO : Link this so that recentModel get selected correctly
371 // auto onHoldCall = callModel_->getActiveCalls().first();
372 // if (onHoldCall != nullptr && onHoldCall->state() == Call::State::HOLD) {
373 // setActualCall(onHoldCall);
374 // onHoldCall->performAction(Call::Action::HOLD);
375 // }
Edric Milaret53f57b62015-05-11 11:02:17 -0400376 } else if (call->state() == Call::State::CURRENT) {
Edric Milaretc54e2272015-10-01 10:14:00 -0400377 ui->instantMessagingWidget->setMediaText(actualCall_);
Edric Milareted0b2802015-10-01 15:10:02 -0400378 ui->stackedWidget->setCurrentWidget(ui->videoPage);
Edric Milaret627500d2015-03-27 16:41:40 -0400379 }
Edric Milaret627500d2015-03-27 16:41:40 -0400380}
381
382void
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400383CallWidget::atExit()
384{
Edric Milaret627500d2015-03-27 16:41:40 -0400385}
Edric Milaret67007d12015-05-07 09:40:09 -0400386
387void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500388CallWidget::on_contactView_doubleClicked(const QModelIndex& index)
Edric Milaret67007d12015-05-07 09:40:09 -0400389{
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400390 if (not index.isValid())
391 return;
392
Edric Milaret2afd2bf2015-07-21 17:12:25 -0400393 ContactMethod* uri = nullptr;
Edric Milaret67007d12015-05-07 09:40:09 -0400394
Edric Milaret7d40a4a2015-05-13 13:01:15 -0400395 auto var = index.child(0,0).data(
396 static_cast<int>(Person::Role::Object));
397 if (var.isValid()) {
398 Person* person = var.value<Person*>();
Edric Milaret2afd2bf2015-07-21 17:12:25 -0400399 if (person->phoneNumbers().size() == 1) {
400 uri = person->phoneNumbers().at(0);
401 } else if (person->phoneNumbers().size() > 1) {
402 ContactMethodPicker dlg(person->phoneNumbers());
403 auto pos = QCursor::pos();
404 dlg.move(pos.x(), pos.y());
405 if (dlg.exec())
406 uri = dlg.getSelected();
407 }
408 if (uri) {
Edric Milareta3e47282015-10-23 15:20:30 -0400409 auto outCall = CallModel::instance().dialingCall(uri);
Edric Milaret2afd2bf2015-07-21 17:12:25 -0400410 outCall->performAction(Call::Action::ACCEPT);
Edric Milareted0b2802015-10-01 15:10:02 -0400411 ui->mainTabMenu->setCurrentIndex(0);
412 ui->smartList->setFocus();
Edric Milaret67007d12015-05-07 09:40:09 -0400413 }
414 }
Edric Milaret67007d12015-05-07 09:40:09 -0400415}
Edric Milaret53f57b62015-05-11 11:02:17 -0400416
Edric Milaret6456baa2015-05-21 12:18:07 -0400417void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500418CallWidget::on_historyList_doubleClicked(const QModelIndex& index)
Edric Milaret53f57b62015-05-11 11:02:17 -0400419{
Edric Milaret12353822015-05-14 14:41:09 -0400420 if (not index.isValid())
421 return;
422
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400423 auto number = index.data(static_cast<int>(Call::Role::ContactMethod)).value<ContactMethod*>();
424 if (number) {
Edric Milareta3e47282015-10-23 15:20:30 -0400425 auto outCall = CallModel::instance().dialingCall(number);
Edric Milaret53f57b62015-05-11 11:02:17 -0400426 outCall->performAction(Call::Action::ACCEPT);
Edric Milareted0b2802015-10-01 15:10:02 -0400427 ui->mainTabMenu->setCurrentIndex(0);
428 ui->smartList->setFocus();
Edric Milaret53f57b62015-05-11 11:02:17 -0400429 }
430}
Edric Milaret6456baa2015-05-21 12:18:07 -0400431
432void
433CallWidget::setActualCall(Call* value)
434{
435 actualCall_ = value;
Edric Milaret80e0b212015-10-16 10:07:43 -0400436 CallModel::instance().selectCall(value);
437 ui->videoWidget->pushRenderer(value);
Edric Milaret6456baa2015-05-21 12:18:07 -0400438}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400439
440void
Edric Milareted0b2802015-10-01 15:10:02 -0400441CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400442{
443 if (actualCall_)
444 actualCall_->performAction(Call::Action::REFUSE);
445}
Edric Milareted0b2802015-10-01 15:10:02 -0400446
447void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500448CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400449{
Edric Milareta3e47282015-10-23 15:20:30 -0400450 auto realIndex = RecentModel::instance().peopleProxy()->mapToSource(index);
451 if (RecentModel::instance().hasActiveCall(realIndex))
Edric Milareted0b2802015-10-01 15:10:02 -0400452 return;
453
454 ContactMethod* m = nullptr;
455 if (auto cm = realIndex.data((int)Call::Role::ContactMethod).value<ContactMethod*>()) {
456 m = cm;
457 } else {
458 if (auto person = realIndex.data((int)Person::Role::Object).value<Person*>()) {
459 m = person->phoneNumbers().first();
460 }
461 }
Edric Milareta3e47282015-10-23 15:20:30 -0400462 if (m && !RecentModel::instance().index(0, 0, realIndex).isValid()) {
463 Call* c = CallModel::instance().dialingCall(m);
Edric Milareted0b2802015-10-01 15:10:02 -0400464 c->performAction(Call::Action::ACCEPT);
465 }
466}
467
468void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500469CallWidget::smartListSelectionChanged(const QItemSelection& newSel, const QItemSelection& oldSel) {
Edric Milareted0b2802015-10-01 15:10:02 -0400470
471 Q_UNUSED(oldSel)
472
Edric Milaretab12d022015-12-04 16:09:44 -0500473 if (newSel.indexes().empty())
474 {
475 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
476 return;
477 }
Edric Milareted0b2802015-10-01 15:10:02 -0400478 auto newIdx = newSel.indexes().first();
Edric Milaret80e0b212015-10-16 10:07:43 -0400479 if (not newIdx.isValid())
Edric Milareted0b2802015-10-01 15:10:02 -0400480 return;
481
Edric Milaretab12d022015-12-04 16:09:44 -0500482 auto nodeIdx = RecentModel::instance().peopleProxy()->mapToSource(newIdx);
483 auto newIdxCall = RecentModel::instance().getActiveCall(nodeIdx);
Edric Milareted0b2802015-10-01 15:10:02 -0400484
Edric Milareta0ebd062016-01-13 12:18:23 -0500485 if (newIdxCall && newIdxCall != actualCall_) {
Edric Milareted0b2802015-10-01 15:10:02 -0400486 setActualCall(newIdxCall);
487 ui->stackedWidget->setCurrentWidget(ui->videoPage);
Edric Milareta0ebd062016-01-13 12:18:23 -0500488 } else if (newIdxCall == nullptr){
489 setActualCall(nullptr);
490 showIMOutOfCall();
Edric Milareted0b2802015-10-01 15:10:02 -0400491 } else {
492 setActualCall(nullptr);
493 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
494 }
495}
496
497void
498CallWidget::placeCall()
499{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500500 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400501 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500502 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400503 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500504 ui->ringContactLineEdit->clear();
Edric Milareted0b2802015-10-01 15:10:02 -0400505}
506
507void
Edric Milaret33cb4832016-01-08 10:14:14 -0500508CallWidget::settingsButton_clicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400509{
510 emit NavigationRequested(ScreenEnum::ConfScreen);
511}
512
513void
Edric Milaret33cb4832016-01-08 10:14:14 -0500514CallWidget::contactButton_clicked(bool checked)
Edric Milareted0b2802015-10-01 15:10:02 -0400515{
Edric Milareted0b2802015-10-01 15:10:02 -0400516 ui->mainTabMenu->setCurrentIndex(checked ? 1 : 0);
517}
518
519void
Edric Milaret33cb4832016-01-08 10:14:14 -0500520CallWidget::historicButton_clicked(bool checked)
Edric Milareted0b2802015-10-01 15:10:02 -0400521{
Edric Milareted0b2802015-10-01 15:10:02 -0400522 ui->mainTabMenu->setCurrentIndex(checked ? 2 : 0);
523}
Nicolas Jager97a21b42015-12-03 16:55:45 -0500524
525void
526CallWidget::on_ringContactLineEdit_returnPressed()
527{
Edric Milaret00593d12016-01-19 11:57:46 -0500528 auto cm = PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text());
529 time_t currentTime;
530 ::time(&currentTime);
531 cm->setLastUsed(currentTime);
Edric Milaret8001f6f2016-01-27 09:55:12 -0500532 ui->ringContactLineEdit->clear();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500533}
534
535void
536CallWidget::on_btnCall_clicked()
537{
538 placeCall();
539}
540
541void
542CallWidget::on_btnvideo_clicked()
543{
544 if (not highLightedIndex_.isValid())
545 return;
546
547 on_smartList_doubleClicked(highLightedIndex_);
548}
Edric Milaretab12d022015-12-04 16:09:44 -0500549
550void
Edric Milareta0ebd062016-01-13 12:18:23 -0500551CallWidget::showIMOutOfCall()
Edric Milaretab12d022015-12-04 16:09:44 -0500552{
553 if (not highLightedIndex_.isValid())
554 return;
555
556 ui->smartList->selectionModel()->select(highLightedIndex_, QItemSelectionModel::ClearAndSelect);
557
558 ui->contactMethodComboBox->clear();
559
560 auto nodeIdx = RecentModel::instance().peopleProxy()->mapToSource(highLightedIndex_);
Edric Milareta0ebd062016-01-13 12:18:23 -0500561 ui->imNameLabel->setText(QString(tr("Conversation with %1", "%1 is the contact name"))
562 .arg(nodeIdx.data(static_cast<int>(Ring::Role::Name)).toString()));
Edric Milaretab12d022015-12-04 16:09:44 -0500563 auto cmVector = RecentModel::instance().getContactMethods(nodeIdx);
Edric Milareta0ebd062016-01-13 12:18:23 -0500564 ui->contactMethodComboBox->setEnabled(cmVector.size() > 1);
Edric Milaretab12d022015-12-04 16:09:44 -0500565 foreach (const ContactMethod* cm, cmVector) {
Edric Milareta0ebd062016-01-13 12:18:23 -0500566 ui->contactMethodComboBox->addItem(cm->uri());
Edric Milaretab12d022015-12-04 16:09:44 -0500567 }
Nicolas Jagerca850292016-01-17 14:11:10 -0500568 slideToRight(messagingPageAnim_, ui->messagingPage);
Edric Milaretab12d022015-12-04 16:09:44 -0500569}
570
571void
572CallWidget::on_sendButton_clicked()
573{
Edric Milareta0ebd062016-01-13 12:18:23 -0500574 if (ui->messageEdit->text().trimmed().isEmpty())
Edric Milaretab12d022015-12-04 16:09:44 -0500575 return;
576 auto number = ui->contactMethodComboBox->currentText();
577 if (auto cm = PhoneDirectoryModel::instance().getNumber(number)) {
578 QMap<QString, QString> msg;
579 msg["text/plain"] = ui->messageEdit->text();
580 cm->sendOfflineTextMessage(msg);
581 ui->messageEdit->clear();
582 } else {
583 qWarning() << "Contact Method not found for " << number;
584 }
585}
586
587void
588CallWidget::on_messageEdit_returnPressed()
589{
590 on_sendButton_clicked();
591}
592
593void
594CallWidget::on_contactMethodComboBox_currentIndexChanged(const QString& number)
595{
596 auto cm = PhoneDirectoryModel::instance().getNumber(number);
597 if (auto txtRecording = cm->textRecording()) {
598 ui->listMessageView->setModel(txtRecording->instantMessagingModel());
599 disconnect(imConnection_);
600 imConnection_ = connect(txtRecording,
Edric Milareta0ebd062016-01-13 12:18:23 -0500601 SIGNAL(messageInserted(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)),
602 this,
603 SLOT(slotAccountMessageReceived(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)));
Edric Milaret4be72022016-01-19 10:24:13 -0500604 auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
605 if (messagesPresent) {
606 ui->listMessageView->scrollToBottom();
607 txtRecording->setAllRead();
608 }
609 ui->listMessageView->setVisible(messagesPresent);
610 ui->noMessagesLabel->setVisible(!messagesPresent);
611 if (not messagesPresent) {
Edric Milaret49130472016-01-22 10:39:37 -0500612 imVisibleConnection_ = connect(txtRecording->instantMessagingModel(),
613 &QAbstractItemModel::rowsInserted,
614 [this, txtRecording]() {
615 if (imVisibleConnection_)
616 disconnect(imVisibleConnection_);
617 auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
Edric Milaret4be72022016-01-19 10:24:13 -0500618 ui->listMessageView->setVisible(messagesPresent);
619 ui->noMessagesLabel->setVisible(!messagesPresent);
Edric Milaret4be72022016-01-19 10:24:13 -0500620 });
621 }
Edric Milaretab12d022015-12-04 16:09:44 -0500622 }
623}
624
625void
626CallWidget::slotAccountMessageReceived(const QMap<QString,QString> message,
627 ContactMethod* cm,
628 Media::Media::Direction dir)
629{
630 Q_UNUSED(message)
Edric Milaretab12d022015-12-04 16:09:44 -0500631 Q_UNUSED(dir)
632
633 ui->listMessageView->scrollToBottom();
Edric Milaret23fd3fa2016-01-15 15:37:35 -0500634 cm->textRecording()->setAllRead();
Edric Milaretab12d022015-12-04 16:09:44 -0500635}
Edric Milaretfa05d972016-01-13 16:22:04 -0500636
637void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500638CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500639{
640 RecentModel::instance().peopleProxy()->setFilterWildcard(text);
641}
Edric Milareta0ebd062016-01-13 12:18:23 -0500642
Nicolas Jagerca850292016-01-17 14:11:10 -0500643void
644CallWidget::on_imBackButton_clicked()
Edric Milareta0ebd062016-01-13 12:18:23 -0500645{
Nicolas Jagerca850292016-01-17 14:11:10 -0500646 slideToLeft(welcomePageAnim_, ui->welcomePage);
647}
648
649void
650CallWidget::slideToLeft(QPropertyAnimation* anim, QWidget* widget)
651{
652 ui->stackedWidget->setCurrentWidget(widget);
653 anim->setDuration(animDuration_);
654 anim->setStartValue(QPoint(widget->width(), widget->y()));
655 anim->setEndValue(QPoint(widget->x(), widget->y()));
656 anim->setEasingCurve(QEasingCurve::OutQuad);
657 anim->start();
658}
659
660void
661CallWidget::slideToRight(QPropertyAnimation* anim, QWidget* widget)
662{
663 ui->stackedWidget->setCurrentWidget(widget);
664 anim->setDuration(animDuration_);
665 anim->setStartValue(QPoint(-widget->width(), widget->y()));
666 anim->setEndValue(QPoint(widget->x(), widget->y()));
667 anim->setEasingCurve(QEasingCurve::OutQuad);
668 anim->start();
Edric Milareta0ebd062016-01-13 12:18:23 -0500669}