blob: ba7e3f98c6f6b4c789864fb9cb880466078383eb [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
Andreas Traczykb81281e2018-12-13 13:13:28 -0500196 // hide the call stack
197 ui->callStackWidget->hide();
Andreas Traczykfc33a492018-12-14 13:53:13 -0500198
199 ui->containerWidget->setVisible(false);
Edric Milaret627500d2015-03-27 16:41:40 -0400200}
201
202CallWidget::~CallWidget()
203{
204 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400205 delete menu_;
Edric Milaret00a32252016-01-19 10:37:13 -0500206}
207
Andreas Traczykfc33a492018-12-14 13:53:13 -0500208void
209CallWidget::navigated(bool to)
210{
211 ui->containerWidget->setVisible(to);
212 if (to) {
213 updateSmartList();
214 connectConversationModel();
215 } else {
216 QObject::disconnect(smartlistSelectionConnection_);
217 smartListModel_.reset(nullptr);
218 }
219}
220
Andreas Traczykb81281e2018-12-13 13:13:28 -0500221int
222CallWidget::getLeftPanelWidth()
223{
224 return ui->currentAccountComboBox->width();
225}
226
Edric Milaret00a32252016-01-19 10:37:13 -0500227void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400228CallWidget::onIncomingMessage(const std::string& convUid,
229 uint64_t interactionId,
230 const lrc::api::interaction::Info& interaction)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400231{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400232 Q_UNUSED(interactionId);
Edric Milaret00a32252016-01-19 10:37:13 -0500233 if (!QApplication::focusWidget()) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400234 auto convModel = LRCInstance::getCurrentConversationModel();
235 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
236 auto bestName = Utils::bestNameForConversation(*conversation, *convModel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400237 Utils::showSystemNotification(this,
238 QString(tr("Message incoming from %1"))
Andreas Traczyk43c08232018-10-31 13:42:09 -0400239 .arg(QString::fromStdString(bestName)));
Edric Milaret00a32252016-01-19 10:37:13 -0500240 }
Andreas Traczyk1d8159a2018-12-13 15:48:24 -0500241 updateConversationsFilterWidget();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400242 if (convUid != selectedConvUid()) {
243 return;
244 }
245
246 auto convModel = LRCInstance::getCurrentConversationModel();
247 convModel->clearUnreadInteractions(convUid);
248 auto currentConversation = Utils::getConversationFromUid(convUid, *convModel);
249 if (currentConversation == convModel->allFilteredConversations().end()) {
250 return;
251 }
252 ui->messageView->printNewInteraction(*convModel, interactionId, interaction);
Edric Milareta0ebd062016-01-13 12:18:23 -0500253}
254
255void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400256CallWidget::setupSmartListContextMenu(const QPoint& pos)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400257{
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400258 QPoint globalPos = ui->smartList->mapToGlobal(pos);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400259 auto index = ui->smartList->indexAt(pos);
260 if (not index.isValid()) {
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400261 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400262 }
263
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400264 auto convModel = LRCInstance::getCurrentConversationModel();
265 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID))
266 .value<QString>()
267 .toStdString();
268 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
269 auto contactUid = (*conversation).participants.at(0);
270 auto contact = LRCInstance::getCurrentAccountInfo().contactModel.get()->getContact(contactUid);
271
272 if (!Utils::isContactValid(contactUid, *convModel)) {
273 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400274 }
275
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400276 QMenu menu;
277
278 // video call
279 auto videoCallAction = new QAction(tr("Start video call"), this);
280 menu.addAction(videoCallAction);
281 connect(videoCallAction, &QAction::triggered,
282 [this, convUid, conversation, convModel]() {
283 convModel->placeCall(convUid);
284 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
285 if (convUid != selectedConvUid()) {
286 selectConversation(*conversation, *convModel);
287 }
288 });
289 // audio call
290 auto audioCallAction = new QAction(tr("Start audio call"), this);
291 menu.addAction(audioCallAction);
292 connect(audioCallAction, &QAction::triggered,
293 [this, convUid, conversation, convModel]() {
294 convModel->placeAudioOnlyCall(convUid);
295 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
296 if (convUid != selectedConvUid()) {
297 selectConversation(*conversation, *convModel);
298 }
299 });
300
301 if (contact.profileInfo.type == lrc::api::profile::Type::RING) {
302 // separator
303 menu.addSeparator();
304
305 // clear conversation
306 auto clearConversationAction = new QAction(tr("Clear conversation"), this);
307 menu.addAction(clearConversationAction);
308 connect(clearConversationAction, &QAction::triggered,
309 [convUid]() {
310 LRCInstance::getCurrentConversationModel()->clearHistory(convUid);
311 });
Sébastien Blin31fccce2018-12-13 11:27:05 -0500312 // remove contact
313 auto removeContactAction = new QAction(tr("Remove contact"), this);
314 menu.addAction(removeContactAction);
315 connect(removeContactAction, &QAction::triggered,
316 [convUid]() {
317 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, false);
318 });
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400319 // block contact
320 auto blockContactAction = new QAction(tr("Block contact"), this);
321 menu.addAction(blockContactAction);
322 connect(blockContactAction, &QAction::triggered,
323 [convUid]() {
324 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
325 });
326
327 // separator
328 menu.addSeparator();
329
330 // copy number(infohash)
331 auto copyNumberAction = new QAction(tr("Copy number"), this);
332 menu.addAction(copyNumberAction);
333 connect(copyNumberAction, &QAction::triggered,
334 [contact]() {
335 QApplication::clipboard()->setText(
336 QString::fromStdString(contact.profileInfo.uri)
337 );
338 });
339 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400340 smartListModel_->isContextMenuOpen = true;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400341 menu.exec(globalPos);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400342 smartListModel_->isContextMenuOpen = false;
Edric Milareta0ebd062016-01-13 12:18:23 -0500343}
344
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400345void
346CallWidget::setupQRCode(QString ringID)
Edric Milarete19c4cd2016-02-12 10:19:44 -0500347{
Anthony Léonarda86a8972016-12-15 10:33:47 -0500348 auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
Edric Milaret6d0e5312016-04-04 16:30:22 -0400349 0, //Let the version be decided by libqrencode
350 QR_ECLEVEL_L, // Lowest level of error correction
Edric Milarete19c4cd2016-02-12 10:19:44 -0500351 QR_MODE_8, // 8-bit data mode
352 1);
353 if (not rcode) {
354 qWarning() << "Failed to generate QR code: " << strerror(errno);
355 return;
356 }
357
358 auto margin = 5;
359 int qrwidth = rcode->width + margin * 2;
360 QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono);
361 QPainter painter;
362 painter.begin(&result);
363 painter.setClipRect(QRect(0, 0, qrwidth, qrwidth));
364 painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
365 painter.setBrush(Qt::black);
366 painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
Edric Milaret74474f52016-05-16 13:36:23 -0400367 unsigned char* p;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500368 p = rcode->data;
369 for(int y = 0; y < rcode->width; y++) {
Edric Milaret74474f52016-05-16 13:36:23 -0400370 unsigned char* row = (p + (y * rcode->width));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500371 for(int x = 0; x < rcode->width; x++) {
372 if(*(row + x) & 0x1) {
373 painter.drawRect(margin + x, margin + y, 1, 1);
374 }
375 }
376
377 }
378 painter.end();
379 QRcode_free(rcode);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400380 ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_),
381 Qt::KeepAspectRatio)));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500382}
383
Edric Milaret627500d2015-03-27 16:41:40 -0400384void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400385CallWidget::on_smartList_clicked(const QModelIndex& index)
Edric Milaret00d34f22016-05-09 16:30:29 -0400386{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400387 Q_UNUSED(index);
Edric Milaret627500d2015-03-27 16:41:40 -0400388}
389
390void
391CallWidget::on_acceptButton_clicked()
392{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400393 auto convModel = LRCInstance::getCurrentConversationModel();
394 auto callModel = LRCInstance::getCurrentCallModel();
395 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
396 callModel->accept(conversation->callId);
Edric Milaret627500d2015-03-27 16:41:40 -0400397}
398
399void
400CallWidget::on_refuseButton_clicked()
401{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400402 auto convModel = LRCInstance::getCurrentConversationModel();
403 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
404 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
405 showConversationView();
Edric Milaret6456baa2015-05-21 12:18:07 -0400406}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400407
408void
Edric Milareted0b2802015-10-01 15:10:02 -0400409CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400410{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400411 auto convModel = LRCInstance::getCurrentConversationModel();
412 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
413 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
414 showConversationView();
Edric Milaretd8528fa2015-07-07 14:13:51 -0400415}
Edric Milareted0b2802015-10-01 15:10:02 -0400416
417void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400418CallWidget::showConversationView()
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400419{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400420 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
421 ui->messageView->setFocus();
422
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400423}
424
425void
426CallWidget::selectSmartlistItem(const std::string & convUid)
427{
428 if (convUid.empty()) {
429 return;
430 }
431 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
432 auto convModel = LRCInstance::getCurrentConversationModel();
433 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
434 if (conversation == convModel->allFilteredConversations().end()) {
435 return;
436 }
437 auto contactURI = QString::fromStdString((*conversation).participants[0]);
438 if (contactURI.isEmpty() ||
439 convModel->owner.contactModel->getContact(contactURI.toStdString()).profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
440 return;
441 }
442 for (int row = 0; row < smartListModel_->rowCount(); row++) {
443 QModelIndex index = smartListModel_->index(row);
444 auto indexContactURI = index.data(SmartListModel::Role::URI).value<QString>();
445 if (indexContactURI == contactURI) {
446 ui->smartList->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
447 return;
448 }
449 }
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400450}
451
452void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500453CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400454{
Olivier SOLDANO70279d32017-07-18 15:21:34 -0400455 if (!index.isValid())
456 return;
457
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400458 LRCInstance::getCurrentConversationModel()->placeCall(selectedConvUid());
Edric Milareted0b2802015-10-01 15:10:02 -0400459
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400460 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(selectedConvUid())));
461}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500462
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400463QImage
464CallWidget::imageForConv(const std::string& convUid)
465{
466 return Utils::conversationPhoto(convUid, LRCInstance::getCurrentAccountInfo());
467}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500468
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400469const std::string&
470CallWidget::selectedAccountId()
471{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500472 return LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400473}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500474
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400475const std::string&
476CallWidget::selectedConvUid()
477{
478 return LRCInstance::getSelectedConvUid();
Edric Milareted0b2802015-10-01 15:10:02 -0400479}
480
481void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400482CallWidget::smartListSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500483{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400484 Q_UNUSED(deselected);
485 QModelIndexList indices = selected.indexes();
486
487 if (indices.isEmpty()) {
Edric Milareted0b2802015-10-01 15:10:02 -0400488 return;
Anthony Léonardecfe7422017-05-04 14:14:37 -0400489 }
Edric Milareted0b2802015-10-01 15:10:02 -0400490
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400491 auto selectedIndex = indices.at(0);
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500492
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400493 if (not selectedIndex.isValid()) {
494 return;
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400495 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400496
497 selectConversation(selectedIndex);
Edric Milareted0b2802015-10-01 15:10:02 -0400498}
499
500void
501CallWidget::placeCall()
502{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500503 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400504 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500505 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400506 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500507 ui->ringContactLineEdit->clear();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400508 auto photoRect = ui->callingPhoto->frameGeometry();
Edric1bed3f92016-05-19 10:24:48 -0400509 ui->callingPhoto->setPixmap(
510 QPixmap::fromImage(
511 GlobalInstances::pixmapManipulator()
Andreas Traczyk43c08232018-10-31 13:42:09 -0400512 .callPhoto(c, QSize(photoRect.width(), photoRect.height()))
513 .value<QImage>()));
Edric Milareted0b2802015-10-01 15:10:02 -0400514}
515
516void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400517CallWidget::conversationsButtonClicked()
518{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400519 ui->btnConversations->setChecked(true);
520 ui->btnInvites->setChecked(false);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400521 setConversationFilter(lrc::api::profile::Type::RING);
522}
523
524void
525CallWidget::invitationsButtonClicked()
526{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400527 ui->btnConversations->setChecked(false);
528 ui->btnInvites->setChecked(true);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400529 setConversationFilter(lrc::api::profile::Type::PENDING);
530}
531
532void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500533CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400534{
Andreas Traczyk7548e732018-12-12 10:47:21 -0500535 emit NavigationRequested(ScreenEnum::SetttingsScreen);
Edric Milareted0b2802015-10-01 15:10:02 -0400536}
537
538void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400539CallWidget::processContactLineEdit()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500540{
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400541 auto contactLineText = ui->ringContactLineEdit->text();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400542 setConversationFilter(contactLineText);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500543}
544
545void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400546CallWidget::on_ringContactLineEdit_returnPressed()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500547{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400548 // select current temporary item and show conversation
549 auto convModel = LRCInstance::getCurrentConversationModel();
550 auto conversations = convModel->allFilteredConversations();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400551 if (!conversations.empty() &&
552 Utils::isContactValid(conversations.at(0).participants.at(0), *convModel)) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400553 selectConversation(smartListModel_->index(0));
554 }
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400555}
556
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400557void CallWidget::slotAcceptInviteClicked(const QModelIndex & index)
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400558{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400559 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
560 LRCInstance::getCurrentConversationModel()->makePermanent(convUid.toStdString());
Nicolas Jager97a21b42015-12-03 16:55:45 -0500561}
562
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400563void CallWidget::slotBlockInviteClicked(const QModelIndex & index)
Nicolas Jager97a21b42015-12-03 16:55:45 -0500564{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400565 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
566 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), true);
567}
568
569void CallWidget::slotIgnoreInviteClicked(const QModelIndex & index)
570{
571 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
Sébastien Blin31fccce2018-12-13 11:27:05 -0500572 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), false);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400573}
574
575void CallWidget::slotCustomContextMenuRequested(const QPoint& pos)
576{
577 setupSmartListContextMenu(pos);
578}
579
Isa Nanic601de1d2018-10-23 11:37:26 -0400580void CallWidget::slotAccountChanged(int index)
581{
582 auto accountList = LRCInstance::accountModel().getAccountList();
583 setSelectedAccount(accountList.at(index));
584}
585
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400586void CallWidget::slotShowCallView(const std::string& accountId,
587 const lrc::api::conversation::Info& convInfo)
588{
589 Q_UNUSED(accountId);
590 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400591 qDebug() << "slotShowCallView";
592 ui->callStackWidget->show();
593 ui->callStackWidget->setCurrentWidget(ui->videoPage);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400594 hideMiniSpinner();
595}
596
597void CallWidget::slotShowIncomingCallView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400598 const lrc::api::conversation::Info& convInfo)
599{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400600 Q_UNUSED(accountId);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400601 qDebug() << "slotShowIncomingCallView";
602
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400603 auto callModel = LRCInstance::getCurrentCallModel();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400604
605 if (!callModel->hasCall(convInfo.callId)) {
Nicolas Jager97a21b42015-12-03 16:55:45 -0500606 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400607 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500608
Andreas Traczyk43c08232018-10-31 13:42:09 -0400609 auto convModel = LRCInstance::getCurrentConversationModel();
610 ui->callerPhoto->setPixmap(QPixmap::fromImage(imageForConv(convInfo.uid)));
611 auto bestName = QString::fromStdString(Utils::bestNameForConversation(convInfo, *convModel));
612 auto bestId = QString::fromStdString(Utils::bestIdForConversation(convInfo, *convModel));
613 auto finalBestId = (bestName != bestId) ? bestId : "";
614
615 auto call = callModel->getCall(convInfo.callId);
616 auto isCallSelected = selectedConvUid() == convInfo.uid;
617
618 if (call.isOutgoing) {
619 if (isCallSelected) {
620 miniSpinner_->start();
621 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
622 ui->spinnerLabel->show();
623 ui->callStackWidget->setCurrentWidget(ui->outgoingCallPage);
624 ui->callStackWidget->show();
625 }
626 } else {
627 if (!QApplication::focusWidget()) {
628 auto formattedName = Utils::bestNameForConversation(convInfo, *convModel);
629 Utils::showSystemNotification(this,
630 QString(tr("Call incoming from %1")).arg(QString::fromStdString(formattedName)));
631 }
632 selectSmartlistItem(convInfo.uid);
633 auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
634 auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
635 if (accountProperties.autoAnswer) {
636 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
637 ui->callStackWidget->setCurrentWidget(ui->videoPage);
638 } else if (isCallSelected) {
639 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
640 ui->callStackWidget->setCurrentWidget(ui->incomingCallPage);
641 ui->callStackWidget->show();
642 }
643 }
644
645 // flashing index widget during call
646 for (int row = 0; row < smartListModel_->rowCount(); row++) {
647 QModelIndex index = smartListModel_->index(row);
648 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
649 if (indexUid == convInfo.uid) {
650 auto widget = ui->smartList->indexWidget(index);
651 if (!widget) {
652 auto blinkingWidget = new AnimatedOverlay(RingTheme::urgentOrange_);
653 ui->smartList->setIndexWidget(index, blinkingWidget);
654 blinkingWidget->show();
655 } else {
656 widget->show();
657 }
658 }
659 }
660
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400661 ui->videoWidget->pushRenderer(convInfo.callId);
Andreas Traczykfd0d7c02018-10-30 17:14:06 -0400662
Andreas Traczyk43c08232018-10-31 13:42:09 -0400663 QFontMetrics primaryCallLabelFontMetrics(ui->callingBestNameLabel->font());
664 QFontMetrics sencondaryCallLabelFontMetrics(ui->callingBestIdLabel->font());
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400665
Andreas Traczyk43c08232018-10-31 13:42:09 -0400666 QString elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callerBestNameLabel->width());
667 ui->callerBestNameLabel->setText(elidedLabel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400668
Andreas Traczyk43c08232018-10-31 13:42:09 -0400669 elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callingBestNameLabel->width());
670 ui->callingBestNameLabel->setText(elidedLabel);
671
672 elidedLabel = sencondaryCallLabelFontMetrics.elidedText(finalBestId, Qt::ElideRight, ui->callingBestIdLabel->width());
673 ui->callingBestIdLabel->setText(elidedLabel);
674
675 ui->smartList->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400676}
677
678void CallWidget::slotShowChatView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400679 const lrc::api::conversation::Info& convInfo)
680{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400681 Q_UNUSED(accountId);
682 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400683
684 for (int row = 0; row < smartListModel_->rowCount(); row++) {
685 QModelIndex index = smartListModel_->index(row);
686 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
687 if (indexUid == convInfo.uid) {
688 if (auto widget = ui->smartList->indexWidget(index)) {
689 widget->hide();
690 widget->deleteLater();
691 ui->smartList->setIndexWidget(index, nullptr);
692 }
693 }
694 }
695
696 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400697 showConversationView();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500698}
Edric Milaretab12d022015-12-04 16:09:44 -0500699
700void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400701CallWidget::setSelectedAccount(const std::string& accountId)
702{
703 LRCInstance::setSelectedAccountId(accountId);
704
705 // First, we get back to the welcome view (except if in call)
706 if (ui->stackedWidget->currentWidget() != ui->videoPage &&
707 ui->stackedWidget->currentWidget() != ui->welcomePage) {
708 Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
709 }
710
711 // We setup the ringIdLabel and the QRCode
712 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
713 auto id = accountInfo.registeredName.empty() ? accountInfo.profileInfo.uri : accountInfo.registeredName;
714 auto isRingAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
715 if (isRingAccount) {
716 ui->ringIdLabel->setText(QString::fromStdString(id));
717 setupQRCode(QString::fromStdString(accountInfo.profileInfo.uri));
718 }
719
720 updateSmartList();
721 currentTypeFilter_ = accountInfo.profileInfo.type;
722 LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
723 updateConversationsFilterWidget();
724 connectConversationModel();
725}
726
727void CallWidget::setConversationFilter(lrc::api::profile::Type filter)
728{
729 if (currentTypeFilter_ == filter) {
730 return;
731 }
732 currentTypeFilter_ = filter;
733 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
734}
735
736void CallWidget::updateConversationsFilterWidget()
737{
738 auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
739 if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
740 currentTypeFilter_ = lrc::api::profile::Type::RING;
741 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
742 }
743 ui->conversationsFilterWidget->setVisible(invites);
Andreas Traczyk1d8159a2018-12-13 15:48:24 -0500744 ui->conversationsFilterWidget->updateBadges();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400745 ui->conversationsFilterWidget->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400746}
747
748void CallWidget::setConversationFilter(const QString & filter)
749{
750 LRCInstance::getCurrentConversationModel()->setFilter(filter.toStdString());
Anthony Léonardd47179c2017-03-28 10:39:10 -0400751}
752
753void
Edric Milaret6b68a482016-02-01 15:23:44 -0500754CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500755{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400756 QString displayName = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayName)).toString();
757 QString displayId = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayID)).toString();
758 QString contactURI = nodeIdx.data(static_cast<int>(SmartListModel::Role::URI)).toString();
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400759
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400760 bool isContact = false;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500761 auto selectedAccountId = LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400762 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);
763 bool isRINGAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
764 try {
765 accountInfo.contactModel->getContact(contactURI.toStdString());
766 isContact = true;
767 }
768 catch (...) {}
769
Olivier SOLDANO31b9aac2017-07-14 15:50:09 -0400770 ui->imNameLabel->setText(QString(tr("%1", "%1 is the contact username"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400771 .arg(displayName));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400772
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400773 if (isRINGAccount && displayName != displayId){
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400774 ui->imIdLabel->show();
775 ui->imIdLabel->setText(QString(tr("%1", "%1 is the contact unique identifier"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400776 .arg(displayId));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400777 } else {
778 ui->imIdLabel->hide();
779 }
780
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400781 bool shouldShowSendContactRequestBtn = !isContact && isRINGAccount;
Andreas Traczyk912242e2018-10-29 14:44:44 -0400782 ui->sendContactRequestButton->setVisible(shouldShowSendContactRequestBtn);
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400783
Andreas Traczyk43c08232018-10-31 13:42:09 -0400784 auto convModel = LRCInstance::getCurrentConversationModel();
785 auto currentConversation = Utils::getConversationFromUid(selectedConvUid(),
786 *convModel);
787 ui->messageView->clear();
788 ui->messageView->printHistory(*convModel, currentConversation->interactions);
789
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400790 showConversationView();
Anthony Léonard041ad392017-07-14 16:44:09 -0400791
Andreas Traczyk43c08232018-10-31 13:42:09 -0400792 // Contact Avatars
793 auto accInfo = &LRCInstance::getCurrentAccountInfo();
794 auto contactUri = currentConversation->participants.front();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400795 try {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400796 auto& contact = accInfo->contactModel->getContact(contactUri);
Sébastien Blin942d1022018-12-13 09:49:03 -0500797 auto bestName = Utils::bestNameForConversation(*currentConversation, *convModel);
798 ui->messageView->setInvitation(
799 (contact.profileInfo.type == lrc::api::profile::Type::PENDING),
800 bestName,
801 accInfo->contactModel->getContactProfileId(contact.profileInfo.uri)
802 );
Andreas Traczyk43c08232018-10-31 13:42:09 -0400803 if (!contact.profileInfo.avatar.empty()) {
804 ui->messageView->setSenderImage(
805 accInfo->contactModel->getContactProfileId(contactUri),
806 contact.profileInfo.avatar);
807 } else {
808 auto avatar = Utils::conversationPhoto(selectedConvUid(), *accInfo);
809 QByteArray ba;
810 QBuffer bu(&ba);
811 avatar.save(&bu, "PNG");
812 std::string avatarString = ba.toBase64().toStdString();
813 ui->messageView->setSenderImage(
814 accInfo->contactModel->getContactProfileId(contactUri),
815 avatarString);
816 }
817 } catch (...) { }
Edric Milaretab12d022015-12-04 16:09:44 -0500818}
Edric Milaretfa05d972016-01-13 16:22:04 -0500819
820void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500821CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500822{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400823 Q_UNUSED(text);
824 processContactLineEdit();
Edric Milaretfa05d972016-01-13 16:22:04 -0500825}
Edric Milareta0ebd062016-01-13 12:18:23 -0500826
Nicolas Jagerca850292016-01-17 14:11:10 -0500827void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400828CallWidget::backToWelcomePage()
Edric Milareta0ebd062016-01-13 12:18:23 -0500829{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400830 deselectConversation();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400831 ui->messageView->hideMessages();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400832 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Nicolas Jagerca850292016-01-17 14:11:10 -0500833}
834
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400835void
836CallWidget::hideMiniSpinner()
Olivier SOLDANO19193412017-06-06 12:03:36 -0400837{
838 if(ui->spinnerLabel->isVisible()){
839 miniSpinner_->stop();
840 ui->spinnerLabel->hide();
841 }
842}
843
Nicolas Jagerca850292016-01-17 14:11:10 -0500844void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400845CallWidget::on_imBackButton_clicked()
846{
847 backToWelcomePage();
848}
849
850void
Edric Milaret1e598592016-09-02 10:10:01 -0400851CallWidget::on_qrButton_toggled(bool checked)
852{
853 ui->qrLabel->setVisible(checked);
854}
855
856void
Edric Milaret4097d2f2016-02-09 14:41:50 -0500857CallWidget::on_shareButton_clicked()
858{
Sébastien Blincba5b522018-12-10 12:48:36 -0500859 Utils::InvokeMailto(tr("Contact me on Jami"), tr("My Id is : ") + ui->ringIdLabel->text());
Edric Milaret4097d2f2016-02-09 14:41:50 -0500860}
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400861
862void
Andreas Traczyk912242e2018-10-29 14:44:44 -0400863CallWidget::on_sendContactRequestButton_clicked()
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400864{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400865 LRCInstance::getCurrentConversationModel()->makePermanent(selectedConvUid());
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400866}
867
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400868void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400869CallWidget::on_pendingCRBackButton_clicked()
870{
Olivier SOLDANO8179e992017-07-19 15:59:19 -0400871 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400872}
Anthony Léonard5cc76412017-04-21 16:52:25 -0400873
Andreas Traczyk912242e2018-10-29 14:44:44 -0400874void
875CallWidget::on_btnAudioCall_clicked()
876{
877 auto convUid = LRCInstance::getSelectedConvUid();
878 LRCInstance::getCurrentConversationModel()->placeAudioOnlyCall(convUid);
879 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
880}
881
882void
883CallWidget::on_btnVideoCall_clicked()
884{
885 auto convUid = LRCInstance::getSelectedConvUid();
886 LRCInstance::getCurrentConversationModel()->placeCall(convUid);
887 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
888}
889
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400890bool
891CallWidget::connectConversationModel()
Anthony Léonard5cc76412017-04-21 16:52:25 -0400892{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400893 auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get();
894
895 if (ui->smartList->selectionModel()) {
896 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
Anthony Léonard5cc76412017-04-21 16:52:25 -0400897 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400898
899 QObject::disconnect(modelSortedConnection_);
900 QObject::disconnect(modelUpdatedConnection_);
901 QObject::disconnect(filterChangedConnection_);
902 QObject::disconnect(newConversationConnection_);
903 QObject::disconnect(conversationRemovedConnection_);
904 QObject::disconnect(conversationClearedConnection);
905 QObject::disconnect(interactionStatusUpdatedConnection_);
906 QObject::disconnect(newInteractionConnection_);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400907 QObject::disconnect(interactionRemovedConnection_);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400908
909 modelSortedConnection_ = QObject::connect(
910 currentConversationModel, &lrc::api::ConversationModel::modelSorted,
911 [this]() {
912 updateConversationsFilterWidget();
913 selectSmartlistItem(selectedConvUid());
914 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400915 }
916 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400917 modelUpdatedConnection_ = QObject::connect(
918 currentConversationModel, &lrc::api::ConversationModel::conversationUpdated,
919 [this](const std::string& convUid) {
920 Q_UNUSED(convUid);
921 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400922 }
923 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400924 filterChangedConnection_ = QObject::connect(
925 currentConversationModel, &lrc::api::ConversationModel::filterChanged,
926 [this]() {
927 updateSmartList();
928 updateConversationsFilterWidget();
929 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400930 }
931 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400932 newConversationConnection_ = QObject::connect(
933 currentConversationModel, &lrc::api::ConversationModel::newConversation,
934 [this](const std::string& convUid) {
935 updateSmartList();
936 updateConversationForNewContact(convUid);
937 ui->conversationsFilterWidget->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400938 }
939 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400940 conversationRemovedConnection_ = QObject::connect(
941 currentConversationModel, &lrc::api::ConversationModel::conversationRemoved,
942 [this]() {
943 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400944 }
945 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400946 conversationClearedConnection = QObject::connect(
947 currentConversationModel, &lrc::api::ConversationModel::conversationCleared,
948 [this](const std::string& convUid) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400949 ui->messageView->clear();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400950 // if currently selected,
951 // switch to welcome screen (deselecting current smartlist item )
952 if (convUid != selectedConvUid()) {
953 return;
954 }
955 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400956 }
957 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400958 interactionStatusUpdatedConnection_ = QObject::connect(
959 currentConversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400960 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400961 if (convUid != selectedConvUid()) {
962 return;
963 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400964 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
965 auto currentConversationModel = currentAccountInfo.conversationModel.get();
966 currentConversationModel->clearUnreadInteractions(convUid);
967 ui->conversationsFilterWidget->update();
968 ui->messageView->updateInteraction(*currentConversationModel, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400969 }
970 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400971 newInteractionConnection_ = QObject::connect(
972 currentConversationModel, &lrc::api::ConversationModel::newInteraction,
973 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
974 onIncomingMessage(convUid, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400975 }
976 );
Andreas Traczyk43c08232018-10-31 13:42:09 -0400977 interactionRemovedConnection_ = QObject::connect(
978 currentConversationModel, &lrc::api::ConversationModel::interactionRemoved,
979 [this](const std::string& convUid, uint64_t interactionId) {
980 Q_UNUSED(convUid);
981 ui->messageView->removeInteraction(interactionId);
982 }
983 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400984 currentConversationModel->setFilter("");
985 // clear search field
986 ui->ringContactLineEdit->setText("");
987 return true;
988}
989
990void
991CallWidget::updateConversationView(const std::string& convUid)
992{
993 if (convUid != selectedConvUid()) {
994 return;
995 }
996
Andreas Traczyk43c08232018-10-31 13:42:09 -0400997
998
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400999}
1000
1001void
1002CallWidget::selectConversation(const QModelIndex& index)
1003{
1004 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1005
1006 if (currentConversationModel == nullptr || !index.isValid()) {
1007 return;
1008 }
1009
1010 const auto item = currentConversationModel->filteredConversation(index.row());
1011
1012 if (selectConversation(item, *currentConversationModel)) {
Andreas Traczyk43c08232018-10-31 13:42:09 -04001013 showIMOutOfCall(index);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001014 auto convUid = selectedConvUid();
1015 if (!lastConvUid_.compare(convUid)) {
1016 return;
1017 }
1018 lastConvUid_.assign(convUid);
1019 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1020 auto callModel = LRCInstance::getCurrentCallModel();
1021 auto conversation = Utils::getConversationFromUid(convUid, *currentConversationModel);
1022 const auto item = currentConversationModel->filteredConversation(index.row());
Andreas Traczyk43c08232018-10-31 13:42:09 -04001023 if (callModel->hasCall(conversation->callId) && item.callId == conversation->callId) {
1024 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
1025 ui->callStackWidget->show();
1026 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001027 }
Andreas Traczyk43c08232018-10-31 13:42:09 -04001028 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001029 }
Anthony Léonard5cc76412017-04-21 16:52:25 -04001030}
Anthony Léonardecfe7422017-05-04 14:14:37 -04001031
Anthony Léonard041ad392017-07-14 16:44:09 -04001032bool
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001033CallWidget::selectConversation( const lrc::api::conversation::Info& item,
1034 lrc::api::ConversationModel& convModel)
Anthony Léonard041ad392017-07-14 16:44:09 -04001035{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001036 if (selectedConvUid() == item.uid) {
1037 return false;
1038 } else if (item.participants.size() > 0) {
1039 convModel.selectConversation(item.uid);
1040 LRCInstance::setSelectedConvId(item.uid);
1041 convModel.clearUnreadInteractions(item.uid);
1042 ui->conversationsFilterWidget->update();
1043 return true;
Anthony Léonard041ad392017-07-14 16:44:09 -04001044 }
Anthony Léonard041ad392017-07-14 16:44:09 -04001045}
1046
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001047void
1048CallWidget::deselectConversation()
Anthony Léonardecfe7422017-05-04 14:14:37 -04001049{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001050 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1051
1052 if (currentConversationModel == nullptr) {
1053 return;
1054 }
1055
1056 currentConversationModel->selectConversation("");
1057 LRCInstance::setSelectedConvId("");
1058
1059 ui->smartList->selectionModel()->clear();
1060 disconnect(imConnection_);
Anthony Léonardecfe7422017-05-04 14:14:37 -04001061}
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001062
1063void
1064CallWidget::updateConversationForNewContact(const std::string& convUid)
1065{
1066 auto convModel = LRCInstance::getCurrentConversationModel();
1067 if (convModel == nullptr) {
1068 return;
1069 }
1070 ui->ringContactLineEdit->setText("");
1071 auto selectedUid = selectedConvUid();
1072 auto it = Utils::getConversationFromUid(convUid, *convModel);
1073 if (it != convModel->allFilteredConversations().end()) {
1074 try {
1075 auto contact = convModel->owner.contactModel->getContact(it->participants[0]);
1076 if (!contact.profileInfo.uri.empty() && contact.profileInfo.uri.compare(selectedUid) == 0) {
1077 LRCInstance::setSelectedConvId(convUid);
1078 convModel->selectConversation(convUid);
1079 }
1080 } catch (...) {
1081 return;
1082 }
1083 }
1084}
1085
1086void
1087CallWidget::updateSmartList()
1088{
1089 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
Andreas Traczykfc33a492018-12-14 13:53:13 -05001090 smartListModel_.reset(new SmartListModel(currentAccountInfo, this));
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001091 ui->smartList->setModel(smartListModel_.get());
1092 ui->smartList->setItemDelegate(new ConversationItemDelegate());
1093
1094 // smartlist selection
1095 QObject::disconnect(smartlistSelectionConnection_);
1096 smartlistSelectionConnection_ = connect(ui->smartList->selectionModel(),
1097 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
1098 this,
1099 SLOT(smartListSelectionChanged(QItemSelection, QItemSelection)));
1100}
1101
1102void
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001103CallWidget::updateComboBox()
1104{
1105 ui->currentAccountComboBox->updateComboBoxDisplay();
1106}
1107
1108void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001109CallWidget::update()
1110{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001111 updateSmartList();
1112 updateConversationsFilterWidget();
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001113 updateComboBox();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001114 connectConversationModel();
Isa Nanic601de1d2018-10-23 11:37:26 -04001115}