blob: 0bf4c095caf39bee3ba3d075f24fa74b9629529a [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> *
Isa Nanic37ccc1c2018-10-26 14:16:28 -04007 * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> *
Edric Milaret627500d2015-03-27 16:41:40 -04008 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 3 of the License, or *
12 * (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
21 **************************************************************************/
22
23#include "callwidget.h"
24#include "ui_callwidget.h"
25
Andreas Traczyk912242e2018-10-29 14:44:44 -040026#include <QScrollBar>
Edric Milaret43f3c1e2015-07-16 17:52:47 -040027#include <QClipboard>
Edric Milaret70ae8782016-04-18 16:10:44 -040028#include <QDesktopServices>
Isa Nanic601de1d2018-10-23 11:37:26 -040029#include <QComboBox>
Andreas Traczyk43c08232018-10-31 13:42:09 -040030#include <QWebEngineScript>
Edric Milaret43f3c1e2015-07-16 17:52:47 -040031
Edric Milaret53f57b62015-05-11 11:02:17 -040032#include <memory>
Edric Milaret627500d2015-03-27 16:41:40 -040033
Edric Milarete19c4cd2016-02-12 10:19:44 -050034#include "qrencode.h"
35
Edric Milaret43f3c1e2015-07-16 17:52:47 -040036//ERROR is defined in windows.h
37#include "utils.h"
38#undef ERROR
Edric Milareta0ebd062016-01-13 12:18:23 -050039#undef interface
Edric Milaret43f3c1e2015-07-16 17:52:47 -040040
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040041// lrc
Edric Milareta0ebd062016-01-13 12:18:23 -050042#include "globalinstances.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040043#include "profilemodel.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040044#include "localprofilecollection.h"
Anthony Léonardd47179c2017-03-28 10:39:10 -040045
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040046// client
Edric Milaret559bda52015-04-29 17:02:31 -040047#include "wizarddialog.h"
Edric Milaret83b248c2015-06-02 11:42:23 -040048#include "windowscontactbackend.h"
Edric Milaret2cf34292015-06-22 16:27:03 -040049#include "globalsystemtray.h"
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040050#include "conversationitemdelegate.h"
Edric Milareta0ebd062016-01-13 12:18:23 -050051#include "pixbufmanipulator.h"
Edric Milaret70ae8782016-04-18 16:10:44 -040052#include "settingskey.h"
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040053#include "lrcinstance.h"
Andreas Traczyk43c08232018-10-31 13:42:09 -040054#include "animationhelpers.h"
55#include "ringthemeutils.h"
Edric Milaret25236d92016-03-28 09:40:58 -040056
Nicolas Jager97a21b42015-12-03 16:55:45 -050057CallWidget::CallWidget(QWidget* parent) :
Nicolas Jager74fe46f2016-02-29 14:55:09 -050058 NavWidget(parent),
Edric Milaret7d40a4a2015-05-13 13:01:15 -040059 ui(new Ui::CallWidget),
Andreas Traczyk43c08232018-10-31 13:42:09 -040060 menu_(new QMenu())
Edric Milaret627500d2015-03-27 16:41:40 -040061{
62 ui->setupUi(this);
63
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040064 using namespace lrc::api;
Nicolas Jagerca850292016-01-17 14:11:10 -050065
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040066 QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
Edric Milaret3aca8e32015-06-12 10:01:40 -040067
Sébastien Blincba5b522018-12-10 12:48:36 -050068 QPixmap logo(":/images/logo-jami-standard-coul.png");
Edric Milareted0b2802015-10-01 15:10:02 -040069 ui->ringLogo->setPixmap(logo.scaledToHeight(100, Qt::SmoothTransformation));
70 ui->ringLogo->setAlignment(Qt::AlignHCenter);
71
Edric Milaret1e598592016-09-02 10:10:01 -040072 ui->qrLabel->hide();
Edric Milarete19c4cd2016-02-12 10:19:44 -050073
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040074 videoRenderer_ = nullptr;
Edric Milaret627500d2015-03-27 16:41:40 -040075
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040076 // this line is not welcome here, and must be removed
77 ProfileModel::instance().addCollection<LocalProfileCollection>(LoadOptions::FORCE_ENABLED);
Edric Milaret627500d2015-03-27 16:41:40 -040078
Andreas Traczyk43c08232018-10-31 13:42:09 -040079 QSettings settings;
80
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040081 // select last used account if stored in registry
82 auto accountList = LRCInstance::accountModel().getAccountList();
83 if (!accountList.empty()) {
84 std::string accountIdToStartWith;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040085 if (settings.contains(SettingsKey::selectedAccount)) {
86 accountIdToStartWith = settings
87 .value(SettingsKey::selectedAccount, true)
88 .value<QString>()
89 .toStdString();
90 if (Utils::indexInVector(accountList, accountIdToStartWith) == -1) {
91 accountIdToStartWith = accountList.at(0);
Olivier SOLDANOaf8f2822017-07-11 12:15:18 -040092 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040093 }
94 else {
95 accountIdToStartWith = accountList.at(0);
96 }
97 setSelectedAccount(accountIdToStartWith);
Isa Nanic601de1d2018-10-23 11:37:26 -040098 // get account index and set the currentAccountComboBox
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040099 auto index = Utils::indexInVector(accountList, accountIdToStartWith);
100 if (index != -1) {
Isa Nanic601de1d2018-10-23 11:37:26 -0400101 ui->currentAccountComboBox->setCurrentIndex(index);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400102 }
Edric Milaret627500d2015-03-27 16:41:40 -0400103 }
Olivier SOLDANO2100f1c2017-09-06 16:45:20 -0400104
Andreas Traczyk43c08232018-10-31 13:42:09 -0400105 if (settings.contains(SettingsKey::mainSplitterState)) {
106 auto splitterStates = settings.value(SettingsKey::mainSplitterState).toByteArray();
107 ui->mainActivitySplitter->restoreState(splitterStates);
108 }
109
110 ui->mainActivitySplitter->setCollapsible(0, false);
111 ui->splitter->setCollapsible(0, false);
112 ui->splitter->setCollapsible(1, false);
113
Isa Nanic601de1d2018-10-23 11:37:26 -0400114 //disable dropdown shadow on combobox
115 ui->currentAccountComboBox->view()->window()->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
116
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400117 // conversation list
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400118 ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
119
120 // setup searchingfor mini spinner
121 miniSpinner_ = new QMovie(":/images/waiting.gif");
122 ui->spinnerLabel->setMovie(miniSpinner_);
123 ui->spinnerLabel->hide();
124
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400125 // connections
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400126 connect(ui->currentAccountComboBox, &CurrentAccountComboBox::settingsButtonClicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400127 this, &CallWidget::settingsButtonClicked);
128
Andreas Traczyk43c08232018-10-31 13:42:09 -0400129 connect(ui->videoWidget, &VideoView::setChatVisibility,
130 [this](bool visible) {
131 ui->callStackWidget->hide();
132 });
133
134 connect(ui->mainActivitySplitter, &QSplitter::splitterMoved,
135 [this](int pos, int index) {
136 QSettings settings;
137 settings.setValue(SettingsKey::mainSplitterState, ui->mainActivitySplitter->saveState());
138 });
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400139
140 connect(ui->videoWidget, &VideoView::videoSettingsClicked,
141 this, &CallWidget::settingsButtonClicked);
142
Andreas Traczyk43c08232018-10-31 13:42:09 -0400143 connect(ui->btnConversations, &QPushButton::clicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400144 this, &CallWidget::conversationsButtonClicked);
145
Andreas Traczyk43c08232018-10-31 13:42:09 -0400146 connect(ui->btnInvites, &QPushButton::clicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400147 this, &CallWidget::invitationsButtonClicked);
148
Andreas Traczyk43c08232018-10-31 13:42:09 -0400149 connect(ui->smartList, &QTreeView::customContextMenuRequested,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400150 this, &CallWidget::slotCustomContextMenuRequested);
151
152 connect(ui->smartList, &SmartListView::btnAcceptInviteClicked,
153 this, &CallWidget::slotAcceptInviteClicked);
154
155 connect(ui->smartList, &SmartListView::btnBlockInviteClicked,
156 this, &CallWidget::slotBlockInviteClicked);
157
158 connect(ui->smartList, &SmartListView::btnIgnoreInviteClicked,
159 this, &CallWidget::slotIgnoreInviteClicked);
160
161 connect(&LRCInstance::behaviorController(), &BehaviorController::showCallView,
162 this, &CallWidget::slotShowCallView);
163
164 connect(&LRCInstance::behaviorController(), &BehaviorController::showIncomingCallView,
165 this, &CallWidget::slotShowIncomingCallView);
166
167 connect(&LRCInstance::behaviorController(), &BehaviorController::showChatView,
168 this, &CallWidget::slotShowChatView);
Andreas Traczyk55f92cb2018-10-23 12:26:25 -0400169
Isa Nanic601de1d2018-10-23 11:37:26 -0400170 connect(ui->currentAccountComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
171 this, &CallWidget::slotAccountChanged);
172
Andreas Traczyk912242e2018-10-29 14:44:44 -0400173 connect(ui->sendContactRequestButton, &QPushButton::clicked,
174 this, &CallWidget::on_sendContactRequestButton_clicked);
175
176 connect(ui->btnAudioCall, &QPushButton::clicked,
177 this, &CallWidget::on_sendContactRequestButton_clicked);
178
179 connect(ui->btnVideoCall, &QPushButton::clicked,
180 this, &CallWidget::on_sendContactRequestButton_clicked);
181
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400182 connect(ui->currentAccountComboBox, QOverload<int>::of(&CurrentAccountComboBox::currentIndexChanged),
183 [this] {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400184 ui->btnConversations->setChecked(true);
185 ui->btnInvites->setChecked(false);
186 });
187
Andreas Traczyk55f92cb2018-10-23 12:26:25 -0400188 // set first view to welcome view
189 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400190 ui->btnConversations->setChecked(true);
191
192 // chat view
193 ui->messageView->buildView();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500194
195 emit setLeftSizeWidget(ui->currentAccountComboBox->width());
Edric Milaret627500d2015-03-27 16:41:40 -0400196}
197
198CallWidget::~CallWidget()
199{
200 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400201 delete menu_;
Edric Milaret00a32252016-01-19 10:37:13 -0500202}
203
204void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400205CallWidget::onIncomingMessage(const std::string& convUid,
206 uint64_t interactionId,
207 const lrc::api::interaction::Info& interaction)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400208{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400209 Q_UNUSED(interactionId);
Edric Milaret00a32252016-01-19 10:37:13 -0500210 if (!QApplication::focusWidget()) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400211 auto convModel = LRCInstance::getCurrentConversationModel();
212 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
213 auto bestName = Utils::bestNameForConversation(*conversation, *convModel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400214 Utils::showSystemNotification(this,
215 QString(tr("Message incoming from %1"))
Andreas Traczyk43c08232018-10-31 13:42:09 -0400216 .arg(QString::fromStdString(bestName)));
Edric Milaret00a32252016-01-19 10:37:13 -0500217 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400218 if (convUid != selectedConvUid()) {
219 return;
220 }
221
222 auto convModel = LRCInstance::getCurrentConversationModel();
223 convModel->clearUnreadInteractions(convUid);
224 auto currentConversation = Utils::getConversationFromUid(convUid, *convModel);
225 if (currentConversation == convModel->allFilteredConversations().end()) {
226 return;
227 }
228 ui->messageView->printNewInteraction(*convModel, interactionId, interaction);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400229 ui->conversationsFilterWidget->update();
Edric Milareta0ebd062016-01-13 12:18:23 -0500230}
231
232void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400233CallWidget::setupSmartListContextMenu(const QPoint& pos)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400234{
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400235 QPoint globalPos = ui->smartList->mapToGlobal(pos);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400236 auto index = ui->smartList->indexAt(pos);
237 if (not index.isValid()) {
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400238 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400239 }
240
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400241 auto convModel = LRCInstance::getCurrentConversationModel();
242 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID))
243 .value<QString>()
244 .toStdString();
245 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
246 auto contactUid = (*conversation).participants.at(0);
247 auto contact = LRCInstance::getCurrentAccountInfo().contactModel.get()->getContact(contactUid);
248
249 if (!Utils::isContactValid(contactUid, *convModel)) {
250 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400251 }
252
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400253 QMenu menu;
254
255 // video call
256 auto videoCallAction = new QAction(tr("Start video call"), this);
257 menu.addAction(videoCallAction);
258 connect(videoCallAction, &QAction::triggered,
259 [this, convUid, conversation, convModel]() {
260 convModel->placeCall(convUid);
261 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
262 if (convUid != selectedConvUid()) {
263 selectConversation(*conversation, *convModel);
264 }
265 });
266 // audio call
267 auto audioCallAction = new QAction(tr("Start audio call"), this);
268 menu.addAction(audioCallAction);
269 connect(audioCallAction, &QAction::triggered,
270 [this, convUid, conversation, convModel]() {
271 convModel->placeAudioOnlyCall(convUid);
272 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
273 if (convUid != selectedConvUid()) {
274 selectConversation(*conversation, *convModel);
275 }
276 });
277
278 if (contact.profileInfo.type == lrc::api::profile::Type::RING) {
279 // separator
280 menu.addSeparator();
281
282 // clear conversation
283 auto clearConversationAction = new QAction(tr("Clear conversation"), this);
284 menu.addAction(clearConversationAction);
285 connect(clearConversationAction, &QAction::triggered,
286 [convUid]() {
287 LRCInstance::getCurrentConversationModel()->clearHistory(convUid);
288 });
289 // block contact
290 auto blockContactAction = new QAction(tr("Block contact"), this);
291 menu.addAction(blockContactAction);
292 connect(blockContactAction, &QAction::triggered,
293 [convUid]() {
294 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
295 });
296
297 // separator
298 menu.addSeparator();
299
300 // copy number(infohash)
301 auto copyNumberAction = new QAction(tr("Copy number"), this);
302 menu.addAction(copyNumberAction);
303 connect(copyNumberAction, &QAction::triggered,
304 [contact]() {
305 QApplication::clipboard()->setText(
306 QString::fromStdString(contact.profileInfo.uri)
307 );
308 });
309 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400310 smartListModel_->isContextMenuOpen = true;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400311 menu.exec(globalPos);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400312 smartListModel_->isContextMenuOpen = false;
Edric Milareta0ebd062016-01-13 12:18:23 -0500313}
314
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400315void
316CallWidget::setupQRCode(QString ringID)
Edric Milarete19c4cd2016-02-12 10:19:44 -0500317{
Anthony Léonarda86a8972016-12-15 10:33:47 -0500318 auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
Edric Milaret6d0e5312016-04-04 16:30:22 -0400319 0, //Let the version be decided by libqrencode
320 QR_ECLEVEL_L, // Lowest level of error correction
Edric Milarete19c4cd2016-02-12 10:19:44 -0500321 QR_MODE_8, // 8-bit data mode
322 1);
323 if (not rcode) {
324 qWarning() << "Failed to generate QR code: " << strerror(errno);
325 return;
326 }
327
328 auto margin = 5;
329 int qrwidth = rcode->width + margin * 2;
330 QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono);
331 QPainter painter;
332 painter.begin(&result);
333 painter.setClipRect(QRect(0, 0, qrwidth, qrwidth));
334 painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
335 painter.setBrush(Qt::black);
336 painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
Edric Milaret74474f52016-05-16 13:36:23 -0400337 unsigned char* p;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500338 p = rcode->data;
339 for(int y = 0; y < rcode->width; y++) {
Edric Milaret74474f52016-05-16 13:36:23 -0400340 unsigned char* row = (p + (y * rcode->width));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500341 for(int x = 0; x < rcode->width; x++) {
342 if(*(row + x) & 0x1) {
343 painter.drawRect(margin + x, margin + y, 1, 1);
344 }
345 }
346
347 }
348 painter.end();
349 QRcode_free(rcode);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400350 ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_),
351 Qt::KeepAspectRatio)));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500352}
353
Edric Milaret627500d2015-03-27 16:41:40 -0400354void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400355CallWidget::on_smartList_clicked(const QModelIndex& index)
Edric Milaret00d34f22016-05-09 16:30:29 -0400356{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400357 Q_UNUSED(index);
Edric Milaret627500d2015-03-27 16:41:40 -0400358}
359
360void
361CallWidget::on_acceptButton_clicked()
362{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400363 auto convModel = LRCInstance::getCurrentConversationModel();
364 auto callModel = LRCInstance::getCurrentCallModel();
365 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
366 callModel->accept(conversation->callId);
Edric Milaret627500d2015-03-27 16:41:40 -0400367}
368
369void
370CallWidget::on_refuseButton_clicked()
371{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400372 auto convModel = LRCInstance::getCurrentConversationModel();
373 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
374 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
375 showConversationView();
Edric Milaret6456baa2015-05-21 12:18:07 -0400376}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400377
378void
Edric Milareted0b2802015-10-01 15:10:02 -0400379CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400380{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400381 auto convModel = LRCInstance::getCurrentConversationModel();
382 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
383 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
384 showConversationView();
Edric Milaretd8528fa2015-07-07 14:13:51 -0400385}
Edric Milareted0b2802015-10-01 15:10:02 -0400386
387void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400388CallWidget::showConversationView()
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400389{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400390 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
391 ui->messageView->setFocus();
392
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400393}
394
395void
396CallWidget::selectSmartlistItem(const std::string & convUid)
397{
398 if (convUid.empty()) {
399 return;
400 }
401 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
402 auto convModel = LRCInstance::getCurrentConversationModel();
403 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
404 if (conversation == convModel->allFilteredConversations().end()) {
405 return;
406 }
407 auto contactURI = QString::fromStdString((*conversation).participants[0]);
408 if (contactURI.isEmpty() ||
409 convModel->owner.contactModel->getContact(contactURI.toStdString()).profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
410 return;
411 }
412 for (int row = 0; row < smartListModel_->rowCount(); row++) {
413 QModelIndex index = smartListModel_->index(row);
414 auto indexContactURI = index.data(SmartListModel::Role::URI).value<QString>();
415 if (indexContactURI == contactURI) {
416 ui->smartList->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
417 return;
418 }
419 }
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400420}
421
422void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500423CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400424{
Olivier SOLDANO70279d32017-07-18 15:21:34 -0400425 if (!index.isValid())
426 return;
427
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400428 LRCInstance::getCurrentConversationModel()->placeCall(selectedConvUid());
Edric Milareted0b2802015-10-01 15:10:02 -0400429
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400430 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(selectedConvUid())));
431}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500432
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400433QImage
434CallWidget::imageForConv(const std::string& convUid)
435{
436 return Utils::conversationPhoto(convUid, LRCInstance::getCurrentAccountInfo());
437}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500438
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400439const std::string&
440CallWidget::selectedAccountId()
441{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500442 return LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400443}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500444
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400445const std::string&
446CallWidget::selectedConvUid()
447{
448 return LRCInstance::getSelectedConvUid();
Edric Milareted0b2802015-10-01 15:10:02 -0400449}
450
451void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400452CallWidget::smartListSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500453{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400454 Q_UNUSED(deselected);
455 QModelIndexList indices = selected.indexes();
456
457 if (indices.isEmpty()) {
Edric Milareted0b2802015-10-01 15:10:02 -0400458 return;
Anthony Léonardecfe7422017-05-04 14:14:37 -0400459 }
Edric Milareted0b2802015-10-01 15:10:02 -0400460
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400461 auto selectedIndex = indices.at(0);
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500462
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400463 if (not selectedIndex.isValid()) {
464 return;
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400465 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400466
467 selectConversation(selectedIndex);
Edric Milareted0b2802015-10-01 15:10:02 -0400468}
469
470void
471CallWidget::placeCall()
472{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500473 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400474 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500475 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400476 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500477 ui->ringContactLineEdit->clear();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400478 auto photoRect = ui->callingPhoto->frameGeometry();
Edric1bed3f92016-05-19 10:24:48 -0400479 ui->callingPhoto->setPixmap(
480 QPixmap::fromImage(
481 GlobalInstances::pixmapManipulator()
Andreas Traczyk43c08232018-10-31 13:42:09 -0400482 .callPhoto(c, QSize(photoRect.width(), photoRect.height()))
483 .value<QImage>()));
Edric Milareted0b2802015-10-01 15:10:02 -0400484}
485
486void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400487CallWidget::conversationsButtonClicked()
488{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400489 ui->btnConversations->setChecked(true);
490 ui->btnInvites->setChecked(false);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400491 setConversationFilter(lrc::api::profile::Type::RING);
492}
493
494void
495CallWidget::invitationsButtonClicked()
496{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400497 ui->btnConversations->setChecked(false);
498 ui->btnInvites->setChecked(true);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400499 setConversationFilter(lrc::api::profile::Type::PENDING);
500}
501
502void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500503CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400504{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500505 emit setLeftSizeWidget(ui->currentAccountComboBox->width());
Andreas Traczyk7548e732018-12-12 10:47:21 -0500506 emit NavigationRequested(ScreenEnum::SetttingsScreen);
Edric Milareted0b2802015-10-01 15:10:02 -0400507}
508
509void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400510CallWidget::processContactLineEdit()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500511{
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400512 auto contactLineText = ui->ringContactLineEdit->text();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400513 setConversationFilter(contactLineText);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500514}
515
516void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400517CallWidget::on_ringContactLineEdit_returnPressed()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500518{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400519 // select current temporary item and show conversation
520 auto convModel = LRCInstance::getCurrentConversationModel();
521 auto conversations = convModel->allFilteredConversations();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400522 if (!conversations.empty() &&
523 Utils::isContactValid(conversations.at(0).participants.at(0), *convModel)) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400524 selectConversation(smartListModel_->index(0));
525 }
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400526}
527
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400528void CallWidget::slotAcceptInviteClicked(const QModelIndex & index)
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400529{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400530 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
531 LRCInstance::getCurrentConversationModel()->makePermanent(convUid.toStdString());
Nicolas Jager97a21b42015-12-03 16:55:45 -0500532}
533
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400534void CallWidget::slotBlockInviteClicked(const QModelIndex & index)
Nicolas Jager97a21b42015-12-03 16:55:45 -0500535{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400536 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
537 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), true);
538}
539
540void CallWidget::slotIgnoreInviteClicked(const QModelIndex & index)
541{
542 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
543 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString());
544}
545
546void CallWidget::slotCustomContextMenuRequested(const QPoint& pos)
547{
548 setupSmartListContextMenu(pos);
549}
550
Isa Nanic601de1d2018-10-23 11:37:26 -0400551void CallWidget::slotAccountChanged(int index)
552{
553 auto accountList = LRCInstance::accountModel().getAccountList();
554 setSelectedAccount(accountList.at(index));
555}
556
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400557void CallWidget::slotShowCallView(const std::string& accountId,
558 const lrc::api::conversation::Info& convInfo)
559{
560 Q_UNUSED(accountId);
561 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400562 qDebug() << "slotShowCallView";
563 ui->callStackWidget->show();
564 ui->callStackWidget->setCurrentWidget(ui->videoPage);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400565 hideMiniSpinner();
566}
567
568void CallWidget::slotShowIncomingCallView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400569 const lrc::api::conversation::Info& convInfo)
570{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400571 Q_UNUSED(accountId);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400572 qDebug() << "slotShowIncomingCallView";
573
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400574 auto callModel = LRCInstance::getCurrentCallModel();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400575
576 if (!callModel->hasCall(convInfo.callId)) {
Nicolas Jager97a21b42015-12-03 16:55:45 -0500577 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400578 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500579
Andreas Traczyk43c08232018-10-31 13:42:09 -0400580 auto convModel = LRCInstance::getCurrentConversationModel();
581 ui->callerPhoto->setPixmap(QPixmap::fromImage(imageForConv(convInfo.uid)));
582 auto bestName = QString::fromStdString(Utils::bestNameForConversation(convInfo, *convModel));
583 auto bestId = QString::fromStdString(Utils::bestIdForConversation(convInfo, *convModel));
584 auto finalBestId = (bestName != bestId) ? bestId : "";
585
586 auto call = callModel->getCall(convInfo.callId);
587 auto isCallSelected = selectedConvUid() == convInfo.uid;
588
589 if (call.isOutgoing) {
590 if (isCallSelected) {
591 miniSpinner_->start();
592 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
593 ui->spinnerLabel->show();
594 ui->callStackWidget->setCurrentWidget(ui->outgoingCallPage);
595 ui->callStackWidget->show();
596 }
597 } else {
598 if (!QApplication::focusWidget()) {
599 auto formattedName = Utils::bestNameForConversation(convInfo, *convModel);
600 Utils::showSystemNotification(this,
601 QString(tr("Call incoming from %1")).arg(QString::fromStdString(formattedName)));
602 }
603 selectSmartlistItem(convInfo.uid);
604 auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
605 auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
606 if (accountProperties.autoAnswer) {
607 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
608 ui->callStackWidget->setCurrentWidget(ui->videoPage);
609 } else if (isCallSelected) {
610 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
611 ui->callStackWidget->setCurrentWidget(ui->incomingCallPage);
612 ui->callStackWidget->show();
613 }
614 }
615
616 // flashing index widget during call
617 for (int row = 0; row < smartListModel_->rowCount(); row++) {
618 QModelIndex index = smartListModel_->index(row);
619 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
620 if (indexUid == convInfo.uid) {
621 auto widget = ui->smartList->indexWidget(index);
622 if (!widget) {
623 auto blinkingWidget = new AnimatedOverlay(RingTheme::urgentOrange_);
624 ui->smartList->setIndexWidget(index, blinkingWidget);
625 blinkingWidget->show();
626 } else {
627 widget->show();
628 }
629 }
630 }
631
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400632 ui->videoWidget->pushRenderer(convInfo.callId);
Andreas Traczykfd0d7c02018-10-30 17:14:06 -0400633
Andreas Traczyk43c08232018-10-31 13:42:09 -0400634 QFontMetrics primaryCallLabelFontMetrics(ui->callingBestNameLabel->font());
635 QFontMetrics sencondaryCallLabelFontMetrics(ui->callingBestIdLabel->font());
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400636
Andreas Traczyk43c08232018-10-31 13:42:09 -0400637 QString elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callerBestNameLabel->width());
638 ui->callerBestNameLabel->setText(elidedLabel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400639
Andreas Traczyk43c08232018-10-31 13:42:09 -0400640 elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callingBestNameLabel->width());
641 ui->callingBestNameLabel->setText(elidedLabel);
642
643 elidedLabel = sencondaryCallLabelFontMetrics.elidedText(finalBestId, Qt::ElideRight, ui->callingBestIdLabel->width());
644 ui->callingBestIdLabel->setText(elidedLabel);
645
646 ui->smartList->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400647}
648
649void CallWidget::slotShowChatView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400650 const lrc::api::conversation::Info& convInfo)
651{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400652 Q_UNUSED(accountId);
653 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400654
655 for (int row = 0; row < smartListModel_->rowCount(); row++) {
656 QModelIndex index = smartListModel_->index(row);
657 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
658 if (indexUid == convInfo.uid) {
659 if (auto widget = ui->smartList->indexWidget(index)) {
660 widget->hide();
661 widget->deleteLater();
662 ui->smartList->setIndexWidget(index, nullptr);
663 }
664 }
665 }
666
667 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400668 showConversationView();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500669}
Edric Milaretab12d022015-12-04 16:09:44 -0500670
671void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400672CallWidget::setSelectedAccount(const std::string& accountId)
673{
674 LRCInstance::setSelectedAccountId(accountId);
675
676 // First, we get back to the welcome view (except if in call)
677 if (ui->stackedWidget->currentWidget() != ui->videoPage &&
678 ui->stackedWidget->currentWidget() != ui->welcomePage) {
679 Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
680 }
681
682 // We setup the ringIdLabel and the QRCode
683 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
684 auto id = accountInfo.registeredName.empty() ? accountInfo.profileInfo.uri : accountInfo.registeredName;
685 auto isRingAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
686 if (isRingAccount) {
687 ui->ringIdLabel->setText(QString::fromStdString(id));
688 setupQRCode(QString::fromStdString(accountInfo.profileInfo.uri));
689 }
690
691 updateSmartList();
692 currentTypeFilter_ = accountInfo.profileInfo.type;
693 LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
694 updateConversationsFilterWidget();
695 connectConversationModel();
696}
697
698void CallWidget::setConversationFilter(lrc::api::profile::Type filter)
699{
700 if (currentTypeFilter_ == filter) {
701 return;
702 }
703 currentTypeFilter_ = filter;
704 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
705}
706
707void CallWidget::updateConversationsFilterWidget()
708{
709 auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
710 if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
711 currentTypeFilter_ = lrc::api::profile::Type::RING;
712 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
713 }
714 ui->conversationsFilterWidget->setVisible(invites);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400715 ui->conversationsFilterWidget->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400716}
717
718void CallWidget::setConversationFilter(const QString & filter)
719{
720 LRCInstance::getCurrentConversationModel()->setFilter(filter.toStdString());
Anthony Léonardd47179c2017-03-28 10:39:10 -0400721}
722
723void
Edric Milaret6b68a482016-02-01 15:23:44 -0500724CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500725{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400726 QString displayName = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayName)).toString();
727 QString displayId = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayID)).toString();
728 QString contactURI = nodeIdx.data(static_cast<int>(SmartListModel::Role::URI)).toString();
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400729
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400730 bool isContact = false;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500731 auto selectedAccountId = LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400732 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);
733 bool isRINGAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
734 try {
735 accountInfo.contactModel->getContact(contactURI.toStdString());
736 isContact = true;
737 }
738 catch (...) {}
739
Olivier SOLDANO31b9aac2017-07-14 15:50:09 -0400740 ui->imNameLabel->setText(QString(tr("%1", "%1 is the contact username"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400741 .arg(displayName));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400742
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400743 if (isRINGAccount && displayName != displayId){
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400744 ui->imIdLabel->show();
745 ui->imIdLabel->setText(QString(tr("%1", "%1 is the contact unique identifier"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400746 .arg(displayId));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400747 } else {
748 ui->imIdLabel->hide();
749 }
750
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400751 bool shouldShowSendContactRequestBtn = !isContact && isRINGAccount;
Andreas Traczyk912242e2018-10-29 14:44:44 -0400752 ui->sendContactRequestButton->setVisible(shouldShowSendContactRequestBtn);
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400753
Andreas Traczyk43c08232018-10-31 13:42:09 -0400754 auto convModel = LRCInstance::getCurrentConversationModel();
755 auto currentConversation = Utils::getConversationFromUid(selectedConvUid(),
756 *convModel);
757 ui->messageView->clear();
758 ui->messageView->printHistory(*convModel, currentConversation->interactions);
759
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400760 showConversationView();
Anthony Léonard041ad392017-07-14 16:44:09 -0400761
Andreas Traczyk43c08232018-10-31 13:42:09 -0400762 // Contact Avatars
763 auto accInfo = &LRCInstance::getCurrentAccountInfo();
764 auto contactUri = currentConversation->participants.front();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400765 try {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400766 auto& contact = accInfo->contactModel->getContact(contactUri);
767 if (!contact.profileInfo.avatar.empty()) {
768 ui->messageView->setSenderImage(
769 accInfo->contactModel->getContactProfileId(contactUri),
770 contact.profileInfo.avatar);
771 } else {
772 auto avatar = Utils::conversationPhoto(selectedConvUid(), *accInfo);
773 QByteArray ba;
774 QBuffer bu(&ba);
775 avatar.save(&bu, "PNG");
776 std::string avatarString = ba.toBase64().toStdString();
777 ui->messageView->setSenderImage(
778 accInfo->contactModel->getContactProfileId(contactUri),
779 avatarString);
780 }
781 } catch (...) { }
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();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400795 ui->messageView->hideMessages();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400796 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Nicolas Jagerca850292016-01-17 14:11:10 -0500797}
798
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400799void
800CallWidget::hideMiniSpinner()
Olivier SOLDANO19193412017-06-06 12:03:36 -0400801{
802 if(ui->spinnerLabel->isVisible()){
803 miniSpinner_->stop();
804 ui->spinnerLabel->hide();
805 }
806}
807
Nicolas Jagerca850292016-01-17 14:11:10 -0500808void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400809CallWidget::on_imBackButton_clicked()
810{
811 backToWelcomePage();
812}
813
814void
Edric Milaret1e598592016-09-02 10:10:01 -0400815CallWidget::on_qrButton_toggled(bool checked)
816{
817 ui->qrLabel->setVisible(checked);
818}
819
820void
Edric Milaret4097d2f2016-02-09 14:41:50 -0500821CallWidget::on_shareButton_clicked()
822{
Sébastien Blincba5b522018-12-10 12:48:36 -0500823 Utils::InvokeMailto(tr("Contact me on Jami"), tr("My Id is : ") + ui->ringIdLabel->text());
Edric Milaret4097d2f2016-02-09 14:41:50 -0500824}
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400825
826void
Andreas Traczyk912242e2018-10-29 14:44:44 -0400827CallWidget::on_sendContactRequestButton_clicked()
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400828{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400829 LRCInstance::getCurrentConversationModel()->makePermanent(selectedConvUid());
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400830}
831
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400832void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400833CallWidget::on_pendingCRBackButton_clicked()
834{
Olivier SOLDANO8179e992017-07-19 15:59:19 -0400835 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400836}
Anthony Léonard5cc76412017-04-21 16:52:25 -0400837
Andreas Traczyk912242e2018-10-29 14:44:44 -0400838void
839CallWidget::on_btnAudioCall_clicked()
840{
841 auto convUid = LRCInstance::getSelectedConvUid();
842 LRCInstance::getCurrentConversationModel()->placeAudioOnlyCall(convUid);
843 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
844}
845
846void
847CallWidget::on_btnVideoCall_clicked()
848{
849 auto convUid = LRCInstance::getSelectedConvUid();
850 LRCInstance::getCurrentConversationModel()->placeCall(convUid);
851 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
852}
853
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400854bool
855CallWidget::connectConversationModel()
Anthony Léonard5cc76412017-04-21 16:52:25 -0400856{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400857 auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get();
858
859 if (ui->smartList->selectionModel()) {
860 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
Anthony Léonard5cc76412017-04-21 16:52:25 -0400861 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400862
863 QObject::disconnect(modelSortedConnection_);
864 QObject::disconnect(modelUpdatedConnection_);
865 QObject::disconnect(filterChangedConnection_);
866 QObject::disconnect(newConversationConnection_);
867 QObject::disconnect(conversationRemovedConnection_);
868 QObject::disconnect(conversationClearedConnection);
869 QObject::disconnect(interactionStatusUpdatedConnection_);
870 QObject::disconnect(newInteractionConnection_);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400871 QObject::disconnect(interactionRemovedConnection_);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400872
873 modelSortedConnection_ = QObject::connect(
874 currentConversationModel, &lrc::api::ConversationModel::modelSorted,
875 [this]() {
876 updateConversationsFilterWidget();
877 selectSmartlistItem(selectedConvUid());
878 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400879 }
880 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400881 modelUpdatedConnection_ = QObject::connect(
882 currentConversationModel, &lrc::api::ConversationModel::conversationUpdated,
883 [this](const std::string& convUid) {
884 Q_UNUSED(convUid);
885 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400886 }
887 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400888 filterChangedConnection_ = QObject::connect(
889 currentConversationModel, &lrc::api::ConversationModel::filterChanged,
890 [this]() {
891 updateSmartList();
892 updateConversationsFilterWidget();
893 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400894 }
895 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400896 newConversationConnection_ = QObject::connect(
897 currentConversationModel, &lrc::api::ConversationModel::newConversation,
898 [this](const std::string& convUid) {
899 updateSmartList();
900 updateConversationForNewContact(convUid);
901 ui->conversationsFilterWidget->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400902 }
903 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400904 conversationRemovedConnection_ = QObject::connect(
905 currentConversationModel, &lrc::api::ConversationModel::conversationRemoved,
906 [this]() {
907 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400908 }
909 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400910 conversationClearedConnection = QObject::connect(
911 currentConversationModel, &lrc::api::ConversationModel::conversationCleared,
912 [this](const std::string& convUid) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400913 ui->messageView->clear();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400914 // if currently selected,
915 // switch to welcome screen (deselecting current smartlist item )
916 if (convUid != selectedConvUid()) {
917 return;
918 }
919 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400920 }
921 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400922 interactionStatusUpdatedConnection_ = QObject::connect(
923 currentConversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400924 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400925 if (convUid != selectedConvUid()) {
926 return;
927 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400928 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
929 auto currentConversationModel = currentAccountInfo.conversationModel.get();
930 currentConversationModel->clearUnreadInteractions(convUid);
931 ui->conversationsFilterWidget->update();
932 ui->messageView->updateInteraction(*currentConversationModel, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400933 }
934 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400935 newInteractionConnection_ = QObject::connect(
936 currentConversationModel, &lrc::api::ConversationModel::newInteraction,
937 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
938 onIncomingMessage(convUid, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400939 }
940 );
Andreas Traczyk43c08232018-10-31 13:42:09 -0400941 interactionRemovedConnection_ = QObject::connect(
942 currentConversationModel, &lrc::api::ConversationModel::interactionRemoved,
943 [this](const std::string& convUid, uint64_t interactionId) {
944 Q_UNUSED(convUid);
945 ui->messageView->removeInteraction(interactionId);
946 }
947 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400948 currentConversationModel->setFilter("");
949 // clear search field
950 ui->ringContactLineEdit->setText("");
951 return true;
952}
953
954void
955CallWidget::updateConversationView(const std::string& convUid)
956{
957 if (convUid != selectedConvUid()) {
958 return;
959 }
960
Andreas Traczyk43c08232018-10-31 13:42:09 -0400961
962
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400963}
964
965void
966CallWidget::selectConversation(const QModelIndex& index)
967{
968 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
969
970 if (currentConversationModel == nullptr || !index.isValid()) {
971 return;
972 }
973
974 const auto item = currentConversationModel->filteredConversation(index.row());
975
976 if (selectConversation(item, *currentConversationModel)) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400977 showIMOutOfCall(index);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400978 auto convUid = selectedConvUid();
979 if (!lastConvUid_.compare(convUid)) {
980 return;
981 }
982 lastConvUid_.assign(convUid);
983 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
984 auto callModel = LRCInstance::getCurrentCallModel();
985 auto conversation = Utils::getConversationFromUid(convUid, *currentConversationModel);
986 const auto item = currentConversationModel->filteredConversation(index.row());
Andreas Traczyk43c08232018-10-31 13:42:09 -0400987 if (callModel->hasCall(conversation->callId) && item.callId == conversation->callId) {
988 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
989 ui->callStackWidget->show();
990 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400991 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400992 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400993 }
Anthony Léonard5cc76412017-04-21 16:52:25 -0400994}
Anthony Léonardecfe7422017-05-04 14:14:37 -0400995
Anthony Léonard041ad392017-07-14 16:44:09 -0400996bool
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400997CallWidget::selectConversation( const lrc::api::conversation::Info& item,
998 lrc::api::ConversationModel& convModel)
Anthony Léonard041ad392017-07-14 16:44:09 -0400999{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001000 if (selectedConvUid() == item.uid) {
1001 return false;
1002 } else if (item.participants.size() > 0) {
1003 convModel.selectConversation(item.uid);
1004 LRCInstance::setSelectedConvId(item.uid);
1005 convModel.clearUnreadInteractions(item.uid);
1006 ui->conversationsFilterWidget->update();
1007 return true;
Anthony Léonard041ad392017-07-14 16:44:09 -04001008 }
Anthony Léonard041ad392017-07-14 16:44:09 -04001009}
1010
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001011void
1012CallWidget::deselectConversation()
Anthony Léonardecfe7422017-05-04 14:14:37 -04001013{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001014 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1015
1016 if (currentConversationModel == nullptr) {
1017 return;
1018 }
1019
1020 currentConversationModel->selectConversation("");
1021 LRCInstance::setSelectedConvId("");
1022
1023 ui->smartList->selectionModel()->clear();
1024 disconnect(imConnection_);
Anthony Léonardecfe7422017-05-04 14:14:37 -04001025}
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001026
1027void
1028CallWidget::updateConversationForNewContact(const std::string& convUid)
1029{
1030 auto convModel = LRCInstance::getCurrentConversationModel();
1031 if (convModel == nullptr) {
1032 return;
1033 }
1034 ui->ringContactLineEdit->setText("");
1035 auto selectedUid = selectedConvUid();
1036 auto it = Utils::getConversationFromUid(convUid, *convModel);
1037 if (it != convModel->allFilteredConversations().end()) {
1038 try {
1039 auto contact = convModel->owner.contactModel->getContact(it->participants[0]);
1040 if (!contact.profileInfo.uri.empty() && contact.profileInfo.uri.compare(selectedUid) == 0) {
1041 LRCInstance::setSelectedConvId(convUid);
1042 convModel->selectConversation(convUid);
1043 }
1044 } catch (...) {
1045 return;
1046 }
1047 }
1048}
1049
1050void
1051CallWidget::updateSmartList()
1052{
1053 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
1054 smartListModel_.reset(new SmartListModel(currentAccountInfo, this->parent()));
1055 ui->smartList->setModel(smartListModel_.get());
1056 ui->smartList->setItemDelegate(new ConversationItemDelegate());
1057
1058 // smartlist selection
1059 QObject::disconnect(smartlistSelectionConnection_);
1060 smartlistSelectionConnection_ = connect(ui->smartList->selectionModel(),
1061 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
1062 this,
1063 SLOT(smartListSelectionChanged(QItemSelection, QItemSelection)));
1064}
1065
1066void
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001067CallWidget::updateComboBox()
1068{
1069 ui->currentAccountComboBox->updateComboBoxDisplay();
1070}
1071
1072void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001073CallWidget::update()
1074{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001075 updateSmartList();
1076 updateConversationsFilterWidget();
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001077 updateComboBox();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001078 connectConversationModel();
Isa Nanic601de1d2018-10-23 11:37:26 -04001079}