blob: e41a38ede14dbc03ea643fd8bb4756b2014bdd88 [file] [log] [blame]
Edric Milaret627500d2015-03-27 16:41:40 -04001/***************************************************************************
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04002 * Copyright (C) 2015-2018 by Savoir-faire Linux *
Edric Milaret627500d2015-03-27 16:41:40 -04003 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -04004 * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
5 * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04006 * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
Edric Milaret627500d2015-03-27 16:41:40 -04007 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 **************************************************************************/
21
22#include "callwidget.h"
23#include "ui_callwidget.h"
24
Edric Milaret43f3c1e2015-07-16 17:52:47 -040025#include <QClipboard>
Edric Milaret70ae8782016-04-18 16:10:44 -040026#include <QDesktopServices>
Edric Milaret43f3c1e2015-07-16 17:52:47 -040027
Edric Milaret53f57b62015-05-11 11:02:17 -040028#include <memory>
Edric Milaret627500d2015-03-27 16:41:40 -040029
Edric Milarete19c4cd2016-02-12 10:19:44 -050030#include "qrencode.h"
31
Edric Milaret43f3c1e2015-07-16 17:52:47 -040032//ERROR is defined in windows.h
33#include "utils.h"
34#undef ERROR
Edric Milareta0ebd062016-01-13 12:18:23 -050035#undef interface
Edric Milaret43f3c1e2015-07-16 17:52:47 -040036
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040037// lrc
Edric Milareta0ebd062016-01-13 12:18:23 -050038#include "globalinstances.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040039#include "profilemodel.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040040#include "localprofilecollection.h"
Anthony Léonardd47179c2017-03-28 10:39:10 -040041
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040042// client
Edric Milaret559bda52015-04-29 17:02:31 -040043#include "wizarddialog.h"
Edric Milaret83b248c2015-06-02 11:42:23 -040044#include "windowscontactbackend.h"
Edric Milaret43f3c1e2015-07-16 17:52:47 -040045#include "contactpicker.h"
Edric Milaret2cf34292015-06-22 16:27:03 -040046#include "globalsystemtray.h"
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040047#include "conversationitemdelegate.h"
Edric Milaretab12d022015-12-04 16:09:44 -050048#include "imdelegate.h"
Edric Milareta0ebd062016-01-13 12:18:23 -050049#include "pixbufmanipulator.h"
Edric Milaret70ae8782016-04-18 16:10:44 -040050#include "settingskey.h"
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040051#include "lrcinstance.h"
52#include "messagemodel.h"
Edric Milaret25236d92016-03-28 09:40:58 -040053
Nicolas Jager97a21b42015-12-03 16:55:45 -050054CallWidget::CallWidget(QWidget* parent) :
Nicolas Jager74fe46f2016-02-29 14:55:09 -050055 NavWidget(parent),
Edric Milaret7d40a4a2015-05-13 13:01:15 -040056 ui(new Ui::CallWidget),
Edric Milaretab12d022015-12-04 16:09:44 -050057 menu_(new QMenu()),
58 imDelegate_(new ImDelegate())
Edric Milaret627500d2015-03-27 16:41:40 -040059{
60 ui->setupUi(this);
61
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040062 using namespace lrc::api;
Nicolas Jagerca850292016-01-17 14:11:10 -050063
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040064 QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
Edric Milaret3aca8e32015-06-12 10:01:40 -040065
Edric Milareted0b2802015-10-01 15:10:02 -040066 QPixmap logo(":/images/logo-ring-standard-coul.png");
67 ui->ringLogo->setPixmap(logo.scaledToHeight(100, Qt::SmoothTransformation));
68 ui->ringLogo->setAlignment(Qt::AlignHCenter);
69
Edric Milaret1e598592016-09-02 10:10:01 -040070 ui->qrLabel->hide();
Edric Milarete19c4cd2016-02-12 10:19:44 -050071
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040072 videoRenderer_ = nullptr;
Edric Milaret627500d2015-03-27 16:41:40 -040073
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040074 // this line is not welcome here, and must be removed
75 ProfileModel::instance().addCollection<LocalProfileCollection>(LoadOptions::FORCE_ENABLED);
Edric Milaret627500d2015-03-27 16:41:40 -040076
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040077 // select last used account if stored in registry
78 auto accountList = LRCInstance::accountModel().getAccountList();
79 if (!accountList.empty()) {
80 std::string accountIdToStartWith;
81 QSettings settings;
82 if (settings.contains(SettingsKey::selectedAccount)) {
83 accountIdToStartWith = settings
84 .value(SettingsKey::selectedAccount, true)
85 .value<QString>()
86 .toStdString();
87 if (Utils::indexInVector(accountList, accountIdToStartWith) == -1) {
88 accountIdToStartWith = accountList.at(0);
Olivier SOLDANOaf8f2822017-07-11 12:15:18 -040089 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040090 }
91 else {
92 accountIdToStartWith = accountList.at(0);
93 }
94 setSelectedAccount(accountIdToStartWith);
95 // get account index and set the currentAccountWidget selector
96 auto index = Utils::indexInVector(accountList, accountIdToStartWith);
97 if (index != -1) {
98 ui->currentAccountWidget->changeSelectedIndex(index);
99 }
Edric Milaret627500d2015-03-27 16:41:40 -0400100 }
Olivier SOLDANO2100f1c2017-09-06 16:45:20 -0400101
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400102 // conversation list
103 conversationItemDelegate_ = new ConversationItemDelegate();
104 ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
105
106 // setup searchingfor mini spinner
107 miniSpinner_ = new QMovie(":/images/waiting.gif");
108 ui->spinnerLabel->setMovie(miniSpinner_);
109 ui->spinnerLabel->hide();
110
111 // set to welcome view
112 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Olivier SOLDANO2100f1c2017-09-06 16:45:20 -0400113 setupOutOfCallIM();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400114
115 // connections
116 connect(ui->settingsButton, &QPushButton::clicked,
117 this, &CallWidget::settingsButtonClicked);
118
119 connect(ui->videoWidget, SIGNAL(setChatVisibility(bool)),
120 ui->instantMessagingWidget, SLOT(setVisible(bool)));
121
122 connect(ui->videoWidget, &VideoView::videoSettingsClicked,
123 this, &CallWidget::settingsButtonClicked);
124
125 connect(ui->buttonConversations, &QPushButton::clicked,
126 this, &CallWidget::conversationsButtonClicked);
127
128 connect(ui->buttonInvites, &QPushButton::clicked,
129 this, &CallWidget::invitationsButtonClicked);
130
131 connect(ui->currentAccountWidget, &CurrentAccountWidget::currentAccountChanged,
132 this, &CallWidget::currentAccountChanged);
133
134 // TODO(new lrc)
135 connect(&ProfileModel::instance(), &ProfileModel::dataChanged,
136 ui->currentAccountWidget, &CurrentAccountWidget::setPhoto);
137
138 connect(ui->smartList, &QListView::customContextMenuRequested,
139 this, &CallWidget::slotCustomContextMenuRequested);
140
141 connect(ui->smartList, &SmartListView::btnAcceptInviteClicked,
142 this, &CallWidget::slotAcceptInviteClicked);
143
144 connect(ui->smartList, &SmartListView::btnBlockInviteClicked,
145 this, &CallWidget::slotBlockInviteClicked);
146
147 connect(ui->smartList, &SmartListView::btnIgnoreInviteClicked,
148 this, &CallWidget::slotIgnoreInviteClicked);
149
150 connect(&LRCInstance::behaviorController(), &BehaviorController::showCallView,
151 this, &CallWidget::slotShowCallView);
152
153 connect(&LRCInstance::behaviorController(), &BehaviorController::showIncomingCallView,
154 this, &CallWidget::slotShowIncomingCallView);
155
156 connect(&LRCInstance::behaviorController(), &BehaviorController::showChatView,
157 this, &CallWidget::slotShowChatView);
Edric Milaret627500d2015-03-27 16:41:40 -0400158}
159
160CallWidget::~CallWidget()
161{
162 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400163 delete menu_;
Edric Milaretab12d022015-12-04 16:09:44 -0500164 delete imDelegate_;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400165 delete conversationItemDelegate_;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500166}
167
168void
Edric Milareta0ebd062016-01-13 12:18:23 -0500169CallWidget::setupOutOfCallIM()
170{
171 ui->listMessageView->setItemDelegate(imDelegate_);
172 ui->listMessageView->setContextMenuPolicy(Qt::ActionsContextMenu);
173
174 auto copyAction = new QAction(tr("Copy"), this);
175 ui->listMessageView->addAction(copyAction);
Olivier SOLDANO1f41a0d2017-08-18 16:30:20 -0400176
Edric Milareta0ebd062016-01-13 12:18:23 -0500177 connect(copyAction, &QAction::triggered, [=]() {
178 auto idx = ui->listMessageView->currentIndex();
179 if (idx.isValid()) {
180 auto text = ui->listMessageView->model()->data(idx);
181 QApplication::clipboard()->setText(text.value<QString>());
182 }
183 });
Edric Milaret00a32252016-01-19 10:37:13 -0500184}
185
186void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400187CallWidget::onIncomingMessage(const std::string& convUid,
188 uint64_t interactionId,
189 const lrc::api::interaction::Info& interaction)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400190{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400191 Q_UNUSED(interactionId);
Edric Milaret00a32252016-01-19 10:37:13 -0500192 if (!QApplication::focusWidget()) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400193 Utils::showSystemNotification(this,
194 QString(tr("Message incoming from %1"))
195 .arg(QString::fromStdString(interaction.body)));
Edric Milaret00a32252016-01-19 10:37:13 -0500196 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400197 updateConversationView(convUid);
198 ui->conversationsFilterWidget->update();
Edric Milareta0ebd062016-01-13 12:18:23 -0500199}
200
201void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400202CallWidget::setupSmartListContextMenu(const QPoint& pos)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400203{
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400204 QPoint globalPos = ui->smartList->mapToGlobal(pos);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400205 auto index = ui->smartList->indexAt(pos);
206 if (not index.isValid()) {
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400207 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400208 }
209
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400210 auto convModel = LRCInstance::getCurrentConversationModel();
211 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID))
212 .value<QString>()
213 .toStdString();
214 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
215 auto contactUid = (*conversation).participants.at(0);
216 auto contact = LRCInstance::getCurrentAccountInfo().contactModel.get()->getContact(contactUid);
217
218 if (!Utils::isContactValid(contactUid, *convModel)) {
219 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400220 }
221
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400222 QMenu menu;
223
224 // video call
225 auto videoCallAction = new QAction(tr("Start video call"), this);
226 menu.addAction(videoCallAction);
227 connect(videoCallAction, &QAction::triggered,
228 [this, convUid, conversation, convModel]() {
229 convModel->placeCall(convUid);
230 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
231 if (convUid != selectedConvUid()) {
232 selectConversation(*conversation, *convModel);
233 }
234 });
235 // audio call
236 auto audioCallAction = new QAction(tr("Start audio call"), this);
237 menu.addAction(audioCallAction);
238 connect(audioCallAction, &QAction::triggered,
239 [this, convUid, conversation, convModel]() {
240 convModel->placeAudioOnlyCall(convUid);
241 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
242 if (convUid != selectedConvUid()) {
243 selectConversation(*conversation, *convModel);
244 }
245 });
246
247 if (contact.profileInfo.type == lrc::api::profile::Type::RING) {
248 // separator
249 menu.addSeparator();
250
251 // clear conversation
252 auto clearConversationAction = new QAction(tr("Clear conversation"), this);
253 menu.addAction(clearConversationAction);
254 connect(clearConversationAction, &QAction::triggered,
255 [convUid]() {
256 LRCInstance::getCurrentConversationModel()->clearHistory(convUid);
257 });
258 // block contact
259 auto blockContactAction = new QAction(tr("Block contact"), this);
260 menu.addAction(blockContactAction);
261 connect(blockContactAction, &QAction::triggered,
262 [convUid]() {
263 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
264 });
265
266 // separator
267 menu.addSeparator();
268
269 // copy number(infohash)
270 auto copyNumberAction = new QAction(tr("Copy number"), this);
271 menu.addAction(copyNumberAction);
272 connect(copyNumberAction, &QAction::triggered,
273 [contact]() {
274 QApplication::clipboard()->setText(
275 QString::fromStdString(contact.profileInfo.uri)
276 );
277 });
278 }
279 smartListModel_->isContextMenuOpen_ = true;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400280 menu.exec(globalPos);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400281 smartListModel_->isContextMenuOpen_ = false;
Edric Milareta0ebd062016-01-13 12:18:23 -0500282}
283
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400284void
285CallWidget::setupQRCode(QString ringID)
Edric Milarete19c4cd2016-02-12 10:19:44 -0500286{
Anthony Léonarda86a8972016-12-15 10:33:47 -0500287 auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
Edric Milaret6d0e5312016-04-04 16:30:22 -0400288 0, //Let the version be decided by libqrencode
289 QR_ECLEVEL_L, // Lowest level of error correction
Edric Milarete19c4cd2016-02-12 10:19:44 -0500290 QR_MODE_8, // 8-bit data mode
291 1);
292 if (not rcode) {
293 qWarning() << "Failed to generate QR code: " << strerror(errno);
294 return;
295 }
296
297 auto margin = 5;
298 int qrwidth = rcode->width + margin * 2;
299 QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono);
300 QPainter painter;
301 painter.begin(&result);
302 painter.setClipRect(QRect(0, 0, qrwidth, qrwidth));
303 painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
304 painter.setBrush(Qt::black);
305 painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
Edric Milaret74474f52016-05-16 13:36:23 -0400306 unsigned char* p;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500307 p = rcode->data;
308 for(int y = 0; y < rcode->width; y++) {
Edric Milaret74474f52016-05-16 13:36:23 -0400309 unsigned char* row = (p + (y * rcode->width));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500310 for(int x = 0; x < rcode->width; x++) {
311 if(*(row + x) & 0x1) {
312 painter.drawRect(margin + x, margin + y, 1, 1);
313 }
314 }
315
316 }
317 painter.end();
318 QRcode_free(rcode);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400319 ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_),
320 Qt::KeepAspectRatio)));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500321}
322
Olivier SOLDANO2100f1c2017-09-06 16:45:20 -0400323bool
Edric Milaret67007d12015-05-07 09:40:09 -0400324CallWidget::findRingAccount()
325{
Anthony Léonard266dd302017-03-31 14:38:32 -0400326 bool ringAccountFound = false;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400327 auto accountList = LRCInstance::accountModel().getAccountList();
328 for (int i = 0; i < accountList.size(); ++i) {
329 auto accountId = accountList.at(i);
330 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
331 if (accountInfo.profileInfo.type == lrc::api::profile::Type::RING) {
Anthony Léonard266dd302017-03-31 14:38:32 -0400332 ringAccountFound = true;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400333 if (accountInfo.status == lrc::api::account::Status::ERROR_NEED_MIGRATION) {
334 WizardDialog dlg(WizardDialog::MIGRATION);
Edric Milaret57467842016-08-30 13:06:11 -0400335 dlg.exec();
336 }
Edric Milaret627500d2015-03-27 16:41:40 -0400337 }
338 }
Olivier SOLDANO2100f1c2017-09-06 16:45:20 -0400339
Anthony Léonard266dd302017-03-31 14:38:32 -0400340 if (!ringAccountFound) {
Edric Milaret57467842016-08-30 13:06:11 -0400341 WizardDialog wizardDialog;
342 wizardDialog.exec();
Olivier SOLDANO2100f1c2017-09-06 16:45:20 -0400343 if (wizardDialog.result() != QDialog::Accepted) {
344 return false;
345 }
Edric Milaret57467842016-08-30 13:06:11 -0400346 }
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400347
348 ui->currentAccountWidget->update();
349
Olivier SOLDANO2100f1c2017-09-06 16:45:20 -0400350 return true;
Edric Milaret627500d2015-03-27 16:41:40 -0400351}
352
353void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400354CallWidget::on_smartList_clicked(const QModelIndex& index)
Edric Milaret00d34f22016-05-09 16:30:29 -0400355{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400356 Q_UNUSED(index);
Edric Milaret627500d2015-03-27 16:41:40 -0400357}
358
359void
360CallWidget::on_acceptButton_clicked()
361{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400362 auto convModel = LRCInstance::getCurrentConversationModel();
363 auto callModel = LRCInstance::getCurrentCallModel();
364 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
365 callModel->accept(conversation->callId);
Edric Milaret627500d2015-03-27 16:41:40 -0400366}
367
368void
369CallWidget::on_refuseButton_clicked()
370{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400371 auto convModel = LRCInstance::getCurrentConversationModel();
372 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
373 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
374 showConversationView();
Edric Milaret6456baa2015-05-21 12:18:07 -0400375}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400376
377void
Edric Milareted0b2802015-10-01 15:10:02 -0400378CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400379{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400380 auto convModel = LRCInstance::getCurrentConversationModel();
381 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
382 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
383 showConversationView();
Edric Milaretd8528fa2015-07-07 14:13:51 -0400384}
Edric Milareted0b2802015-10-01 15:10:02 -0400385
386void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400387CallWidget::showConversationView()
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400388{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400389 ui->stackedWidget->setCurrentWidget(ui->messagingPage);
390 ui->imMessageEdit->clear();
391 ui->imMessageEdit->setFocus();
392 disconnect(imClickedConnection_);
393 imClickedConnection_ = connect(ui->listMessageView, &QListView::clicked, [this](const QModelIndex& index) {
394 auto urlList = index.data(static_cast<int>(media::TextRecording::Role::LinkList)).value<QList<QUrl>>();
395 if (urlList.size() == 1) {
396 QDesktopServices::openUrl(urlList.at(0));
397 } else if (urlList.size()) {
398 //TODO Handle multiple url in one message
399 }
400 });
401}
402
403void
404CallWidget::selectSmartlistItem(const std::string & convUid)
405{
406 if (convUid.empty()) {
407 return;
408 }
409 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
410 auto convModel = LRCInstance::getCurrentConversationModel();
411 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
412 if (conversation == convModel->allFilteredConversations().end()) {
413 return;
414 }
415 auto contactURI = QString::fromStdString((*conversation).participants[0]);
416 if (contactURI.isEmpty() ||
417 convModel->owner.contactModel->getContact(contactURI.toStdString()).profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
418 return;
419 }
420 for (int row = 0; row < smartListModel_->rowCount(); row++) {
421 QModelIndex index = smartListModel_->index(row);
422 auto indexContactURI = index.data(SmartListModel::Role::URI).value<QString>();
423 if (indexContactURI == contactURI) {
424 ui->smartList->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
425 return;
426 }
427 }
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400428}
429
430void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500431CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400432{
Olivier SOLDANO70279d32017-07-18 15:21:34 -0400433 if (!index.isValid())
434 return;
435
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400436 LRCInstance::getCurrentConversationModel()->placeCall(selectedConvUid());
Edric Milareted0b2802015-10-01 15:10:02 -0400437
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400438 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(selectedConvUid())));
439}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500440
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400441QImage
442CallWidget::imageForConv(const std::string& convUid)
443{
444 return Utils::conversationPhoto(convUid, LRCInstance::getCurrentAccountInfo());
445}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500446
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400447const std::string&
448CallWidget::selectedAccountId()
449{
450 return LRCInstance::getSelectedAccountId();
451}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500452
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400453const std::string&
454CallWidget::selectedConvUid()
455{
456 return LRCInstance::getSelectedConvUid();
Edric Milareted0b2802015-10-01 15:10:02 -0400457}
458
459void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400460CallWidget::smartListSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500461{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400462 Q_UNUSED(deselected);
463 QModelIndexList indices = selected.indexes();
464
465 if (indices.isEmpty()) {
Edric Milareted0b2802015-10-01 15:10:02 -0400466 return;
Anthony Léonardecfe7422017-05-04 14:14:37 -0400467 }
Edric Milareted0b2802015-10-01 15:10:02 -0400468
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400469 auto selectedIndex = indices.at(0);
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500470
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400471 if (not selectedIndex.isValid()) {
472 return;
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400473 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400474
475 selectConversation(selectedIndex);
Edric Milareted0b2802015-10-01 15:10:02 -0400476}
477
478void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400479CallWidget::contactReqListCurrentChanged(const QModelIndex &currentIdx, const QModelIndex &previousIdx)
480{
481 Q_UNUSED(previousIdx)
482
Anthony Léonardecfe7422017-05-04 14:14:37 -0400483 if (currentIdx.isValid()) {
484 ui->contactRequestWidget->setCurrentContactRequest(currentIdx);
485 ui->stackedWidget->setCurrentWidget(ui->contactRequestPage);
486 } else {
487 ui->contactRequestWidget->setCurrentContactRequest(QModelIndex());
488 if (ui->stackedWidget->currentWidget() == ui->contactRequestPage)
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400489 Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
Anthony Léonardecfe7422017-05-04 14:14:37 -0400490 }
Anthony Léonardd47179c2017-03-28 10:39:10 -0400491}
492
493void
Edric Milareted0b2802015-10-01 15:10:02 -0400494CallWidget::placeCall()
495{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500496 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400497 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500498 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400499 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500500 ui->ringContactLineEdit->clear();
Edric1bed3f92016-05-19 10:24:48 -0400501 ui->callingPhoto->setPixmap(
502 QPixmap::fromImage(
503 GlobalInstances::pixmapManipulator()
504 .callPhoto(c, QSize(130,130)).value<QImage>()));
Edric Milareted0b2802015-10-01 15:10:02 -0400505}
506
507void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400508CallWidget::conversationsButtonClicked()
509{
510 setConversationFilter(lrc::api::profile::Type::RING);
511}
512
513void
514CallWidget::invitationsButtonClicked()
515{
516 setConversationFilter(lrc::api::profile::Type::PENDING);
517}
518
519void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500520CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400521{
522 emit NavigationRequested(ScreenEnum::ConfScreen);
523}
524
525void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400526CallWidget::processContactLineEdit()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500527{
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400528 auto contactLineText = ui->ringContactLineEdit->text();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400529 setConversationFilter(contactLineText);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500530}
531
532void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400533CallWidget::on_ringContactLineEdit_returnPressed()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500534{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400535 // select current temporary item and show conversation
536 auto convModel = LRCInstance::getCurrentConversationModel();
537 auto conversations = convModel->allFilteredConversations();
538 auto contactIsValid = Utils::isContactValid(conversations.at(0).participants.at(0), *convModel);
539 if (!conversations.empty() && contactIsValid) {
540 selectConversation(smartListModel_->index(0));
541 }
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400542}
543
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400544void CallWidget::slotAcceptInviteClicked(const QModelIndex & index)
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400545{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400546 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
547 LRCInstance::getCurrentConversationModel()->makePermanent(convUid.toStdString());
Nicolas Jager97a21b42015-12-03 16:55:45 -0500548}
549
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400550void CallWidget::slotBlockInviteClicked(const QModelIndex & index)
Nicolas Jager97a21b42015-12-03 16:55:45 -0500551{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400552 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
553 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), true);
554}
555
556void CallWidget::slotIgnoreInviteClicked(const QModelIndex & index)
557{
558 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
559 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString());
560}
561
562void CallWidget::slotCustomContextMenuRequested(const QPoint& pos)
563{
564 setupSmartListContextMenu(pos);
565}
566
567void CallWidget::slotShowCallView(const std::string& accountId,
568 const lrc::api::conversation::Info& convInfo)
569{
570 Q_UNUSED(accountId);
571 Q_UNUSED(convInfo);
572 qDebug() << "BehaviorController::showCallView";
573 ui->stackedWidget->setCurrentWidget(ui->videoPage);
574 hideMiniSpinner();
575}
576
577void CallWidget::slotShowIncomingCallView(const std::string& accountId,
578 const lrc::api::conversation::Info& convInfo) {
579 Q_UNUSED(accountId);
580 qDebug() << "BehaviorController::showIncomingCallView";
581 auto callModel = LRCInstance::getCurrentCallModel();
582 auto call = callModel->getCall(convInfo.callId);
583 if (call.isOutgoing) {
584 miniSpinner_->start();
585 ui->spinnerLabel->show();
586 ui->stackedWidget->setCurrentWidget(ui->outboundCallPage);
587 }
588 else {
589 selectSmartlistItem(convInfo.uid);
590 auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
591 auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
592 if (!accountProperties.autoAnswer) {
593 ui->stackedWidget->setCurrentWidget(ui->callInvitePage);
594 }
595 else {
596 ui->stackedWidget->setCurrentWidget(ui->videoPage);
597 }
598 if (!QApplication::focusWidget()) {
599 auto formattedName = Utils::bestNameForConversation(convInfo, *LRCInstance::getCurrentConversationModel());
600 Utils::showSystemNotification(this,
601 QString(tr("Call incoming from %1")).arg(QString::fromStdString(formattedName)));
602 }
603 }
604
605 if (!callModel->hasCall(convInfo.callId)) {
Nicolas Jager97a21b42015-12-03 16:55:45 -0500606 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400607 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500608
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400609 ui->videoWidget->pushRenderer(convInfo.callId);
610 // TODO:(new lrc) in call chat
611 //ui->instantMessagingWidget->setMediaText(actualCall_);
612
613 disconnect(selectedCallChanged_);
614 selectedCallChanged_ = connect(
615 callModel,
616 &lrc::api::NewCallModel::callStatusChanged,
617 [this, callModel](const std::string& callUid) {
618 auto call = callModel->getCall(callUid);
619 qDebug() << "NewCallModel::callStatusChanged: " << static_cast<int>(call.status);
620 }
621 );
622
623 ui->callerPhoto->setPixmap(QPixmap::fromImage(imageForConv(selectedConvUid())));
624}
625
626void CallWidget::slotShowChatView(const std::string& accountId,
627 const lrc::api::conversation::Info& convInfo) {
628 Q_UNUSED(accountId);
629 Q_UNUSED(convInfo);
630 qDebug() << "BehaviorController::showChatView";
631 showConversationView();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500632}
Edric Milaretab12d022015-12-04 16:09:44 -0500633
634void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400635CallWidget::currentAccountChanged(const QModelIndex &current)
Anthony Léonardd47179c2017-03-28 10:39:10 -0400636{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400637 if (!current.isValid()) {
Olivier SOLDANO97c4c2d2017-05-08 13:22:44 -0400638 ui->selectBar->hide();
639 ui->ringIdLabel->setText("");
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400640 return;
Anthony Léonardd47179c2017-03-28 10:39:10 -0400641 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400642 if (ui->selectBar->isHidden()){
643 ui->selectBar->show();
644 }
645
646 auto accountId = current.data(static_cast<int>(AccountListModel::Role::ID)).value<QString>().toStdString();
647
648 setSelectedAccount(accountId);
649}
650
651void
652CallWidget::setSelectedAccount(const std::string& accountId)
653{
654 LRCInstance::setSelectedAccountId(accountId);
655
656 // First, we get back to the welcome view (except if in call)
657 if (ui->stackedWidget->currentWidget() != ui->videoPage &&
658 ui->stackedWidget->currentWidget() != ui->welcomePage) {
659 Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
660 }
661
662 // We setup the ringIdLabel and the QRCode
663 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
664 auto id = accountInfo.registeredName.empty() ? accountInfo.profileInfo.uri : accountInfo.registeredName;
665 auto isRingAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
666 if (isRingAccount) {
667 ui->ringIdLabel->setText(QString::fromStdString(id));
668 setupQRCode(QString::fromStdString(accountInfo.profileInfo.uri));
669 }
670
671 updateSmartList();
672 currentTypeFilter_ = accountInfo.profileInfo.type;
673 LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
674 updateConversationsFilterWidget();
675 connectConversationModel();
676}
677
678void CallWidget::setConversationFilter(lrc::api::profile::Type filter)
679{
680 if (currentTypeFilter_ == filter) {
681 return;
682 }
683 currentTypeFilter_ = filter;
684 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
685}
686
687void CallWidget::updateConversationsFilterWidget()
688{
689 auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
690 if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
691 currentTypeFilter_ = lrc::api::profile::Type::RING;
692 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
693 }
694 ui->conversationsFilterWidget->setVisible(invites);
695 ui->verticalSpacer_3->changeSize(0, 10 * (1 - static_cast<bool>(invites)));
696}
697
698void CallWidget::setConversationFilter(const QString & filter)
699{
700 LRCInstance::getCurrentConversationModel()->setFilter(filter.toStdString());
Anthony Léonardd47179c2017-03-28 10:39:10 -0400701}
702
703void
Edric Milaret6b68a482016-02-01 15:23:44 -0500704CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500705{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400706 QString displayName = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayName)).toString();
707 QString displayId = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayID)).toString();
708 QString contactURI = nodeIdx.data(static_cast<int>(SmartListModel::Role::URI)).toString();
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400709
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400710 bool isContact = false;
711 auto selectedAccountId = LRCInstance::getSelectedAccountId();
712 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);
713 bool isRINGAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
714 try {
715 accountInfo.contactModel->getContact(contactURI.toStdString());
716 isContact = true;
717 }
718 catch (...) {}
719
720 if (!isRINGAccount){
Olivier SOLDANO1f41a0d2017-08-18 16:30:20 -0400721 ui->imMessageEdit->setPlaceholderText("No messaging possible out of call (SIP) ");
722 ui->imMessageEdit->setEnabled(false);
723 ui->sendIMButton->hide();
724 } else {
Olivier SOLDANO1f41a0d2017-08-18 16:30:20 -0400725 ui->imMessageEdit->setPlaceholderText("Type your message here");
726 ui->imMessageEdit->setEnabled(true);
727 ui->sendIMButton->show();
728 }
729
Olivier SOLDANO31b9aac2017-07-14 15:50:09 -0400730 ui->imNameLabel->setText(QString(tr("%1", "%1 is the contact username"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400731 .arg(displayName));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400732
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400733 if (isRINGAccount && displayName != displayId){
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400734 ui->imIdLabel->show();
735 ui->imIdLabel->setText(QString(tr("%1", "%1 is the contact unique identifier"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400736 .arg(displayId));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400737 } else {
738 ui->imIdLabel->hide();
739 }
740
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400741 bool shouldShowSendContactRequestBtn = !isContact && isRINGAccount;
742 ui->sendContactRequestPageButton->setVisible(shouldShowSendContactRequestBtn);
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400743
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400744 showConversationView();
Anthony Léonard041ad392017-07-14 16:44:09 -0400745
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400746 auto currentConversation = Utils::getConversationFromUid(selectedConvUid(),
747 *LRCInstance::getCurrentConversationModel());
748 messageModel_.reset(new MessageModel(*currentConversation, accountInfo, this->parent()));
749 ui->listMessageView->setModel(messageModel_.get());
750 ui->listMessageView->scrollToBottom();
Edric Milaretab12d022015-12-04 16:09:44 -0500751}
752
753void
Edric Milaret6a785af2016-03-07 15:39:30 -0500754CallWidget::on_sendIMButton_clicked()
Edric Milaretab12d022015-12-04 16:09:44 -0500755{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400756 auto msg = ui->imMessageEdit->text();
757 if (msg.trimmed().isEmpty()) return;
758 ui->imMessageEdit->clear();
759 try {
760 LRCInstance::getCurrentConversationModel()->sendMessage(selectedConvUid(), msg.toStdString());
761 } catch (...) {
762 qDebug() << "exception when sending message";
Edric Milaretab12d022015-12-04 16:09:44 -0500763 }
764}
765
766void
Edric Milaret6a785af2016-03-07 15:39:30 -0500767CallWidget::on_imMessageEdit_returnPressed()
Edric Milaretab12d022015-12-04 16:09:44 -0500768{
Edric Milaret6a785af2016-03-07 15:39:30 -0500769 on_sendIMButton_clicked();
Edric Milaretab12d022015-12-04 16:09:44 -0500770}
771
Edric Milaretab12d022015-12-04 16:09:44 -0500772void
773CallWidget::slotAccountMessageReceived(const QMap<QString,QString> message,
774 ContactMethod* cm,
Andreas Traczyke86fb3c2018-08-02 17:38:34 -0400775 media::Media::Direction dir)
Edric Milaretab12d022015-12-04 16:09:44 -0500776{
777 Q_UNUSED(message)
Edric Milaretab12d022015-12-04 16:09:44 -0500778 Q_UNUSED(dir)
779
780 ui->listMessageView->scrollToBottom();
Edric Milaret23fd3fa2016-01-15 15:37:35 -0500781 cm->textRecording()->setAllRead();
Edric Milaretab12d022015-12-04 16:09:44 -0500782}
Edric Milaretfa05d972016-01-13 16:22:04 -0500783
784void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500785CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500786{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400787 Q_UNUSED(text);
788 processContactLineEdit();
Edric Milaretfa05d972016-01-13 16:22:04 -0500789}
Edric Milareta0ebd062016-01-13 12:18:23 -0500790
Nicolas Jagerca850292016-01-17 14:11:10 -0500791void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400792CallWidget::backToWelcomePage()
Edric Milareta0ebd062016-01-13 12:18:23 -0500793{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400794 deselectConversation();
795 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Nicolas Jagerca850292016-01-17 14:11:10 -0500796}
797
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400798void
799CallWidget::hideMiniSpinner()
Olivier SOLDANO19193412017-06-06 12:03:36 -0400800{
801 if(ui->spinnerLabel->isVisible()){
802 miniSpinner_->stop();
803 ui->spinnerLabel->hide();
804 }
805}
806
Nicolas Jagerca850292016-01-17 14:11:10 -0500807void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400808CallWidget::on_imBackButton_clicked()
809{
810 backToWelcomePage();
811}
812
813void
Edric Milaret1e598592016-09-02 10:10:01 -0400814CallWidget::on_qrButton_toggled(bool checked)
815{
816 ui->qrLabel->setVisible(checked);
817}
818
819void
Edric Milaret4097d2f2016-02-09 14:41:50 -0500820CallWidget::on_shareButton_clicked()
821{
Edric Milaret1e598592016-09-02 10:10:01 -0400822 Utils::InvokeMailto(tr("Contact me on Ring"), tr("My RingId is : ") + ui->ringIdLabel->text());
Edric Milaret4097d2f2016-02-09 14:41:50 -0500823}
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400824
825void
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400826CallWidget::on_sendContactRequestPageButton_clicked()
827{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400828 LRCInstance::getCurrentConversationModel()->makePermanent(selectedConvUid());
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400829}
830
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400831void
832CallWidget::on_sendCRBackButton_clicked()
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400833{
Anthony Léonardecfe7422017-05-04 14:14:37 -0400834 ui->stackedWidget->setCurrentWidget(ui->messagingPage);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400835}
Anthony Léonardd47179c2017-03-28 10:39:10 -0400836
837void
838CallWidget::on_pendingCRBackButton_clicked()
839{
Olivier SOLDANO8179e992017-07-19 15:59:19 -0400840 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400841}
Anthony Léonard5cc76412017-04-21 16:52:25 -0400842
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400843bool
844CallWidget::connectConversationModel()
Anthony Léonard5cc76412017-04-21 16:52:25 -0400845{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400846 auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get();
847
848 if (ui->smartList->selectionModel()) {
849 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
Anthony Léonard5cc76412017-04-21 16:52:25 -0400850 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400851
852 QObject::disconnect(modelSortedConnection_);
853 QObject::disconnect(modelUpdatedConnection_);
854 QObject::disconnect(filterChangedConnection_);
855 QObject::disconnect(newConversationConnection_);
856 QObject::disconnect(conversationRemovedConnection_);
857 QObject::disconnect(conversationClearedConnection);
858 QObject::disconnect(interactionStatusUpdatedConnection_);
859 QObject::disconnect(newInteractionConnection_);
860
861 modelSortedConnection_ = QObject::connect(
862 currentConversationModel, &lrc::api::ConversationModel::modelSorted,
863 [this]() {
864 updateConversationsFilterWidget();
865 selectSmartlistItem(selectedConvUid());
866 ui->smartList->update();
867 }
868 );
869 modelUpdatedConnection_ = QObject::connect(
870 currentConversationModel, &lrc::api::ConversationModel::conversationUpdated,
871 [this](const std::string& convUid) {
872 Q_UNUSED(convUid);
873 ui->smartList->update();
874 }
875 );
876 filterChangedConnection_ = QObject::connect(
877 currentConversationModel, &lrc::api::ConversationModel::filterChanged,
878 [this]() {
879 updateSmartList();
880 updateConversationsFilterWidget();
881 ui->smartList->update();
882 }
883 );
884 newConversationConnection_ = QObject::connect(
885 currentConversationModel, &lrc::api::ConversationModel::newConversation,
886 [this](const std::string& convUid) {
887 updateSmartList();
888 updateConversationForNewContact(convUid);
889 ui->conversationsFilterWidget->update();
890 }
891 );
892 conversationRemovedConnection_ = QObject::connect(
893 currentConversationModel, &lrc::api::ConversationModel::conversationRemoved,
894 [this]() {
895 backToWelcomePage();
896 }
897 );
898 conversationClearedConnection = QObject::connect(
899 currentConversationModel, &lrc::api::ConversationModel::conversationCleared,
900 [this](const std::string& convUid) {
901 updateConversationView(convUid);
902 // if currently selected,
903 // switch to welcome screen (deselecting current smartlist item )
904 if (convUid != selectedConvUid()) {
905 return;
906 }
907 backToWelcomePage();
908 }
909 );
910 interactionStatusUpdatedConnection_ = QObject::connect(
911 currentConversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
912 [this](const std::string& convUid) {
913 if (convUid != selectedConvUid()) {
914 return;
915 }
916 updateConversationView(convUid);
917 }
918 );
919 newInteractionConnection_ = QObject::connect(
920 currentConversationModel, &lrc::api::ConversationModel::newInteraction,
921 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
922 onIncomingMessage(convUid, interactionId, interaction);
923 }
924 );
925 currentConversationModel->setFilter("");
926 // clear search field
927 ui->ringContactLineEdit->setText("");
928 return true;
929}
930
931void
932CallWidget::updateConversationView(const std::string& convUid)
933{
934 if (convUid != selectedConvUid()) {
935 return;
936 }
937
938 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
939 auto currentConversationModel = currentAccountInfo.conversationModel.get();
940 currentConversationModel->clearUnreadInteractions(convUid);
941 ui->conversationsFilterWidget->update();
942 auto currentConversation = Utils::getConversationFromUid(convUid,
943 *currentConversationModel);
944 if (currentConversation == currentConversationModel->allFilteredConversations().end()) {
945 return;
946 }
947 messageModel_.reset(new MessageModel(*currentConversation, currentAccountInfo, this->parent()));
948 ui->listMessageView->setModel(messageModel_.get());
949 ui->listMessageView->scrollToBottom();
950}
951
952void
953CallWidget::selectConversation(const QModelIndex& index)
954{
955 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
956
957 if (currentConversationModel == nullptr || !index.isValid()) {
958 return;
959 }
960
961 const auto item = currentConversationModel->filteredConversation(index.row());
962
963 if (selectConversation(item, *currentConversationModel)) {
964 auto convUid = selectedConvUid();
965 if (!lastConvUid_.compare(convUid)) {
966 return;
967 }
968 lastConvUid_.assign(convUid);
969 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
970 auto callModel = LRCInstance::getCurrentCallModel();
971 auto conversation = Utils::getConversationFromUid(convUid, *currentConversationModel);
972 const auto item = currentConversationModel->filteredConversation(index.row());
973 if (callModel->hasCall(conversation->callId)) {
974 ui->stackedWidget->setCurrentWidget(ui->videoPage);
975 }
976 else {
977 showIMOutOfCall(index);
978 }
979 }
Anthony Léonard5cc76412017-04-21 16:52:25 -0400980}
Anthony Léonardecfe7422017-05-04 14:14:37 -0400981
Anthony Léonard041ad392017-07-14 16:44:09 -0400982bool
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400983CallWidget::selectConversation( const lrc::api::conversation::Info& item,
984 lrc::api::ConversationModel& convModel)
Anthony Léonard041ad392017-07-14 16:44:09 -0400985{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400986 if (selectedConvUid() == item.uid) {
987 return false;
988 } else if (item.participants.size() > 0) {
989 convModel.selectConversation(item.uid);
990 LRCInstance::setSelectedConvId(item.uid);
991 convModel.clearUnreadInteractions(item.uid);
992 ui->conversationsFilterWidget->update();
993 return true;
Anthony Léonard041ad392017-07-14 16:44:09 -0400994 }
Anthony Léonard041ad392017-07-14 16:44:09 -0400995}
996
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400997void
998CallWidget::deselectConversation()
Anthony Léonardecfe7422017-05-04 14:14:37 -0400999{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001000 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1001
1002 if (currentConversationModel == nullptr) {
1003 return;
1004 }
1005
1006 currentConversationModel->selectConversation("");
1007 LRCInstance::setSelectedConvId("");
1008
1009 ui->smartList->selectionModel()->clear();
1010 disconnect(imConnection_);
Anthony Léonardecfe7422017-05-04 14:14:37 -04001011}
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001012
1013void
1014CallWidget::updateConversationForNewContact(const std::string& convUid)
1015{
1016 auto convModel = LRCInstance::getCurrentConversationModel();
1017 if (convModel == nullptr) {
1018 return;
1019 }
1020 ui->ringContactLineEdit->setText("");
1021 auto selectedUid = selectedConvUid();
1022 auto it = Utils::getConversationFromUid(convUid, *convModel);
1023 if (it != convModel->allFilteredConversations().end()) {
1024 try {
1025 auto contact = convModel->owner.contactModel->getContact(it->participants[0]);
1026 if (!contact.profileInfo.uri.empty() && contact.profileInfo.uri.compare(selectedUid) == 0) {
1027 LRCInstance::setSelectedConvId(convUid);
1028 convModel->selectConversation(convUid);
1029 }
1030 } catch (...) {
1031 return;
1032 }
1033 }
1034}
1035
1036void
1037CallWidget::updateSmartList()
1038{
1039 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
1040 smartListModel_.reset(new SmartListModel(currentAccountInfo, this->parent()));
1041 ui->smartList->setModel(smartListModel_.get());
1042 ui->smartList->setItemDelegate(new ConversationItemDelegate());
1043
1044 // smartlist selection
1045 QObject::disconnect(smartlistSelectionConnection_);
1046 smartlistSelectionConnection_ = connect(ui->smartList->selectionModel(),
1047 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
1048 this,
1049 SLOT(smartListSelectionChanged(QItemSelection, QItemSelection)));
1050}
1051
1052void
1053CallWidget::update()
1054{
1055 ui->currentAccountWidget->update();
1056 updateSmartList();
1057 updateConversationsFilterWidget();
1058 connectConversationModel();
1059}