blob: 8f8e603272c220c42dd2da424bb3d382caddf08d [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) :
Nicolas Jager74fe46f2016-02-29 14:55:09 -050056 NavWidget(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{
61 ui->setupUi(this);
62
Edric Milaret6b68a482016-02-01 15:23:44 -050063 pageAnim_ = new QPropertyAnimation(ui->welcomePage, "pos", this);
Nicolas Jagerca850292016-01-17 14:11:10 -050064
Edric Milaret6456baa2015-05-21 12:18:07 -040065 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -040066 videoRenderer_ = nullptr;
67
Nicolas Jager74fe46f2016-02-29 14:55:09 -050068 connect(ui->settingsButton, &QPushButton::clicked, this, &CallWidget::settingsButtonClicked);
69
Edric Milaret3aca8e32015-06-12 10:01:40 -040070 connect(ui->videoWidget, SIGNAL(setChatVisibility(bool)),
71 ui->instantMessagingWidget, SLOT(setVisible(bool)));
72
Edric Milareted0b2802015-10-01 15:10:02 -040073 QPixmap logo(":/images/logo-ring-standard-coul.png");
74 ui->ringLogo->setPixmap(logo.scaledToHeight(100, Qt::SmoothTransformation));
75 ui->ringLogo->setAlignment(Qt::AlignHCenter);
76
Edric Milareta0ebd062016-01-13 12:18:23 -050077 GlobalInstances::setPixmapManipulator(std::unique_ptr<Interfaces::PixbufManipulator>(new Interfaces::PixbufManipulator()));
78
Edric Milaret627500d2015-03-27 16:41:40 -040079 try {
Edric Milareta3e47282015-10-23 15:20:30 -040080 callModel_ = &CallModel::instance();
Edric Milaret627500d2015-03-27 16:41:40 -040081
82 connect(callModel_, SIGNAL(incomingCall(Call*)),
83 this, SLOT(callIncoming(Call*)));
Edric Milaret627500d2015-03-27 16:41:40 -040084 connect(callModel_, SIGNAL(callStateChanged(Call*, Call::State)),
85 this, SLOT(callStateChanged(Call*, Call::State)));
86
Edric Milareta3e47282015-10-23 15:20:30 -040087 connect(&AccountModel::instance()
Edric Milaret67007d12015-05-07 09:40:09 -040088 , SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>))
89 , this
90 , SLOT(findRingAccount(QModelIndex, QModelIndex, QVector<int>)));
91
Edric Milaretfa05d972016-01-13 16:22:04 -050092 RecentModel::instance().peopleProxy()->setFilterRole(static_cast<int>(Ring::Role::Name));
93 RecentModel::instance().peopleProxy()->setFilterCaseSensitivity(Qt::CaseInsensitive);
Edric Milareta3e47282015-10-23 15:20:30 -040094 ui->smartList->setModel(RecentModel::instance().peopleProxy());
Edric Milaret6816fd72016-01-29 16:36:24 -050095
96 smartListDelegate_ = new SmartListDelegate();
97 ui->smartList->setSmartListItemDelegate(smartListDelegate_);
Edric Milaret627500d2015-03-27 16:41:40 -040098
Edric Milareta3e47282015-10-23 15:20:30 -040099 PersonModel::instance().
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400100 addCollection<WindowsContactBackend>(LoadOptions::FORCE_ENABLED);
101
Edric Milareta3e47282015-10-23 15:20:30 -0400102 CategorizedContactModel::instance().setSortAlphabetical(false);
103 CategorizedContactModel::instance().setUnreachableHidden(true);
104 ui->contactView->setModel(&CategorizedContactModel::instance());
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400105 contactDelegate_ = new ContactDelegate();
106 ui->contactView->setItemDelegate(contactDelegate_);
107
Edric Milareta3e47282015-10-23 15:20:30 -0400108 CategorizedHistoryModel::instance().
Edric Milaret6a642e22015-05-27 15:06:30 -0400109 addCollection<LocalHistoryCollection>(LoadOptions::FORCE_ENABLED);
Edric Milaret627500d2015-03-27 16:41:40 -0400110
Edric Milareta3e47282015-10-23 15:20:30 -0400111 ui->historyList->setModel(CategorizedHistoryModel::SortedProxy::instance().model());
112 CategorizedHistoryModel::SortedProxy::instance().model()->sort(0, Qt::DescendingOrder);
Edric Milaret53f57b62015-05-11 11:02:17 -0400113 ui->historyList->setHeaderHidden(true);
Edric Milaret01f23842015-06-22 14:46:01 -0400114 historyDelegate_ = new HistoryDelegate();
115 ui->historyList->setItemDelegate(historyDelegate_);
Edric Milaret77dd6982015-07-07 16:45:41 -0400116
Edric Milareta3e47282015-10-23 15:20:30 -0400117 connect(CategorizedHistoryModel::SortedProxy::instance().model(), &QSortFilterProxyModel::layoutChanged, [=]() {
118 auto idx = CategorizedHistoryModel::SortedProxy::instance().model()->index(0,0);
Edric Milaret77dd6982015-07-07 16:45:41 -0400119 if (idx.isValid())
120 ui->historyList->setExpanded(idx, true);
121 });
122
Edric Milaret6b68a482016-02-01 15:23:44 -0500123 connect(ui->smartList, &QTreeView::entered, this, &CallWidget::on_entered);
124
125 smartListDelegate_ = new SmartListDelegate();
126 ui->smartList->setSmartListItemDelegate(smartListDelegate_);
127
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400128 ui->historyList->setContextMenuPolicy(Qt::CustomContextMenu);
129 connect(ui->historyList, &QListView::customContextMenuRequested, [=](const QPoint& pos){
130 if (ui->historyList->currentIndex().parent().isValid()) {
131 QPoint globalPos = ui->historyList->mapToGlobal(pos);
132 QMenu menu;
133
134 ContactMethod* contactMethod = ui->historyList->currentIndex()
135 .data(static_cast<int>(Call::Role::ContactMethod)).value<ContactMethod*>();
136
Edric Milaret53ac6e52015-09-14 13:37:06 -0400137 auto copyAction = new QAction(tr("Copy number"), this);
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400138 menu.addAction(copyAction);
139 connect(copyAction, &QAction::triggered, [=]() {
140 QApplication::clipboard()->setText(contactMethod->uri());
141 });
Edric Milaretbe0aa5a2015-07-31 15:08:39 -0400142 if (not contactMethod->contact() || contactMethod->contact()->isPlaceHolder()) {
Edric Milaret53ac6e52015-09-14 13:37:06 -0400143 auto addExisting = new QAction(tr("Add to contact"), this);
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400144 menu.addAction(addExisting);
145 connect(addExisting, &QAction::triggered, [=]() {
Edric Milaretbe0aa5a2015-07-31 15:08:39 -0400146 ContactPicker contactPicker(contactMethod);
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400147 contactPicker.move(globalPos.x(), globalPos.y() - (contactPicker.height()/2));
Edric Milaretbe0aa5a2015-07-31 15:08:39 -0400148 contactPicker.exec();
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400149 });
150 }
151 menu.exec(globalPos);
152 }
153 });
Edric Milaret53f57b62015-05-11 11:02:17 -0400154
Edric Milaret627500d2015-03-27 16:41:40 -0400155 findRingAccount();
Edric Milareta0ebd062016-01-13 12:18:23 -0500156 setupOutOfCallIM();
157 setupSmartListMenu();
Edric Milaret627500d2015-03-27 16:41:40 -0400158
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500159 connect(ui->smartList, &SmartList::btnVideoClicked, this, &CallWidget::btnComBarVideoClicked);
Nicolas Jager41e4fcf2016-01-28 11:37:03 -0500160
Edric Milaret6b68a482016-02-01 15:23:44 -0500161 connect(RecentModel::instance().selectionModel(),
162 SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
163 this,
164 SLOT(smartListSelectionChanged(QItemSelection,QItemSelection)));
165
166 connect(RecentModel::instance().selectionModel(), &QItemSelectionModel::selectionChanged, [=](const QItemSelection &selected, const QItemSelection &deselected) {
167 Q_UNUSED(deselected)
168 if (selected.size()) {
169 auto idx = selected.indexes().first();
170 auto realIdx = RecentModel::instance().peopleProxy()->mapFromSource(idx);
171 ui->smartList->selectionModel()->setCurrentIndex(realIdx, QItemSelectionModel::ClearAndSelect);
172 } else
173 ui->smartList->clearSelection();
174 });
175
Edric Milaret80e0b212015-10-16 10:07:43 -0400176 } catch (const std::exception& e) {
177 qDebug() << "INIT ERROR" << e.what();
Edric Milaret627500d2015-03-27 16:41:40 -0400178 }
179}
180
181CallWidget::~CallWidget()
182{
183 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400184 delete menu_;
Edric Milaret01f23842015-06-22 14:46:01 -0400185 delete contactDelegate_;
Edric Milaretab12d022015-12-04 16:09:44 -0500186 delete imDelegate_;
Edric Milaret6b68a482016-02-01 15:23:44 -0500187 delete pageAnim_;
188 delete smartListDelegate_;
Edric Milaret627500d2015-03-27 16:41:40 -0400189}
190
191void
Edric Milareta0ebd062016-01-13 12:18:23 -0500192CallWidget::setupOutOfCallIM()
193{
194 ui->listMessageView->setItemDelegate(imDelegate_);
195 ui->listMessageView->setContextMenuPolicy(Qt::ActionsContextMenu);
196
197 auto copyAction = new QAction(tr("Copy"), this);
198 ui->listMessageView->addAction(copyAction);
199 connect(copyAction, &QAction::triggered, [=]() {
200 auto idx = ui->listMessageView->currentIndex();
201 if (idx.isValid()) {
202 auto text = ui->listMessageView->model()->data(idx);
203 QApplication::clipboard()->setText(text.value<QString>());
204 }
205 });
206 auto displayDate = new QAction(tr("Display date"), this);
207 displayDate->setCheckable(true);
208 ui->listMessageView->addAction(displayDate);
209 auto displayAuthor = new QAction(tr("Display author"), this);
210 displayAuthor->setCheckable(true);
211 ui->listMessageView->addAction(displayAuthor);
212 auto lamdba = [=](){
213 int opts = 0;
214 displayAuthor->isChecked() ? opts |= ImDelegate::DisplayOptions::AUTHOR : opts;
215 displayDate->isChecked() ? opts |= ImDelegate::DisplayOptions::DATE : opts;
216 imDelegate_->setDisplayOptions(static_cast<ImDelegate::DisplayOptions>(opts));
217 };
218 connect(displayAuthor, &QAction::triggered, lamdba);
219 connect(displayDate, &QAction::triggered, lamdba);
Edric Milaret00a32252016-01-19 10:37:13 -0500220
221 connect(&::Media::RecordingModel::instance(),
222 SIGNAL(newTextMessage(::Media::TextRecording*, ContactMethod*)),
223 this,
224 SLOT(onIncomingMessage(::Media::TextRecording*, ContactMethod*)));
225}
226
227void
228CallWidget::onIncomingMessage(::Media::TextRecording* t, ContactMethod* cm) {
229 Q_UNUSED(cm)
230
231 if (!QApplication::focusWidget()) {
232 auto idx = t->instantTextMessagingModel()->
233 index(t->instantTextMessagingModel()->rowCount()-1, 0);
234 GlobalSystemTray::instance()
235 .showMessage("Ring",
236 QString(tr("Message incoming from %1")).arg(
237 idx.data((int)Media::TextRecording::Role::AuthorDisplayname).toString()));
238 QApplication::alert(this, 5000);
239 }
Edric Milareta0ebd062016-01-13 12:18:23 -0500240}
241
242void
243CallWidget::setupSmartListMenu() {
244 ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
245 connect(ui->smartList, &QListView::customContextMenuRequested, [=](const QPoint& pos){
246 auto idx = ui->smartList->currentIndex();
247 if (not idx.isValid())
248 return;
249 QPoint globalPos = ui->smartList->mapToGlobal(pos);
250 QMenu menu;
251
Edric Milaret9949b342016-02-02 12:25:08 -0500252 QVector<ContactMethod*> contactMethods = RecentModel::instance()
253 .getContactMethods(RecentModel::instance().peopleProxy()->mapToSource(idx));
254 if (contactMethods.isEmpty())
Edric Milareta0ebd062016-01-13 12:18:23 -0500255 return;
Edric Milaret9949b342016-02-02 12:25:08 -0500256
257 if (contactMethods.size() == 1) {
258 auto contactMethod = contactMethods.at(0);
259 auto copyAction = new QAction(tr("Copy number"), this);
260 menu.addAction(copyAction);
261 connect(copyAction, &QAction::triggered, [contactMethod]() {
262 QApplication::clipboard()->setText(contactMethod->uri());
Edric Milareta0ebd062016-01-13 12:18:23 -0500263 });
Edric Milaret9949b342016-02-02 12:25:08 -0500264 if (not contactMethod->contact() || contactMethod->contact()->isPlaceHolder()) {
265 auto addExisting = new QAction(tr("Add to contact"), this);
266 menu.addAction(addExisting);
267 connect(addExisting, &QAction::triggered, [globalPos, contactMethod]() {
268 ContactPicker contactPicker(contactMethod);
269 contactPicker.move(globalPos.x(), globalPos.y() - (contactPicker.height()/2));
270 contactPicker.exec();
271 });
272 }
273 }
274 else {
275 auto callMenu = menu.addMenu(tr("Call Number"));
276 auto copyMenu = menu.addMenu(tr("Copy Number"));
277 for (auto cM : contactMethods) {
278 auto uri = cM->uri();
279 auto copyAction = new QAction(tr("Copy %1").arg(uri), this);
280 copyMenu->addAction(copyAction);
281 connect(copyAction, &QAction::triggered, [uri]() {
282 QApplication::clipboard()->setText(uri);
283 });
284 auto callAction = new QAction(tr("Call %1").arg(uri), this);
285 callMenu->addAction(callAction);
286 connect(callAction, &QAction::triggered, [cM]() {
287 Call* c = CallModel::instance().dialingCall(cM);
288 c->performAction(Call::Action::ACCEPT);
289 });
290 }
Edric Milareta0ebd062016-01-13 12:18:23 -0500291 }
292 menu.exec(globalPos);
293 });
294}
295
296void
Edric Milaret67007d12015-05-07 09:40:09 -0400297CallWidget::findRingAccount(QModelIndex idx1, QModelIndex idx2, QVector<int> vec)
298{
299 Q_UNUSED(idx1)
300 Q_UNUSED(idx2)
301 Q_UNUSED(vec)
302
Edric Milareta3e47282015-10-23 15:20:30 -0400303 auto a_count = AccountModel::instance().rowCount();
Edric Milaret67007d12015-05-07 09:40:09 -0400304 auto found = false;
305 for (int i = 0; i < a_count; ++i) {
Edric Milareta3e47282015-10-23 15:20:30 -0400306 auto idx = AccountModel::instance().index(i, 0);
Edric Milaret67007d12015-05-07 09:40:09 -0400307 auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
308 if ((Account::Protocol)protocol.toUInt() == Account::Protocol::RING) {
309 auto username = idx.data(static_cast<int>(Account::Role::Username));
Edric Milareted0b2802015-10-01 15:10:02 -0400310 ui->ringIdLabel->setText(username.toString());
Edric Milaret67007d12015-05-07 09:40:09 -0400311 found = true;
312 return;
313 }
314 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500315 if (not found) {
Edric Milaret53ac6e52015-09-14 13:37:06 -0400316 ui->ringIdLabel->setText(tr("NO RING ACCOUNT FOUND"));
Edric Milaret67007d12015-05-07 09:40:09 -0400317 }
318}
319
320void
321CallWidget::findRingAccount()
322{
Edric Milareta3e47282015-10-23 15:20:30 -0400323 auto a_count = AccountModel::instance().rowCount();
Edric Milaret627500d2015-03-27 16:41:40 -0400324 auto found = false;
325 for (int i = 0; i < a_count; ++i) {
Edric Milareta3e47282015-10-23 15:20:30 -0400326 auto idx = AccountModel::instance().index(i, 0);
Edric Milaret627500d2015-03-27 16:41:40 -0400327 auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
328 if ((Account::Protocol)protocol.toUInt() == Account::Protocol::RING) {
Edric Milareta3e47282015-10-23 15:20:30 -0400329 auto account = AccountModel::instance().getAccountByModelIndex(idx);
Edric Milaret68779c42015-07-09 16:53:03 -0400330 if (account->displayName().isEmpty())
331 account->displayName() = account->alias();
332 auto username = account->username();
Edric Milareted0b2802015-10-01 15:10:02 -0400333 ui->ringIdLabel->setText(username);
Edric Milaret627500d2015-03-27 16:41:40 -0400334 found = true;
335 return;
336 }
337 }
338 if (!found) {
Edric Milareted0b2802015-10-01 15:10:02 -0400339 ui->ringIdLabel->setText(tr("NO RING ACCOUNT FOUND"));
Edric Milaret4097d2f2016-02-09 14:41:50 -0500340 auto wizardDialog = new WizardDialog();
Edric Milaret559bda52015-04-29 17:02:31 -0400341 wizardDialog->exec();
342 delete wizardDialog;
Edric Milaret627500d2015-03-27 16:41:40 -0400343 }
344}
345
346void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500347CallWidget::callIncoming(Call* call)
Edric Milaret627500d2015-03-27 16:41:40 -0400348{
Edric Milaret00a32252016-01-19 10:37:13 -0500349 if (!QApplication::focusWidget()) {
350 GlobalSystemTray::instance()
351 .showMessage("Ring",
352 QString(tr("Call incoming from %1")).arg(call->formattedName()));
Edric Milaret2cf34292015-06-22 16:27:03 -0400353 QApplication::alert(this, 5000);
354 }
355
Edric Milaret6b68a482016-02-01 15:23:44 -0500356 ui->callerIdLabel->setText(QString(tr("%1", "%1 is the name of the caller"))
357 .arg(call->formattedName()));
358 ui->callerPhoto->setPixmap(
359 QPixmap::fromImage(
360 GlobalInstances::pixmapManipulator()
361 .callPhoto(call, QSize(130,130)).value<QImage>()));
Edric Milaret6456baa2015-05-21 12:18:07 -0400362 setActualCall(call);
Edric Milaret627500d2015-03-27 16:41:40 -0400363}
364
365void
366CallWidget::on_acceptButton_clicked()
367{
368 if (actualCall_ != nullptr)
Edric Milaret53f57b62015-05-11 11:02:17 -0400369 actualCall_->performAction(Call::Action::ACCEPT);
Edric Milaret627500d2015-03-27 16:41:40 -0400370}
371
372void
373CallWidget::on_refuseButton_clicked()
374{
375 if (actualCall_ == nullptr)
376 return;
377 actualCall_->performAction(Call::Action::REFUSE);
Nicolas Jager13745062016-02-12 18:56:40 -0500378 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Edric Milaret6456baa2015-05-21 12:18:07 -0400379 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -0400380}
381
382void
Edric Milaret67007d12015-05-07 09:40:09 -0400383CallWidget::callStateChanged(Call* call, Call::State previousState)
384{
Edric Milaret627500d2015-03-27 16:41:40 -0400385 Q_UNUSED(previousState)
Edric Milaret4b1be4a2016-01-15 16:49:20 -0500386 if (call == nullptr
387 || call != actualCall_)
Edric Milaretb5b49072015-05-08 11:56:07 -0400388 return;
Edric Milareted0b2802015-10-01 15:10:02 -0400389
Edric Milaret4b1be4a2016-01-15 16:49:20 -0500390 if (call->state() == Call::State::OVER) {
Edric Milaret6456baa2015-05-21 12:18:07 -0400391 setActualCall(nullptr);
Edric Milaret6b68a482016-02-01 15:23:44 -0500392 RecentModel::instance().selectionModel()->clear();
Edric Milaret627500d2015-03-27 16:41:40 -0400393 }
Edric Milaret6b68a482016-02-01 15:23:44 -0500394 callStateToView(call);
Edric Milaret627500d2015-03-27 16:41:40 -0400395}
396
397void
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400398CallWidget::atExit()
399{
Edric Milaret627500d2015-03-27 16:41:40 -0400400}
Edric Milaret67007d12015-05-07 09:40:09 -0400401
402void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500403CallWidget::on_contactView_doubleClicked(const QModelIndex& index)
Edric Milaret67007d12015-05-07 09:40:09 -0400404{
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400405 if (not index.isValid())
406 return;
407
Edric Milaret2afd2bf2015-07-21 17:12:25 -0400408 ContactMethod* uri = nullptr;
Edric Milaret67007d12015-05-07 09:40:09 -0400409
Edric Milaret7d40a4a2015-05-13 13:01:15 -0400410 auto var = index.child(0,0).data(
411 static_cast<int>(Person::Role::Object));
412 if (var.isValid()) {
413 Person* person = var.value<Person*>();
Edric Milaret2afd2bf2015-07-21 17:12:25 -0400414 if (person->phoneNumbers().size() == 1) {
415 uri = person->phoneNumbers().at(0);
416 } else if (person->phoneNumbers().size() > 1) {
417 ContactMethodPicker dlg(person->phoneNumbers());
418 auto pos = QCursor::pos();
419 dlg.move(pos.x(), pos.y());
420 if (dlg.exec())
421 uri = dlg.getSelected();
422 }
423 if (uri) {
Edric Milareta3e47282015-10-23 15:20:30 -0400424 auto outCall = CallModel::instance().dialingCall(uri);
Edric Milaret2afd2bf2015-07-21 17:12:25 -0400425 outCall->performAction(Call::Action::ACCEPT);
Edric Milareted0b2802015-10-01 15:10:02 -0400426 ui->mainTabMenu->setCurrentIndex(0);
427 ui->smartList->setFocus();
Edric Milaret67007d12015-05-07 09:40:09 -0400428 }
429 }
Edric Milaret67007d12015-05-07 09:40:09 -0400430}
Edric Milaret53f57b62015-05-11 11:02:17 -0400431
Edric Milaret6456baa2015-05-21 12:18:07 -0400432void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500433CallWidget::on_historyList_doubleClicked(const QModelIndex& index)
Edric Milaret53f57b62015-05-11 11:02:17 -0400434{
Edric Milaret12353822015-05-14 14:41:09 -0400435 if (not index.isValid())
436 return;
437
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400438 auto number = index.data(static_cast<int>(Call::Role::ContactMethod)).value<ContactMethod*>();
439 if (number) {
Edric Milareta3e47282015-10-23 15:20:30 -0400440 auto outCall = CallModel::instance().dialingCall(number);
Edric Milaret53f57b62015-05-11 11:02:17 -0400441 outCall->performAction(Call::Action::ACCEPT);
Edric Milareted0b2802015-10-01 15:10:02 -0400442 ui->mainTabMenu->setCurrentIndex(0);
443 ui->smartList->setFocus();
Edric Milaret53f57b62015-05-11 11:02:17 -0400444 }
445}
Edric Milaret6456baa2015-05-21 12:18:07 -0400446
Edric Milaret6b68a482016-02-01 15:23:44 -0500447void CallWidget::callStateToView(Call* value)
448{
449 if (value) {
450 switch (value->state()) {
451 case Call::State::INCOMING:
452 if (not value->account()->isAutoAnswer())
453 ui->stackedWidget->setCurrentWidget(ui->callInvitePage);
454 else
455 ui->stackedWidget->setCurrentWidget(ui->videoPage);
456 break;
457 case Call::State::CURRENT:
Edric Milareta86e3f52016-03-14 16:28:57 -0400458 case Call::State::CONFERENCE:
Edric Milaret854c6b44d2016-03-08 11:00:48 -0500459 case Call::State::HOLD:
Edric Milaret6b68a482016-02-01 15:23:44 -0500460 ui->stackedWidget->setCurrentWidget(ui->videoPage);
461 break;
462 case Call::State::OVER:
463 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
464 break;
465 case Call::State::INITIALIZATION:
466 case Call::State::CONNECTED:
467 case Call::State::RINGING:
Edric Milaret854c6b44d2016-03-08 11:00:48 -0500468 case Call::State::FAILURE:
Edric Milaret6b68a482016-02-01 15:23:44 -0500469 case Call::State::ERROR:
470 ui->stackedWidget->setCurrentWidget(ui->outboundCallPage);
471 break;
472 default:
Edric Milaret854c6b44d2016-03-08 11:00:48 -0500473 qWarning() << "Call state not handled doing nothing : "
474 << value->toHumanStateName();
Edric Milaret6b68a482016-02-01 15:23:44 -0500475 break;
476 }
Nicolas Jager13745062016-02-12 18:56:40 -0500477 }
Edric Milaret6b68a482016-02-01 15:23:44 -0500478}
479
Edric Milaret6456baa2015-05-21 12:18:07 -0400480void
481CallWidget::setActualCall(Call* value)
482{
483 actualCall_ = value;
Edric Milaret80e0b212015-10-16 10:07:43 -0400484 CallModel::instance().selectCall(value);
485 ui->videoWidget->pushRenderer(value);
Edric Milareta86e3f52016-03-14 16:28:57 -0400486 ui->instantMessagingWidget->setMediaText(actualCall_);
Edric Milaret6b68a482016-02-01 15:23:44 -0500487 callStateToView(value);
Edric Milaret6456baa2015-05-21 12:18:07 -0400488}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400489
490void
Edric Milareted0b2802015-10-01 15:10:02 -0400491CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400492{
493 if (actualCall_)
494 actualCall_->performAction(Call::Action::REFUSE);
495}
Edric Milareted0b2802015-10-01 15:10:02 -0400496
497void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500498CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400499{
Edric Milareta3e47282015-10-23 15:20:30 -0400500 auto realIndex = RecentModel::instance().peopleProxy()->mapToSource(index);
501 if (RecentModel::instance().hasActiveCall(realIndex))
Edric Milareted0b2802015-10-01 15:10:02 -0400502 return;
503
504 ContactMethod* m = nullptr;
505 if (auto cm = realIndex.data((int)Call::Role::ContactMethod).value<ContactMethod*>()) {
506 m = cm;
507 } else {
508 if (auto person = realIndex.data((int)Person::Role::Object).value<Person*>()) {
509 m = person->phoneNumbers().first();
510 }
511 }
Edric Milareta3e47282015-10-23 15:20:30 -0400512 if (m && !RecentModel::instance().index(0, 0, realIndex).isValid()) {
513 Call* c = CallModel::instance().dialingCall(m);
Edric Milareted0b2802015-10-01 15:10:02 -0400514 c->performAction(Call::Action::ACCEPT);
Edric Milaret6b68a482016-02-01 15:23:44 -0500515 setActualCall(c);
Edric Milareted0b2802015-10-01 15:10:02 -0400516 }
517}
518
519void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500520CallWidget::smartListSelectionChanged(const QItemSelection& newSel, const QItemSelection& oldSel) {
Edric Milareted0b2802015-10-01 15:10:02 -0400521
522 Q_UNUSED(oldSel)
523
Edric Milaretab12d022015-12-04 16:09:44 -0500524 if (newSel.indexes().empty())
Edric Milaret6b68a482016-02-01 15:23:44 -0500525 return ui->stackedWidget->setCurrentWidget(ui->welcomePage);
526
Edric Milareted0b2802015-10-01 15:10:02 -0400527 auto newIdx = newSel.indexes().first();
Edric Milaret80e0b212015-10-16 10:07:43 -0400528 if (not newIdx.isValid())
Edric Milareted0b2802015-10-01 15:10:02 -0400529 return;
530
Edric Milaret6b68a482016-02-01 15:23:44 -0500531 auto newIdxCall = RecentModel::instance().getActiveCall(newIdx);
Edric Milareta0ebd062016-01-13 12:18:23 -0500532 if (newIdxCall && newIdxCall != actualCall_) {
Edric Milareted0b2802015-10-01 15:10:02 -0400533 setActualCall(newIdxCall);
Edric Milareta0ebd062016-01-13 12:18:23 -0500534 } else if (newIdxCall == nullptr){
535 setActualCall(nullptr);
Edric Milaretf6f608d2016-02-02 15:06:33 -0500536 ui->instantMessagingWidget->hide();
Edric Milaret6b68a482016-02-01 15:23:44 -0500537 showIMOutOfCall(newIdx);
Edric Milareted0b2802015-10-01 15:10:02 -0400538 } else {
539 setActualCall(nullptr);
Edric Milaretf6f608d2016-02-02 15:06:33 -0500540 ui->instantMessagingWidget->hide();
Edric Milaret7ef617b2016-02-01 15:40:57 -0500541 if (imConnection_)
542 disconnect(imConnection_);
Edric Milareted0b2802015-10-01 15:10:02 -0400543 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
544 }
545}
546
547void
548CallWidget::placeCall()
549{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500550 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400551 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500552 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400553 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500554 ui->ringContactLineEdit->clear();
Edric Milareted0b2802015-10-01 15:10:02 -0400555}
556
557void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500558CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400559{
560 emit NavigationRequested(ScreenEnum::ConfScreen);
561}
562
563void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500564CallWidget::contactButtonClicked(bool checked)
Edric Milareted0b2802015-10-01 15:10:02 -0400565{
Edric Milareted0b2802015-10-01 15:10:02 -0400566 ui->mainTabMenu->setCurrentIndex(checked ? 1 : 0);
567}
568
569void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500570CallWidget::historicButtonClicked(bool checked)
Edric Milareted0b2802015-10-01 15:10:02 -0400571{
Edric Milareted0b2802015-10-01 15:10:02 -0400572 ui->mainTabMenu->setCurrentIndex(checked ? 2 : 0);
573}
Nicolas Jager97a21b42015-12-03 16:55:45 -0500574
575void
576CallWidget::on_ringContactLineEdit_returnPressed()
577{
Edric Milaret00593d12016-01-19 11:57:46 -0500578 auto cm = PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text());
579 time_t currentTime;
580 ::time(&currentTime);
581 cm->setLastUsed(currentTime);
Edric Milaret8001f6f2016-01-27 09:55:12 -0500582 ui->ringContactLineEdit->clear();
Nicolas Jager5e845d52016-02-18 13:26:12 -0500583
584 QModelIndex index = RecentModel::instance().getIndex(cm);
585 RecentModel::instance().selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500586}
587
588void
589CallWidget::on_btnCall_clicked()
590{
591 placeCall();
592}
593
594void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500595CallWidget::btnComBarVideoClicked()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500596{
597 if (not highLightedIndex_.isValid())
598 return;
599
600 on_smartList_doubleClicked(highLightedIndex_);
601}
Edric Milaretab12d022015-12-04 16:09:44 -0500602
603void
Edric Milaret6b68a482016-02-01 15:23:44 -0500604CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500605{
Edric Milaretab12d022015-12-04 16:09:44 -0500606 ui->contactMethodComboBox->clear();
607
Edric Milareta0ebd062016-01-13 12:18:23 -0500608 ui->imNameLabel->setText(QString(tr("Conversation with %1", "%1 is the contact name"))
609 .arg(nodeIdx.data(static_cast<int>(Ring::Role::Name)).toString()));
Edric Milaretab12d022015-12-04 16:09:44 -0500610 auto cmVector = RecentModel::instance().getContactMethods(nodeIdx);
Edric Milareta0ebd062016-01-13 12:18:23 -0500611 ui->contactMethodComboBox->setEnabled(cmVector.size() > 1);
Edric Milaretab12d022015-12-04 16:09:44 -0500612 foreach (const ContactMethod* cm, cmVector) {
Edric Milareta0ebd062016-01-13 12:18:23 -0500613 ui->contactMethodComboBox->addItem(cm->uri());
Edric Milaretab12d022015-12-04 16:09:44 -0500614 }
Edric Milaret6b68a482016-02-01 15:23:44 -0500615 slidePage(ui->messagingPage, true);
Edric Milaretab12d022015-12-04 16:09:44 -0500616}
617
618void
Edric Milaret6a785af2016-03-07 15:39:30 -0500619CallWidget::on_sendIMButton_clicked()
Edric Milaretab12d022015-12-04 16:09:44 -0500620{
Edric Milaret6a785af2016-03-07 15:39:30 -0500621 if (ui->imMessageEdit->text().trimmed().isEmpty())
Edric Milaretab12d022015-12-04 16:09:44 -0500622 return;
623 auto number = ui->contactMethodComboBox->currentText();
624 if (auto cm = PhoneDirectoryModel::instance().getNumber(number)) {
625 QMap<QString, QString> msg;
Edric Milaret6a785af2016-03-07 15:39:30 -0500626 msg["text/plain"] = ui->imMessageEdit->text();
Edric Milaretab12d022015-12-04 16:09:44 -0500627 cm->sendOfflineTextMessage(msg);
Edric Milaret6a785af2016-03-07 15:39:30 -0500628 ui->imMessageEdit->clear();
Edric Milaretab12d022015-12-04 16:09:44 -0500629 } else {
630 qWarning() << "Contact Method not found for " << number;
631 }
632}
633
634void
Edric Milaret6a785af2016-03-07 15:39:30 -0500635CallWidget::on_imMessageEdit_returnPressed()
Edric Milaretab12d022015-12-04 16:09:44 -0500636{
Edric Milaret6a785af2016-03-07 15:39:30 -0500637 on_sendIMButton_clicked();
Edric Milaretab12d022015-12-04 16:09:44 -0500638}
639
640void
641CallWidget::on_contactMethodComboBox_currentIndexChanged(const QString& number)
642{
643 auto cm = PhoneDirectoryModel::instance().getNumber(number);
644 if (auto txtRecording = cm->textRecording()) {
645 ui->listMessageView->setModel(txtRecording->instantMessagingModel());
Edric Milaret7ef617b2016-02-01 15:40:57 -0500646 if (imConnection_)
647 disconnect(imConnection_);
Edric Milaretab12d022015-12-04 16:09:44 -0500648 imConnection_ = connect(txtRecording,
Edric Milareta0ebd062016-01-13 12:18:23 -0500649 SIGNAL(messageInserted(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)),
650 this,
651 SLOT(slotAccountMessageReceived(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)));
Edric Milaret4be72022016-01-19 10:24:13 -0500652 auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
653 if (messagesPresent) {
654 ui->listMessageView->scrollToBottom();
655 txtRecording->setAllRead();
656 }
657 ui->listMessageView->setVisible(messagesPresent);
658 ui->noMessagesLabel->setVisible(!messagesPresent);
659 if (not messagesPresent) {
Edric Milaret49130472016-01-22 10:39:37 -0500660 imVisibleConnection_ = connect(txtRecording->instantMessagingModel(),
661 &QAbstractItemModel::rowsInserted,
662 [this, txtRecording]() {
663 if (imVisibleConnection_)
664 disconnect(imVisibleConnection_);
665 auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
Edric Milaret4be72022016-01-19 10:24:13 -0500666 ui->listMessageView->setVisible(messagesPresent);
667 ui->noMessagesLabel->setVisible(!messagesPresent);
Edric Milaret4be72022016-01-19 10:24:13 -0500668 });
669 }
Edric Milaretab12d022015-12-04 16:09:44 -0500670 }
671}
672
673void
674CallWidget::slotAccountMessageReceived(const QMap<QString,QString> message,
675 ContactMethod* cm,
676 Media::Media::Direction dir)
677{
678 Q_UNUSED(message)
Edric Milaretab12d022015-12-04 16:09:44 -0500679 Q_UNUSED(dir)
680
681 ui->listMessageView->scrollToBottom();
Edric Milaret23fd3fa2016-01-15 15:37:35 -0500682 cm->textRecording()->setAllRead();
Edric Milaretab12d022015-12-04 16:09:44 -0500683}
Edric Milaretfa05d972016-01-13 16:22:04 -0500684
685void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500686CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500687{
688 RecentModel::instance().peopleProxy()->setFilterWildcard(text);
689}
Edric Milareta0ebd062016-01-13 12:18:23 -0500690
Nicolas Jagerca850292016-01-17 14:11:10 -0500691void
692CallWidget::on_imBackButton_clicked()
Edric Milareta0ebd062016-01-13 12:18:23 -0500693{
Edric Milaret6b68a482016-02-01 15:23:44 -0500694 RecentModel::instance().selectionModel()->clear();
695 slidePage(ui->welcomePage);
Nicolas Jagerca850292016-01-17 14:11:10 -0500696}
697
698void
Edric Milaret6b68a482016-02-01 15:23:44 -0500699CallWidget::slidePage(QWidget* widget, bool toRight)
Nicolas Jagerca850292016-01-17 14:11:10 -0500700{
Edric Milaret6b68a482016-02-01 15:23:44 -0500701 short dir = (toRight ? -1 : 1);
Nicolas Jagerca850292016-01-17 14:11:10 -0500702 ui->stackedWidget->setCurrentWidget(widget);
Edric Milaret6b68a482016-02-01 15:23:44 -0500703 pageAnim_->setTargetObject(widget);
704 pageAnim_->setDuration(animDuration_);
705 pageAnim_->setStartValue(QPoint(widget->width() * dir, widget->y()));
706 pageAnim_->setEndValue(QPoint(widget->x(), widget->y()));
707 pageAnim_->setEasingCurve(QEasingCurve::OutQuad);
708 pageAnim_->start();
Nicolas Jagerca850292016-01-17 14:11:10 -0500709}
710
711void
Edric Milaret6b68a482016-02-01 15:23:44 -0500712CallWidget::on_smartList_clicked(const QModelIndex& index)
Nicolas Jagerca850292016-01-17 14:11:10 -0500713{
Edric Milaret6b68a482016-02-01 15:23:44 -0500714 RecentModel::instance().selectionModel()->setCurrentIndex(
715 RecentModel::instance().peopleProxy()->mapToSource(index),
716 QItemSelectionModel::ClearAndSelect);
Edric Milareta0ebd062016-01-13 12:18:23 -0500717}
Edric Milaret7cf39e22016-02-02 12:44:03 -0500718
719void
720CallWidget::on_copyCMButton_clicked()
721{
722 auto text = ui->contactMethodComboBox->currentText();
723 QApplication::clipboard()->setText(text);
724}
Edric Milaret4097d2f2016-02-09 14:41:50 -0500725
726void
727CallWidget::on_shareButton_clicked()
728{
729 Utils::InvokeMailto("Contact me on Ring", QStringLiteral("My RingId is : ") + ui->ringIdLabel->text());
730}