blob: cd0283b0e357dc62a5de7fc088e2c59bba8f3e81 [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
Sébastien Blin942d1022018-12-13 09:49:03 -050032#include <algorithm>
Edric Milaret53f57b62015-05-11 11:02:17 -040033#include <memory>
Edric Milaret627500d2015-03-27 16:41:40 -040034
Edric Milarete19c4cd2016-02-12 10:19:44 -050035#include "qrencode.h"
36
Edric Milaret43f3c1e2015-07-16 17:52:47 -040037//ERROR is defined in windows.h
38#include "utils.h"
39#undef ERROR
Edric Milareta0ebd062016-01-13 12:18:23 -050040#undef interface
Edric Milaret43f3c1e2015-07-16 17:52:47 -040041
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040042// lrc
Edric Milareta0ebd062016-01-13 12:18:23 -050043#include "globalinstances.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040044#include "profilemodel.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040045#include "localprofilecollection.h"
Anthony Léonardd47179c2017-03-28 10:39:10 -040046
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040047// client
Edric Milaret559bda52015-04-29 17:02:31 -040048#include "wizarddialog.h"
Edric Milaret83b248c2015-06-02 11:42:23 -040049#include "windowscontactbackend.h"
Edric Milaret2cf34292015-06-22 16:27:03 -040050#include "globalsystemtray.h"
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040051#include "conversationitemdelegate.h"
Edric Milareta0ebd062016-01-13 12:18:23 -050052#include "pixbufmanipulator.h"
Edric Milaret70ae8782016-04-18 16:10:44 -040053#include "settingskey.h"
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040054#include "lrcinstance.h"
Andreas Traczyk43c08232018-10-31 13:42:09 -040055#include "animationhelpers.h"
56#include "ringthemeutils.h"
Edric Milaret25236d92016-03-28 09:40:58 -040057
Nicolas Jager97a21b42015-12-03 16:55:45 -050058CallWidget::CallWidget(QWidget* parent) :
Nicolas Jager74fe46f2016-02-29 14:55:09 -050059 NavWidget(parent),
Edric Milaret7d40a4a2015-05-13 13:01:15 -040060 ui(new Ui::CallWidget),
Andreas Traczyk43c08232018-10-31 13:42:09 -040061 menu_(new QMenu())
Edric Milaret627500d2015-03-27 16:41:40 -040062{
63 ui->setupUi(this);
64
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040065 using namespace lrc::api;
Nicolas Jagerca850292016-01-17 14:11:10 -050066
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040067 QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
Edric Milaret3aca8e32015-06-12 10:01:40 -040068
Sébastien Blincba5b522018-12-10 12:48:36 -050069 QPixmap logo(":/images/logo-jami-standard-coul.png");
Edric Milareted0b2802015-10-01 15:10:02 -040070 ui->ringLogo->setPixmap(logo.scaledToHeight(100, Qt::SmoothTransformation));
71 ui->ringLogo->setAlignment(Qt::AlignHCenter);
72
Edric Milaret1e598592016-09-02 10:10:01 -040073 ui->qrLabel->hide();
Edric Milarete19c4cd2016-02-12 10:19:44 -050074
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040075 videoRenderer_ = nullptr;
Edric Milaret627500d2015-03-27 16:41:40 -040076
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040077 // this line is not welcome here, and must be removed
78 ProfileModel::instance().addCollection<LocalProfileCollection>(LoadOptions::FORCE_ENABLED);
Edric Milaret627500d2015-03-27 16:41:40 -040079
Andreas Traczyk43c08232018-10-31 13:42:09 -040080 QSettings settings;
81
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040082 // select last used account if stored in registry
83 auto accountList = LRCInstance::accountModel().getAccountList();
84 if (!accountList.empty()) {
85 std::string accountIdToStartWith;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040086 if (settings.contains(SettingsKey::selectedAccount)) {
87 accountIdToStartWith = settings
88 .value(SettingsKey::selectedAccount, true)
89 .value<QString>()
90 .toStdString();
91 if (Utils::indexInVector(accountList, accountIdToStartWith) == -1) {
92 accountIdToStartWith = accountList.at(0);
Olivier SOLDANOaf8f2822017-07-11 12:15:18 -040093 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040094 }
95 else {
96 accountIdToStartWith = accountList.at(0);
97 }
98 setSelectedAccount(accountIdToStartWith);
Isa Nanic601de1d2018-10-23 11:37:26 -040099 // get account index and set the currentAccountComboBox
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400100 auto index = Utils::indexInVector(accountList, accountIdToStartWith);
101 if (index != -1) {
Isa Nanic601de1d2018-10-23 11:37:26 -0400102 ui->currentAccountComboBox->setCurrentIndex(index);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400103 }
Edric Milaret627500d2015-03-27 16:41:40 -0400104 }
Olivier SOLDANO2100f1c2017-09-06 16:45:20 -0400105
Andreas Traczyk43c08232018-10-31 13:42:09 -0400106 if (settings.contains(SettingsKey::mainSplitterState)) {
107 auto splitterStates = settings.value(SettingsKey::mainSplitterState).toByteArray();
108 ui->mainActivitySplitter->restoreState(splitterStates);
109 }
110
111 ui->mainActivitySplitter->setCollapsible(0, false);
112 ui->splitter->setCollapsible(0, false);
113 ui->splitter->setCollapsible(1, false);
114
Isa Nanic601de1d2018-10-23 11:37:26 -0400115 //disable dropdown shadow on combobox
116 ui->currentAccountComboBox->view()->window()->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
117
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400118 // conversation list
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400119 ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
120
121 // setup searchingfor mini spinner
122 miniSpinner_ = new QMovie(":/images/waiting.gif");
123 ui->spinnerLabel->setMovie(miniSpinner_);
124 ui->spinnerLabel->hide();
125
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400126 // connections
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400127 connect(ui->currentAccountComboBox, &CurrentAccountComboBox::settingsButtonClicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400128 this, &CallWidget::settingsButtonClicked);
129
Andreas Traczyk43c08232018-10-31 13:42:09 -0400130 connect(ui->videoWidget, &VideoView::setChatVisibility,
131 [this](bool visible) {
132 ui->callStackWidget->hide();
133 });
134
135 connect(ui->mainActivitySplitter, &QSplitter::splitterMoved,
136 [this](int pos, int index) {
137 QSettings settings;
138 settings.setValue(SettingsKey::mainSplitterState, ui->mainActivitySplitter->saveState());
139 });
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400140
141 connect(ui->videoWidget, &VideoView::videoSettingsClicked,
142 this, &CallWidget::settingsButtonClicked);
143
Andreas Traczyk43c08232018-10-31 13:42:09 -0400144 connect(ui->btnConversations, &QPushButton::clicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400145 this, &CallWidget::conversationsButtonClicked);
146
Andreas Traczyk43c08232018-10-31 13:42:09 -0400147 connect(ui->btnInvites, &QPushButton::clicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400148 this, &CallWidget::invitationsButtonClicked);
149
Andreas Traczyk43c08232018-10-31 13:42:09 -0400150 connect(ui->smartList, &QTreeView::customContextMenuRequested,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400151 this, &CallWidget::slotCustomContextMenuRequested);
152
153 connect(ui->smartList, &SmartListView::btnAcceptInviteClicked,
154 this, &CallWidget::slotAcceptInviteClicked);
155
156 connect(ui->smartList, &SmartListView::btnBlockInviteClicked,
157 this, &CallWidget::slotBlockInviteClicked);
158
159 connect(ui->smartList, &SmartListView::btnIgnoreInviteClicked,
160 this, &CallWidget::slotIgnoreInviteClicked);
161
162 connect(&LRCInstance::behaviorController(), &BehaviorController::showCallView,
163 this, &CallWidget::slotShowCallView);
164
165 connect(&LRCInstance::behaviorController(), &BehaviorController::showIncomingCallView,
166 this, &CallWidget::slotShowIncomingCallView);
167
168 connect(&LRCInstance::behaviorController(), &BehaviorController::showChatView,
169 this, &CallWidget::slotShowChatView);
Andreas Traczyk55f92cb2018-10-23 12:26:25 -0400170
Isa Nanic601de1d2018-10-23 11:37:26 -0400171 connect(ui->currentAccountComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
172 this, &CallWidget::slotAccountChanged);
173
Andreas Traczyk912242e2018-10-29 14:44:44 -0400174 connect(ui->sendContactRequestButton, &QPushButton::clicked,
175 this, &CallWidget::on_sendContactRequestButton_clicked);
176
177 connect(ui->btnAudioCall, &QPushButton::clicked,
178 this, &CallWidget::on_sendContactRequestButton_clicked);
179
180 connect(ui->btnVideoCall, &QPushButton::clicked,
181 this, &CallWidget::on_sendContactRequestButton_clicked);
182
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400183 connect(ui->currentAccountComboBox, QOverload<int>::of(&CurrentAccountComboBox::currentIndexChanged),
184 [this] {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400185 ui->btnConversations->setChecked(true);
186 ui->btnInvites->setChecked(false);
187 });
188
Andreas Traczyk55f92cb2018-10-23 12:26:25 -0400189 // set first view to welcome view
190 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400191 ui->btnConversations->setChecked(true);
192
193 // chat view
194 ui->messageView->buildView();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500195
196 emit setLeftSizeWidget(ui->currentAccountComboBox->width());
Edric Milaret627500d2015-03-27 16:41:40 -0400197}
198
199CallWidget::~CallWidget()
200{
201 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400202 delete menu_;
Edric Milaret00a32252016-01-19 10:37:13 -0500203}
204
205void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400206CallWidget::onIncomingMessage(const std::string& convUid,
207 uint64_t interactionId,
208 const lrc::api::interaction::Info& interaction)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400209{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400210 Q_UNUSED(interactionId);
Edric Milaret00a32252016-01-19 10:37:13 -0500211 if (!QApplication::focusWidget()) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400212 auto convModel = LRCInstance::getCurrentConversationModel();
213 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
214 auto bestName = Utils::bestNameForConversation(*conversation, *convModel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400215 Utils::showSystemNotification(this,
216 QString(tr("Message incoming from %1"))
Andreas Traczyk43c08232018-10-31 13:42:09 -0400217 .arg(QString::fromStdString(bestName)));
Edric Milaret00a32252016-01-19 10:37:13 -0500218 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400219 if (convUid != selectedConvUid()) {
220 return;
221 }
222
223 auto convModel = LRCInstance::getCurrentConversationModel();
224 convModel->clearUnreadInteractions(convUid);
225 auto currentConversation = Utils::getConversationFromUid(convUid, *convModel);
226 if (currentConversation == convModel->allFilteredConversations().end()) {
227 return;
228 }
229 ui->messageView->printNewInteraction(*convModel, interactionId, interaction);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400230 ui->conversationsFilterWidget->update();
Edric Milareta0ebd062016-01-13 12:18:23 -0500231}
232
233void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400234CallWidget::setupSmartListContextMenu(const QPoint& pos)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400235{
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400236 QPoint globalPos = ui->smartList->mapToGlobal(pos);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400237 auto index = ui->smartList->indexAt(pos);
238 if (not index.isValid()) {
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400239 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400240 }
241
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400242 auto convModel = LRCInstance::getCurrentConversationModel();
243 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID))
244 .value<QString>()
245 .toStdString();
246 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
247 auto contactUid = (*conversation).participants.at(0);
248 auto contact = LRCInstance::getCurrentAccountInfo().contactModel.get()->getContact(contactUid);
249
250 if (!Utils::isContactValid(contactUid, *convModel)) {
251 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400252 }
253
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400254 QMenu menu;
255
256 // video call
257 auto videoCallAction = new QAction(tr("Start video call"), this);
258 menu.addAction(videoCallAction);
259 connect(videoCallAction, &QAction::triggered,
260 [this, convUid, conversation, convModel]() {
261 convModel->placeCall(convUid);
262 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
263 if (convUid != selectedConvUid()) {
264 selectConversation(*conversation, *convModel);
265 }
266 });
267 // audio call
268 auto audioCallAction = new QAction(tr("Start audio call"), this);
269 menu.addAction(audioCallAction);
270 connect(audioCallAction, &QAction::triggered,
271 [this, convUid, conversation, convModel]() {
272 convModel->placeAudioOnlyCall(convUid);
273 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
274 if (convUid != selectedConvUid()) {
275 selectConversation(*conversation, *convModel);
276 }
277 });
278
279 if (contact.profileInfo.type == lrc::api::profile::Type::RING) {
280 // separator
281 menu.addSeparator();
282
283 // clear conversation
284 auto clearConversationAction = new QAction(tr("Clear conversation"), this);
285 menu.addAction(clearConversationAction);
286 connect(clearConversationAction, &QAction::triggered,
287 [convUid]() {
288 LRCInstance::getCurrentConversationModel()->clearHistory(convUid);
289 });
Sébastien Blin31fccce2018-12-13 11:27:05 -0500290 // remove contact
291 auto removeContactAction = new QAction(tr("Remove contact"), this);
292 menu.addAction(removeContactAction);
293 connect(removeContactAction, &QAction::triggered,
294 [convUid]() {
295 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, false);
296 });
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400297 // block contact
298 auto blockContactAction = new QAction(tr("Block contact"), this);
299 menu.addAction(blockContactAction);
300 connect(blockContactAction, &QAction::triggered,
301 [convUid]() {
302 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
303 });
304
305 // separator
306 menu.addSeparator();
307
308 // copy number(infohash)
309 auto copyNumberAction = new QAction(tr("Copy number"), this);
310 menu.addAction(copyNumberAction);
311 connect(copyNumberAction, &QAction::triggered,
312 [contact]() {
313 QApplication::clipboard()->setText(
314 QString::fromStdString(contact.profileInfo.uri)
315 );
316 });
317 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400318 smartListModel_->isContextMenuOpen = true;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400319 menu.exec(globalPos);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400320 smartListModel_->isContextMenuOpen = false;
Edric Milareta0ebd062016-01-13 12:18:23 -0500321}
322
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400323void
324CallWidget::setupQRCode(QString ringID)
Edric Milarete19c4cd2016-02-12 10:19:44 -0500325{
Anthony Léonarda86a8972016-12-15 10:33:47 -0500326 auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
Edric Milaret6d0e5312016-04-04 16:30:22 -0400327 0, //Let the version be decided by libqrencode
328 QR_ECLEVEL_L, // Lowest level of error correction
Edric Milarete19c4cd2016-02-12 10:19:44 -0500329 QR_MODE_8, // 8-bit data mode
330 1);
331 if (not rcode) {
332 qWarning() << "Failed to generate QR code: " << strerror(errno);
333 return;
334 }
335
336 auto margin = 5;
337 int qrwidth = rcode->width + margin * 2;
338 QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono);
339 QPainter painter;
340 painter.begin(&result);
341 painter.setClipRect(QRect(0, 0, qrwidth, qrwidth));
342 painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
343 painter.setBrush(Qt::black);
344 painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
Edric Milaret74474f52016-05-16 13:36:23 -0400345 unsigned char* p;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500346 p = rcode->data;
347 for(int y = 0; y < rcode->width; y++) {
Edric Milaret74474f52016-05-16 13:36:23 -0400348 unsigned char* row = (p + (y * rcode->width));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500349 for(int x = 0; x < rcode->width; x++) {
350 if(*(row + x) & 0x1) {
351 painter.drawRect(margin + x, margin + y, 1, 1);
352 }
353 }
354
355 }
356 painter.end();
357 QRcode_free(rcode);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400358 ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_),
359 Qt::KeepAspectRatio)));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500360}
361
Edric Milaret627500d2015-03-27 16:41:40 -0400362void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400363CallWidget::on_smartList_clicked(const QModelIndex& index)
Edric Milaret00d34f22016-05-09 16:30:29 -0400364{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400365 Q_UNUSED(index);
Edric Milaret627500d2015-03-27 16:41:40 -0400366}
367
368void
369CallWidget::on_acceptButton_clicked()
370{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400371 auto convModel = LRCInstance::getCurrentConversationModel();
372 auto callModel = LRCInstance::getCurrentCallModel();
373 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
374 callModel->accept(conversation->callId);
Edric Milaret627500d2015-03-27 16:41:40 -0400375}
376
377void
378CallWidget::on_refuseButton_clicked()
379{
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 Milaret6456baa2015-05-21 12:18:07 -0400384}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400385
386void
Edric Milareted0b2802015-10-01 15:10:02 -0400387CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400388{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400389 auto convModel = LRCInstance::getCurrentConversationModel();
390 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
391 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
392 showConversationView();
Edric Milaretd8528fa2015-07-07 14:13:51 -0400393}
Edric Milareted0b2802015-10-01 15:10:02 -0400394
395void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400396CallWidget::showConversationView()
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400397{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400398 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
399 ui->messageView->setFocus();
400
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400401}
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{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500450 return LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400451}
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
479CallWidget::placeCall()
480{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500481 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400482 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500483 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400484 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500485 ui->ringContactLineEdit->clear();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400486 auto photoRect = ui->callingPhoto->frameGeometry();
Edric1bed3f92016-05-19 10:24:48 -0400487 ui->callingPhoto->setPixmap(
488 QPixmap::fromImage(
489 GlobalInstances::pixmapManipulator()
Andreas Traczyk43c08232018-10-31 13:42:09 -0400490 .callPhoto(c, QSize(photoRect.width(), photoRect.height()))
491 .value<QImage>()));
Edric Milareted0b2802015-10-01 15:10:02 -0400492}
493
494void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400495CallWidget::conversationsButtonClicked()
496{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400497 ui->btnConversations->setChecked(true);
498 ui->btnInvites->setChecked(false);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400499 setConversationFilter(lrc::api::profile::Type::RING);
500}
501
502void
503CallWidget::invitationsButtonClicked()
504{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400505 ui->btnConversations->setChecked(false);
506 ui->btnInvites->setChecked(true);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400507 setConversationFilter(lrc::api::profile::Type::PENDING);
508}
509
510void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500511CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400512{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500513 emit setLeftSizeWidget(ui->currentAccountComboBox->width());
Andreas Traczyk7548e732018-12-12 10:47:21 -0500514 emit NavigationRequested(ScreenEnum::SetttingsScreen);
Edric Milareted0b2802015-10-01 15:10:02 -0400515}
516
517void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400518CallWidget::processContactLineEdit()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500519{
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400520 auto contactLineText = ui->ringContactLineEdit->text();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400521 setConversationFilter(contactLineText);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500522}
523
524void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400525CallWidget::on_ringContactLineEdit_returnPressed()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500526{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400527 // select current temporary item and show conversation
528 auto convModel = LRCInstance::getCurrentConversationModel();
529 auto conversations = convModel->allFilteredConversations();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400530 if (!conversations.empty() &&
531 Utils::isContactValid(conversations.at(0).participants.at(0), *convModel)) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400532 selectConversation(smartListModel_->index(0));
533 }
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400534}
535
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400536void CallWidget::slotAcceptInviteClicked(const QModelIndex & index)
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400537{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400538 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
539 LRCInstance::getCurrentConversationModel()->makePermanent(convUid.toStdString());
Nicolas Jager97a21b42015-12-03 16:55:45 -0500540}
541
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400542void CallWidget::slotBlockInviteClicked(const QModelIndex & index)
Nicolas Jager97a21b42015-12-03 16:55:45 -0500543{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400544 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
545 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), true);
546}
547
548void CallWidget::slotIgnoreInviteClicked(const QModelIndex & index)
549{
550 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
Sébastien Blin31fccce2018-12-13 11:27:05 -0500551 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), false);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400552}
553
554void CallWidget::slotCustomContextMenuRequested(const QPoint& pos)
555{
556 setupSmartListContextMenu(pos);
557}
558
Isa Nanic601de1d2018-10-23 11:37:26 -0400559void CallWidget::slotAccountChanged(int index)
560{
561 auto accountList = LRCInstance::accountModel().getAccountList();
562 setSelectedAccount(accountList.at(index));
563}
564
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400565void CallWidget::slotShowCallView(const std::string& accountId,
566 const lrc::api::conversation::Info& convInfo)
567{
568 Q_UNUSED(accountId);
569 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400570 qDebug() << "slotShowCallView";
571 ui->callStackWidget->show();
572 ui->callStackWidget->setCurrentWidget(ui->videoPage);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400573 hideMiniSpinner();
574}
575
576void CallWidget::slotShowIncomingCallView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400577 const lrc::api::conversation::Info& convInfo)
578{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400579 Q_UNUSED(accountId);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400580 qDebug() << "slotShowIncomingCallView";
581
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400582 auto callModel = LRCInstance::getCurrentCallModel();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400583
584 if (!callModel->hasCall(convInfo.callId)) {
Nicolas Jager97a21b42015-12-03 16:55:45 -0500585 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400586 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500587
Andreas Traczyk43c08232018-10-31 13:42:09 -0400588 auto convModel = LRCInstance::getCurrentConversationModel();
589 ui->callerPhoto->setPixmap(QPixmap::fromImage(imageForConv(convInfo.uid)));
590 auto bestName = QString::fromStdString(Utils::bestNameForConversation(convInfo, *convModel));
591 auto bestId = QString::fromStdString(Utils::bestIdForConversation(convInfo, *convModel));
592 auto finalBestId = (bestName != bestId) ? bestId : "";
593
594 auto call = callModel->getCall(convInfo.callId);
595 auto isCallSelected = selectedConvUid() == convInfo.uid;
596
597 if (call.isOutgoing) {
598 if (isCallSelected) {
599 miniSpinner_->start();
600 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
601 ui->spinnerLabel->show();
602 ui->callStackWidget->setCurrentWidget(ui->outgoingCallPage);
603 ui->callStackWidget->show();
604 }
605 } else {
606 if (!QApplication::focusWidget()) {
607 auto formattedName = Utils::bestNameForConversation(convInfo, *convModel);
608 Utils::showSystemNotification(this,
609 QString(tr("Call incoming from %1")).arg(QString::fromStdString(formattedName)));
610 }
611 selectSmartlistItem(convInfo.uid);
612 auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
613 auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
614 if (accountProperties.autoAnswer) {
615 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
616 ui->callStackWidget->setCurrentWidget(ui->videoPage);
617 } else if (isCallSelected) {
618 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
619 ui->callStackWidget->setCurrentWidget(ui->incomingCallPage);
620 ui->callStackWidget->show();
621 }
622 }
623
624 // flashing index widget during call
625 for (int row = 0; row < smartListModel_->rowCount(); row++) {
626 QModelIndex index = smartListModel_->index(row);
627 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
628 if (indexUid == convInfo.uid) {
629 auto widget = ui->smartList->indexWidget(index);
630 if (!widget) {
631 auto blinkingWidget = new AnimatedOverlay(RingTheme::urgentOrange_);
632 ui->smartList->setIndexWidget(index, blinkingWidget);
633 blinkingWidget->show();
634 } else {
635 widget->show();
636 }
637 }
638 }
639
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400640 ui->videoWidget->pushRenderer(convInfo.callId);
Andreas Traczykfd0d7c02018-10-30 17:14:06 -0400641
Andreas Traczyk43c08232018-10-31 13:42:09 -0400642 QFontMetrics primaryCallLabelFontMetrics(ui->callingBestNameLabel->font());
643 QFontMetrics sencondaryCallLabelFontMetrics(ui->callingBestIdLabel->font());
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400644
Andreas Traczyk43c08232018-10-31 13:42:09 -0400645 QString elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callerBestNameLabel->width());
646 ui->callerBestNameLabel->setText(elidedLabel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400647
Andreas Traczyk43c08232018-10-31 13:42:09 -0400648 elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callingBestNameLabel->width());
649 ui->callingBestNameLabel->setText(elidedLabel);
650
651 elidedLabel = sencondaryCallLabelFontMetrics.elidedText(finalBestId, Qt::ElideRight, ui->callingBestIdLabel->width());
652 ui->callingBestIdLabel->setText(elidedLabel);
653
654 ui->smartList->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400655}
656
657void CallWidget::slotShowChatView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400658 const lrc::api::conversation::Info& convInfo)
659{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400660 Q_UNUSED(accountId);
661 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400662
663 for (int row = 0; row < smartListModel_->rowCount(); row++) {
664 QModelIndex index = smartListModel_->index(row);
665 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
666 if (indexUid == convInfo.uid) {
667 if (auto widget = ui->smartList->indexWidget(index)) {
668 widget->hide();
669 widget->deleteLater();
670 ui->smartList->setIndexWidget(index, nullptr);
671 }
672 }
673 }
674
675 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400676 showConversationView();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500677}
Edric Milaretab12d022015-12-04 16:09:44 -0500678
679void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400680CallWidget::setSelectedAccount(const std::string& accountId)
681{
682 LRCInstance::setSelectedAccountId(accountId);
683
684 // First, we get back to the welcome view (except if in call)
685 if (ui->stackedWidget->currentWidget() != ui->videoPage &&
686 ui->stackedWidget->currentWidget() != ui->welcomePage) {
687 Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
688 }
689
690 // We setup the ringIdLabel and the QRCode
691 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
692 auto id = accountInfo.registeredName.empty() ? accountInfo.profileInfo.uri : accountInfo.registeredName;
693 auto isRingAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
694 if (isRingAccount) {
695 ui->ringIdLabel->setText(QString::fromStdString(id));
696 setupQRCode(QString::fromStdString(accountInfo.profileInfo.uri));
697 }
698
699 updateSmartList();
700 currentTypeFilter_ = accountInfo.profileInfo.type;
701 LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
702 updateConversationsFilterWidget();
703 connectConversationModel();
704}
705
706void CallWidget::setConversationFilter(lrc::api::profile::Type filter)
707{
708 if (currentTypeFilter_ == filter) {
709 return;
710 }
711 currentTypeFilter_ = filter;
712 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
713}
714
715void CallWidget::updateConversationsFilterWidget()
716{
717 auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
718 if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
719 currentTypeFilter_ = lrc::api::profile::Type::RING;
720 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
721 }
722 ui->conversationsFilterWidget->setVisible(invites);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400723 ui->conversationsFilterWidget->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400724}
725
726void CallWidget::setConversationFilter(const QString & filter)
727{
728 LRCInstance::getCurrentConversationModel()->setFilter(filter.toStdString());
Anthony Léonardd47179c2017-03-28 10:39:10 -0400729}
730
731void
Edric Milaret6b68a482016-02-01 15:23:44 -0500732CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500733{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400734 QString displayName = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayName)).toString();
735 QString displayId = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayID)).toString();
736 QString contactURI = nodeIdx.data(static_cast<int>(SmartListModel::Role::URI)).toString();
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400737
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400738 bool isContact = false;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500739 auto selectedAccountId = LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400740 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);
741 bool isRINGAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
742 try {
743 accountInfo.contactModel->getContact(contactURI.toStdString());
744 isContact = true;
745 }
746 catch (...) {}
747
Olivier SOLDANO31b9aac2017-07-14 15:50:09 -0400748 ui->imNameLabel->setText(QString(tr("%1", "%1 is the contact username"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400749 .arg(displayName));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400750
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400751 if (isRINGAccount && displayName != displayId){
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400752 ui->imIdLabel->show();
753 ui->imIdLabel->setText(QString(tr("%1", "%1 is the contact unique identifier"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400754 .arg(displayId));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400755 } else {
756 ui->imIdLabel->hide();
757 }
758
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400759 bool shouldShowSendContactRequestBtn = !isContact && isRINGAccount;
Andreas Traczyk912242e2018-10-29 14:44:44 -0400760 ui->sendContactRequestButton->setVisible(shouldShowSendContactRequestBtn);
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400761
Andreas Traczyk43c08232018-10-31 13:42:09 -0400762 auto convModel = LRCInstance::getCurrentConversationModel();
763 auto currentConversation = Utils::getConversationFromUid(selectedConvUid(),
764 *convModel);
765 ui->messageView->clear();
766 ui->messageView->printHistory(*convModel, currentConversation->interactions);
767
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400768 showConversationView();
Anthony Léonard041ad392017-07-14 16:44:09 -0400769
Andreas Traczyk43c08232018-10-31 13:42:09 -0400770 // Contact Avatars
771 auto accInfo = &LRCInstance::getCurrentAccountInfo();
772 auto contactUri = currentConversation->participants.front();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400773 try {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400774 auto& contact = accInfo->contactModel->getContact(contactUri);
Sébastien Blin942d1022018-12-13 09:49:03 -0500775 auto bestName = Utils::bestNameForConversation(*currentConversation, *convModel);
776 ui->messageView->setInvitation(
777 (contact.profileInfo.type == lrc::api::profile::Type::PENDING),
778 bestName,
779 accInfo->contactModel->getContactProfileId(contact.profileInfo.uri)
780 );
Andreas Traczyk43c08232018-10-31 13:42:09 -0400781 if (!contact.profileInfo.avatar.empty()) {
782 ui->messageView->setSenderImage(
783 accInfo->contactModel->getContactProfileId(contactUri),
784 contact.profileInfo.avatar);
785 } else {
786 auto avatar = Utils::conversationPhoto(selectedConvUid(), *accInfo);
787 QByteArray ba;
788 QBuffer bu(&ba);
789 avatar.save(&bu, "PNG");
790 std::string avatarString = ba.toBase64().toStdString();
791 ui->messageView->setSenderImage(
792 accInfo->contactModel->getContactProfileId(contactUri),
793 avatarString);
794 }
795 } catch (...) { }
Edric Milaretab12d022015-12-04 16:09:44 -0500796}
Edric Milaretfa05d972016-01-13 16:22:04 -0500797
798void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500799CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500800{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400801 Q_UNUSED(text);
802 processContactLineEdit();
Edric Milaretfa05d972016-01-13 16:22:04 -0500803}
Edric Milareta0ebd062016-01-13 12:18:23 -0500804
Nicolas Jagerca850292016-01-17 14:11:10 -0500805void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400806CallWidget::backToWelcomePage()
Edric Milareta0ebd062016-01-13 12:18:23 -0500807{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400808 deselectConversation();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400809 ui->messageView->hideMessages();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400810 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Nicolas Jagerca850292016-01-17 14:11:10 -0500811}
812
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400813void
814CallWidget::hideMiniSpinner()
Olivier SOLDANO19193412017-06-06 12:03:36 -0400815{
816 if(ui->spinnerLabel->isVisible()){
817 miniSpinner_->stop();
818 ui->spinnerLabel->hide();
819 }
820}
821
Nicolas Jagerca850292016-01-17 14:11:10 -0500822void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400823CallWidget::on_imBackButton_clicked()
824{
825 backToWelcomePage();
826}
827
828void
Edric Milaret1e598592016-09-02 10:10:01 -0400829CallWidget::on_qrButton_toggled(bool checked)
830{
831 ui->qrLabel->setVisible(checked);
832}
833
834void
Edric Milaret4097d2f2016-02-09 14:41:50 -0500835CallWidget::on_shareButton_clicked()
836{
Sébastien Blincba5b522018-12-10 12:48:36 -0500837 Utils::InvokeMailto(tr("Contact me on Jami"), tr("My Id is : ") + ui->ringIdLabel->text());
Edric Milaret4097d2f2016-02-09 14:41:50 -0500838}
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400839
840void
Andreas Traczyk912242e2018-10-29 14:44:44 -0400841CallWidget::on_sendContactRequestButton_clicked()
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400842{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400843 LRCInstance::getCurrentConversationModel()->makePermanent(selectedConvUid());
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400844}
845
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400846void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400847CallWidget::on_pendingCRBackButton_clicked()
848{
Olivier SOLDANO8179e992017-07-19 15:59:19 -0400849 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400850}
Anthony Léonard5cc76412017-04-21 16:52:25 -0400851
Andreas Traczyk912242e2018-10-29 14:44:44 -0400852void
853CallWidget::on_btnAudioCall_clicked()
854{
855 auto convUid = LRCInstance::getSelectedConvUid();
856 LRCInstance::getCurrentConversationModel()->placeAudioOnlyCall(convUid);
857 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
858}
859
860void
861CallWidget::on_btnVideoCall_clicked()
862{
863 auto convUid = LRCInstance::getSelectedConvUid();
864 LRCInstance::getCurrentConversationModel()->placeCall(convUid);
865 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
866}
867
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400868bool
869CallWidget::connectConversationModel()
Anthony Léonard5cc76412017-04-21 16:52:25 -0400870{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400871 auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get();
872
873 if (ui->smartList->selectionModel()) {
874 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
Anthony Léonard5cc76412017-04-21 16:52:25 -0400875 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400876
877 QObject::disconnect(modelSortedConnection_);
878 QObject::disconnect(modelUpdatedConnection_);
879 QObject::disconnect(filterChangedConnection_);
880 QObject::disconnect(newConversationConnection_);
881 QObject::disconnect(conversationRemovedConnection_);
882 QObject::disconnect(conversationClearedConnection);
883 QObject::disconnect(interactionStatusUpdatedConnection_);
884 QObject::disconnect(newInteractionConnection_);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400885 QObject::disconnect(interactionRemovedConnection_);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400886
887 modelSortedConnection_ = QObject::connect(
888 currentConversationModel, &lrc::api::ConversationModel::modelSorted,
889 [this]() {
890 updateConversationsFilterWidget();
891 selectSmartlistItem(selectedConvUid());
892 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400893 }
894 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400895 modelUpdatedConnection_ = QObject::connect(
896 currentConversationModel, &lrc::api::ConversationModel::conversationUpdated,
897 [this](const std::string& convUid) {
898 Q_UNUSED(convUid);
899 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400900 }
901 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400902 filterChangedConnection_ = QObject::connect(
903 currentConversationModel, &lrc::api::ConversationModel::filterChanged,
904 [this]() {
905 updateSmartList();
906 updateConversationsFilterWidget();
907 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400908 }
909 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400910 newConversationConnection_ = QObject::connect(
911 currentConversationModel, &lrc::api::ConversationModel::newConversation,
912 [this](const std::string& convUid) {
913 updateSmartList();
914 updateConversationForNewContact(convUid);
915 ui->conversationsFilterWidget->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400916 }
917 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400918 conversationRemovedConnection_ = QObject::connect(
919 currentConversationModel, &lrc::api::ConversationModel::conversationRemoved,
920 [this]() {
921 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400922 }
923 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400924 conversationClearedConnection = QObject::connect(
925 currentConversationModel, &lrc::api::ConversationModel::conversationCleared,
926 [this](const std::string& convUid) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400927 ui->messageView->clear();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400928 // if currently selected,
929 // switch to welcome screen (deselecting current smartlist item )
930 if (convUid != selectedConvUid()) {
931 return;
932 }
933 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400934 }
935 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400936 interactionStatusUpdatedConnection_ = QObject::connect(
937 currentConversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400938 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400939 if (convUid != selectedConvUid()) {
940 return;
941 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400942 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
943 auto currentConversationModel = currentAccountInfo.conversationModel.get();
944 currentConversationModel->clearUnreadInteractions(convUid);
945 ui->conversationsFilterWidget->update();
946 ui->messageView->updateInteraction(*currentConversationModel, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400947 }
948 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400949 newInteractionConnection_ = QObject::connect(
950 currentConversationModel, &lrc::api::ConversationModel::newInteraction,
951 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
952 onIncomingMessage(convUid, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400953 }
954 );
Andreas Traczyk43c08232018-10-31 13:42:09 -0400955 interactionRemovedConnection_ = QObject::connect(
956 currentConversationModel, &lrc::api::ConversationModel::interactionRemoved,
957 [this](const std::string& convUid, uint64_t interactionId) {
958 Q_UNUSED(convUid);
959 ui->messageView->removeInteraction(interactionId);
960 }
961 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400962 currentConversationModel->setFilter("");
963 // clear search field
964 ui->ringContactLineEdit->setText("");
965 return true;
966}
967
968void
969CallWidget::updateConversationView(const std::string& convUid)
970{
971 if (convUid != selectedConvUid()) {
972 return;
973 }
974
Andreas Traczyk43c08232018-10-31 13:42:09 -0400975
976
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400977}
978
979void
980CallWidget::selectConversation(const QModelIndex& index)
981{
982 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
983
984 if (currentConversationModel == nullptr || !index.isValid()) {
985 return;
986 }
987
988 const auto item = currentConversationModel->filteredConversation(index.row());
989
990 if (selectConversation(item, *currentConversationModel)) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400991 showIMOutOfCall(index);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400992 auto convUid = selectedConvUid();
993 if (!lastConvUid_.compare(convUid)) {
994 return;
995 }
996 lastConvUid_.assign(convUid);
997 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
998 auto callModel = LRCInstance::getCurrentCallModel();
999 auto conversation = Utils::getConversationFromUid(convUid, *currentConversationModel);
1000 const auto item = currentConversationModel->filteredConversation(index.row());
Andreas Traczyk43c08232018-10-31 13:42:09 -04001001 if (callModel->hasCall(conversation->callId) && item.callId == conversation->callId) {
1002 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
1003 ui->callStackWidget->show();
1004 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001005 }
Andreas Traczyk43c08232018-10-31 13:42:09 -04001006 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001007 }
Anthony Léonard5cc76412017-04-21 16:52:25 -04001008}
Anthony Léonardecfe7422017-05-04 14:14:37 -04001009
Anthony Léonard041ad392017-07-14 16:44:09 -04001010bool
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001011CallWidget::selectConversation( const lrc::api::conversation::Info& item,
1012 lrc::api::ConversationModel& convModel)
Anthony Léonard041ad392017-07-14 16:44:09 -04001013{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001014 if (selectedConvUid() == item.uid) {
1015 return false;
1016 } else if (item.participants.size() > 0) {
1017 convModel.selectConversation(item.uid);
1018 LRCInstance::setSelectedConvId(item.uid);
1019 convModel.clearUnreadInteractions(item.uid);
1020 ui->conversationsFilterWidget->update();
1021 return true;
Anthony Léonard041ad392017-07-14 16:44:09 -04001022 }
Anthony Léonard041ad392017-07-14 16:44:09 -04001023}
1024
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001025void
1026CallWidget::deselectConversation()
Anthony Léonardecfe7422017-05-04 14:14:37 -04001027{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001028 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1029
1030 if (currentConversationModel == nullptr) {
1031 return;
1032 }
1033
1034 currentConversationModel->selectConversation("");
1035 LRCInstance::setSelectedConvId("");
1036
1037 ui->smartList->selectionModel()->clear();
1038 disconnect(imConnection_);
Anthony Léonardecfe7422017-05-04 14:14:37 -04001039}
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001040
1041void
1042CallWidget::updateConversationForNewContact(const std::string& convUid)
1043{
1044 auto convModel = LRCInstance::getCurrentConversationModel();
1045 if (convModel == nullptr) {
1046 return;
1047 }
1048 ui->ringContactLineEdit->setText("");
1049 auto selectedUid = selectedConvUid();
1050 auto it = Utils::getConversationFromUid(convUid, *convModel);
1051 if (it != convModel->allFilteredConversations().end()) {
1052 try {
1053 auto contact = convModel->owner.contactModel->getContact(it->participants[0]);
1054 if (!contact.profileInfo.uri.empty() && contact.profileInfo.uri.compare(selectedUid) == 0) {
1055 LRCInstance::setSelectedConvId(convUid);
1056 convModel->selectConversation(convUid);
1057 }
1058 } catch (...) {
1059 return;
1060 }
1061 }
1062}
1063
1064void
1065CallWidget::updateSmartList()
1066{
1067 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
1068 smartListModel_.reset(new SmartListModel(currentAccountInfo, this->parent()));
1069 ui->smartList->setModel(smartListModel_.get());
1070 ui->smartList->setItemDelegate(new ConversationItemDelegate());
1071
1072 // smartlist selection
1073 QObject::disconnect(smartlistSelectionConnection_);
1074 smartlistSelectionConnection_ = connect(ui->smartList->selectionModel(),
1075 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
1076 this,
1077 SLOT(smartListSelectionChanged(QItemSelection, QItemSelection)));
1078}
1079
1080void
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001081CallWidget::updateComboBox()
1082{
1083 ui->currentAccountComboBox->updateComboBoxDisplay();
1084}
1085
1086void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001087CallWidget::update()
1088{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001089 updateSmartList();
1090 updateConversationsFilterWidget();
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001091 updateComboBox();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001092 connectConversationModel();
Isa Nanic601de1d2018-10-23 11:37:26 -04001093}