blob: 456d7334ab21eb02135b617e805273bdd4cd1395 [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);
Sébastien Blin93bd2062018-12-17 15:57:16 -0500112 ui->mainActivitySplitter->setCollapsible(1, false);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400113 ui->splitter->setCollapsible(0, false);
114 ui->splitter->setCollapsible(1, false);
115
Isa Nanic601de1d2018-10-23 11:37:26 -0400116 //disable dropdown shadow on combobox
117 ui->currentAccountComboBox->view()->window()->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
118
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400119 // conversation list
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400120 ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
121
122 // setup searchingfor mini spinner
123 miniSpinner_ = new QMovie(":/images/waiting.gif");
124 ui->spinnerLabel->setMovie(miniSpinner_);
125 ui->spinnerLabel->hide();
126
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400127 // connections
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400128 connect(ui->currentAccountComboBox, &CurrentAccountComboBox::settingsButtonClicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400129 this, &CallWidget::settingsButtonClicked);
130
Andreas Traczyk43c08232018-10-31 13:42:09 -0400131 connect(ui->videoWidget, &VideoView::setChatVisibility,
132 [this](bool visible) {
Sébastien Blin93bd2062018-12-17 15:57:16 -0500133 if (visible) {
134 ui->messagesWidget->show();
135 } else {
136 ui->messagesWidget->hide();
137 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400138 });
139
140 connect(ui->mainActivitySplitter, &QSplitter::splitterMoved,
141 [this](int pos, int index) {
142 QSettings settings;
143 settings.setValue(SettingsKey::mainSplitterState, ui->mainActivitySplitter->saveState());
144 });
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400145
146 connect(ui->videoWidget, &VideoView::videoSettingsClicked,
147 this, &CallWidget::settingsButtonClicked);
148
Andreas Traczyk43c08232018-10-31 13:42:09 -0400149 connect(ui->btnConversations, &QPushButton::clicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400150 this, &CallWidget::conversationsButtonClicked);
151
Andreas Traczyk43c08232018-10-31 13:42:09 -0400152 connect(ui->btnInvites, &QPushButton::clicked,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400153 this, &CallWidget::invitationsButtonClicked);
154
Andreas Traczyk43c08232018-10-31 13:42:09 -0400155 connect(ui->smartList, &QTreeView::customContextMenuRequested,
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400156 this, &CallWidget::slotCustomContextMenuRequested);
157
158 connect(ui->smartList, &SmartListView::btnAcceptInviteClicked,
159 this, &CallWidget::slotAcceptInviteClicked);
160
161 connect(ui->smartList, &SmartListView::btnBlockInviteClicked,
162 this, &CallWidget::slotBlockInviteClicked);
163
164 connect(ui->smartList, &SmartListView::btnIgnoreInviteClicked,
165 this, &CallWidget::slotIgnoreInviteClicked);
166
167 connect(&LRCInstance::behaviorController(), &BehaviorController::showCallView,
168 this, &CallWidget::slotShowCallView);
169
170 connect(&LRCInstance::behaviorController(), &BehaviorController::showIncomingCallView,
171 this, &CallWidget::slotShowIncomingCallView);
172
173 connect(&LRCInstance::behaviorController(), &BehaviorController::showChatView,
174 this, &CallWidget::slotShowChatView);
Andreas Traczyk55f92cb2018-10-23 12:26:25 -0400175
Isa Nanic601de1d2018-10-23 11:37:26 -0400176 connect(ui->currentAccountComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
177 this, &CallWidget::slotAccountChanged);
178
Andreas Traczyk912242e2018-10-29 14:44:44 -0400179 connect(ui->sendContactRequestButton, &QPushButton::clicked,
180 this, &CallWidget::on_sendContactRequestButton_clicked);
181
182 connect(ui->btnAudioCall, &QPushButton::clicked,
183 this, &CallWidget::on_sendContactRequestButton_clicked);
184
185 connect(ui->btnVideoCall, &QPushButton::clicked,
186 this, &CallWidget::on_sendContactRequestButton_clicked);
187
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400188 connect(ui->currentAccountComboBox, QOverload<int>::of(&CurrentAccountComboBox::currentIndexChanged),
189 [this] {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400190 ui->btnConversations->setChecked(true);
191 ui->btnInvites->setChecked(false);
192 });
193
Andreas Traczyk55f92cb2018-10-23 12:26:25 -0400194 // set first view to welcome view
195 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400196 ui->btnConversations->setChecked(true);
197
198 // chat view
199 ui->messageView->buildView();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500200
Andreas Traczykb81281e2018-12-13 13:13:28 -0500201 // hide the call stack
202 ui->callStackWidget->hide();
Andreas Traczykfc33a492018-12-14 13:53:13 -0500203
204 ui->containerWidget->setVisible(false);
Edric Milaret627500d2015-03-27 16:41:40 -0400205}
206
207CallWidget::~CallWidget()
208{
209 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400210 delete menu_;
Edric Milaret00a32252016-01-19 10:37:13 -0500211}
212
Andreas Traczykfc33a492018-12-14 13:53:13 -0500213void
214CallWidget::navigated(bool to)
215{
216 ui->containerWidget->setVisible(to);
217 if (to) {
218 updateSmartList();
219 connectConversationModel();
220 } else {
221 QObject::disconnect(smartlistSelectionConnection_);
222 smartListModel_.reset(nullptr);
223 }
224}
225
Andreas Traczykb81281e2018-12-13 13:13:28 -0500226int
227CallWidget::getLeftPanelWidth()
228{
229 return ui->currentAccountComboBox->width();
230}
231
Edric Milaret00a32252016-01-19 10:37:13 -0500232void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400233CallWidget::onIncomingMessage(const std::string& convUid,
234 uint64_t interactionId,
235 const lrc::api::interaction::Info& interaction)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400236{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400237 Q_UNUSED(interactionId);
Edric Milaret00a32252016-01-19 10:37:13 -0500238 if (!QApplication::focusWidget()) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400239 auto convModel = LRCInstance::getCurrentConversationModel();
240 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
241 auto bestName = Utils::bestNameForConversation(*conversation, *convModel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400242 Utils::showSystemNotification(this,
243 QString(tr("Message incoming from %1"))
Andreas Traczyk43c08232018-10-31 13:42:09 -0400244 .arg(QString::fromStdString(bestName)));
Edric Milaret00a32252016-01-19 10:37:13 -0500245 }
Andreas Traczyk1d8159a2018-12-13 15:48:24 -0500246 updateConversationsFilterWidget();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400247 if (convUid != selectedConvUid()) {
248 return;
249 }
250
251 auto convModel = LRCInstance::getCurrentConversationModel();
252 convModel->clearUnreadInteractions(convUid);
253 auto currentConversation = Utils::getConversationFromUid(convUid, *convModel);
254 if (currentConversation == convModel->allFilteredConversations().end()) {
255 return;
256 }
257 ui->messageView->printNewInteraction(*convModel, interactionId, interaction);
Edric Milareta0ebd062016-01-13 12:18:23 -0500258}
259
260void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400261CallWidget::setupSmartListContextMenu(const QPoint& pos)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400262{
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400263 QPoint globalPos = ui->smartList->mapToGlobal(pos);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400264 auto index = ui->smartList->indexAt(pos);
265 if (not index.isValid()) {
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400266 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400267 }
268
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400269 auto convModel = LRCInstance::getCurrentConversationModel();
270 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID))
271 .value<QString>()
272 .toStdString();
273 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
274 auto contactUid = (*conversation).participants.at(0);
275 auto contact = LRCInstance::getCurrentAccountInfo().contactModel.get()->getContact(contactUid);
276
277 if (!Utils::isContactValid(contactUid, *convModel)) {
278 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400279 }
280
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400281 QMenu menu;
282
283 // video call
284 auto videoCallAction = new QAction(tr("Start video call"), this);
285 menu.addAction(videoCallAction);
286 connect(videoCallAction, &QAction::triggered,
287 [this, convUid, conversation, convModel]() {
288 convModel->placeCall(convUid);
289 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
290 if (convUid != selectedConvUid()) {
291 selectConversation(*conversation, *convModel);
292 }
293 });
294 // audio call
295 auto audioCallAction = new QAction(tr("Start audio call"), this);
296 menu.addAction(audioCallAction);
297 connect(audioCallAction, &QAction::triggered,
298 [this, convUid, conversation, convModel]() {
299 convModel->placeAudioOnlyCall(convUid);
300 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
301 if (convUid != selectedConvUid()) {
302 selectConversation(*conversation, *convModel);
303 }
304 });
305
306 if (contact.profileInfo.type == lrc::api::profile::Type::RING) {
307 // separator
308 menu.addSeparator();
309
310 // clear conversation
311 auto clearConversationAction = new QAction(tr("Clear conversation"), this);
312 menu.addAction(clearConversationAction);
313 connect(clearConversationAction, &QAction::triggered,
314 [convUid]() {
315 LRCInstance::getCurrentConversationModel()->clearHistory(convUid);
316 });
Sébastien Blin31fccce2018-12-13 11:27:05 -0500317 // remove contact
318 auto removeContactAction = new QAction(tr("Remove contact"), this);
319 menu.addAction(removeContactAction);
320 connect(removeContactAction, &QAction::triggered,
321 [convUid]() {
322 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, false);
323 });
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400324 // block contact
325 auto blockContactAction = new QAction(tr("Block contact"), this);
326 menu.addAction(blockContactAction);
327 connect(blockContactAction, &QAction::triggered,
328 [convUid]() {
329 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
330 });
331
332 // separator
333 menu.addSeparator();
334
335 // copy number(infohash)
336 auto copyNumberAction = new QAction(tr("Copy number"), this);
337 menu.addAction(copyNumberAction);
338 connect(copyNumberAction, &QAction::triggered,
339 [contact]() {
340 QApplication::clipboard()->setText(
341 QString::fromStdString(contact.profileInfo.uri)
342 );
343 });
344 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400345 smartListModel_->isContextMenuOpen = true;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400346 menu.exec(globalPos);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400347 smartListModel_->isContextMenuOpen = false;
Edric Milareta0ebd062016-01-13 12:18:23 -0500348}
349
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400350void
351CallWidget::setupQRCode(QString ringID)
Edric Milarete19c4cd2016-02-12 10:19:44 -0500352{
Anthony Léonarda86a8972016-12-15 10:33:47 -0500353 auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
Edric Milaret6d0e5312016-04-04 16:30:22 -0400354 0, //Let the version be decided by libqrencode
355 QR_ECLEVEL_L, // Lowest level of error correction
Edric Milarete19c4cd2016-02-12 10:19:44 -0500356 QR_MODE_8, // 8-bit data mode
357 1);
358 if (not rcode) {
359 qWarning() << "Failed to generate QR code: " << strerror(errno);
360 return;
361 }
362
363 auto margin = 5;
364 int qrwidth = rcode->width + margin * 2;
365 QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono);
366 QPainter painter;
367 painter.begin(&result);
368 painter.setClipRect(QRect(0, 0, qrwidth, qrwidth));
369 painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
370 painter.setBrush(Qt::black);
371 painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
Edric Milaret74474f52016-05-16 13:36:23 -0400372 unsigned char* p;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500373 p = rcode->data;
374 for(int y = 0; y < rcode->width; y++) {
Edric Milaret74474f52016-05-16 13:36:23 -0400375 unsigned char* row = (p + (y * rcode->width));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500376 for(int x = 0; x < rcode->width; x++) {
377 if(*(row + x) & 0x1) {
378 painter.drawRect(margin + x, margin + y, 1, 1);
379 }
380 }
381
382 }
383 painter.end();
384 QRcode_free(rcode);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400385 ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_),
386 Qt::KeepAspectRatio)));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500387}
388
Edric Milaret627500d2015-03-27 16:41:40 -0400389void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400390CallWidget::on_smartList_clicked(const QModelIndex& index)
Edric Milaret00d34f22016-05-09 16:30:29 -0400391{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400392 Q_UNUSED(index);
Edric Milaret627500d2015-03-27 16:41:40 -0400393}
394
395void
396CallWidget::on_acceptButton_clicked()
397{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400398 auto convModel = LRCInstance::getCurrentConversationModel();
399 auto callModel = LRCInstance::getCurrentCallModel();
400 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
401 callModel->accept(conversation->callId);
Edric Milaret627500d2015-03-27 16:41:40 -0400402}
403
404void
405CallWidget::on_refuseButton_clicked()
406{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400407 auto convModel = LRCInstance::getCurrentConversationModel();
408 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
409 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
410 showConversationView();
Edric Milaret6456baa2015-05-21 12:18:07 -0400411}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400412
413void
Edric Milareted0b2802015-10-01 15:10:02 -0400414CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400415{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400416 auto convModel = LRCInstance::getCurrentConversationModel();
417 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
418 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
419 showConversationView();
Edric Milaretd8528fa2015-07-07 14:13:51 -0400420}
Edric Milareted0b2802015-10-01 15:10:02 -0400421
422void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400423CallWidget::showConversationView()
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400424{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400425 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
426 ui->messageView->setFocus();
Sébastien Blin93bd2062018-12-17 15:57:16 -0500427 if (ui->messagesWidget->isHidden()) {
428 ui->messagesWidget->show();
429 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400430}
431
432void
433CallWidget::selectSmartlistItem(const std::string & convUid)
434{
435 if (convUid.empty()) {
436 return;
437 }
438 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
439 auto convModel = LRCInstance::getCurrentConversationModel();
440 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
441 if (conversation == convModel->allFilteredConversations().end()) {
442 return;
443 }
444 auto contactURI = QString::fromStdString((*conversation).participants[0]);
445 if (contactURI.isEmpty() ||
446 convModel->owner.contactModel->getContact(contactURI.toStdString()).profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
447 return;
448 }
449 for (int row = 0; row < smartListModel_->rowCount(); row++) {
450 QModelIndex index = smartListModel_->index(row);
451 auto indexContactURI = index.data(SmartListModel::Role::URI).value<QString>();
452 if (indexContactURI == contactURI) {
453 ui->smartList->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
454 return;
455 }
456 }
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400457}
458
459void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500460CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400461{
Olivier SOLDANO70279d32017-07-18 15:21:34 -0400462 if (!index.isValid())
463 return;
464
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400465 LRCInstance::getCurrentConversationModel()->placeCall(selectedConvUid());
Edric Milareted0b2802015-10-01 15:10:02 -0400466
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400467 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(selectedConvUid())));
468}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500469
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400470QImage
471CallWidget::imageForConv(const std::string& convUid)
472{
473 return Utils::conversationPhoto(convUid, LRCInstance::getCurrentAccountInfo());
474}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500475
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400476const std::string&
477CallWidget::selectedAccountId()
478{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500479 return LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400480}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500481
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400482const std::string&
483CallWidget::selectedConvUid()
484{
485 return LRCInstance::getSelectedConvUid();
Edric Milareted0b2802015-10-01 15:10:02 -0400486}
487
488void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400489CallWidget::smartListSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500490{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400491 Q_UNUSED(deselected);
492 QModelIndexList indices = selected.indexes();
493
494 if (indices.isEmpty()) {
Edric Milareted0b2802015-10-01 15:10:02 -0400495 return;
Anthony Léonardecfe7422017-05-04 14:14:37 -0400496 }
Edric Milareted0b2802015-10-01 15:10:02 -0400497
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400498 auto selectedIndex = indices.at(0);
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500499
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400500 if (not selectedIndex.isValid()) {
501 return;
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400502 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400503
504 selectConversation(selectedIndex);
Edric Milareted0b2802015-10-01 15:10:02 -0400505}
506
507void
508CallWidget::placeCall()
509{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500510 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400511 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500512 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400513 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500514 ui->ringContactLineEdit->clear();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400515 auto photoRect = ui->callingPhoto->frameGeometry();
Edric1bed3f92016-05-19 10:24:48 -0400516 ui->callingPhoto->setPixmap(
517 QPixmap::fromImage(
518 GlobalInstances::pixmapManipulator()
Andreas Traczyk43c08232018-10-31 13:42:09 -0400519 .callPhoto(c, QSize(photoRect.width(), photoRect.height()))
520 .value<QImage>()));
Edric Milareted0b2802015-10-01 15:10:02 -0400521}
522
523void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400524CallWidget::conversationsButtonClicked()
525{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400526 ui->btnConversations->setChecked(true);
527 ui->btnInvites->setChecked(false);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400528 setConversationFilter(lrc::api::profile::Type::RING);
529}
530
531void
532CallWidget::invitationsButtonClicked()
533{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400534 ui->btnConversations->setChecked(false);
535 ui->btnInvites->setChecked(true);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400536 setConversationFilter(lrc::api::profile::Type::PENDING);
537}
538
539void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500540CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400541{
Andreas Traczyk7548e732018-12-12 10:47:21 -0500542 emit NavigationRequested(ScreenEnum::SetttingsScreen);
Edric Milareted0b2802015-10-01 15:10:02 -0400543}
544
545void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400546CallWidget::processContactLineEdit()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500547{
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400548 auto contactLineText = ui->ringContactLineEdit->text();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400549 setConversationFilter(contactLineText);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500550}
551
552void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400553CallWidget::on_ringContactLineEdit_returnPressed()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500554{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400555 // select current temporary item and show conversation
556 auto convModel = LRCInstance::getCurrentConversationModel();
557 auto conversations = convModel->allFilteredConversations();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400558 if (!conversations.empty() &&
559 Utils::isContactValid(conversations.at(0).participants.at(0), *convModel)) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400560 selectConversation(smartListModel_->index(0));
561 }
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400562}
563
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400564void CallWidget::slotAcceptInviteClicked(const QModelIndex & index)
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400565{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400566 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
567 LRCInstance::getCurrentConversationModel()->makePermanent(convUid.toStdString());
Nicolas Jager97a21b42015-12-03 16:55:45 -0500568}
569
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400570void CallWidget::slotBlockInviteClicked(const QModelIndex & index)
Nicolas Jager97a21b42015-12-03 16:55:45 -0500571{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400572 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
573 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), true);
574}
575
576void CallWidget::slotIgnoreInviteClicked(const QModelIndex & index)
577{
578 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
Sébastien Blin31fccce2018-12-13 11:27:05 -0500579 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), false);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400580}
581
582void CallWidget::slotCustomContextMenuRequested(const QPoint& pos)
583{
584 setupSmartListContextMenu(pos);
585}
586
Isa Nanic601de1d2018-10-23 11:37:26 -0400587void CallWidget::slotAccountChanged(int index)
588{
589 auto accountList = LRCInstance::accountModel().getAccountList();
590 setSelectedAccount(accountList.at(index));
591}
592
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400593void CallWidget::slotShowCallView(const std::string& accountId,
594 const lrc::api::conversation::Info& convInfo)
595{
596 Q_UNUSED(accountId);
597 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400598 qDebug() << "slotShowCallView";
599 ui->callStackWidget->show();
600 ui->callStackWidget->setCurrentWidget(ui->videoPage);
Sébastien Blin93bd2062018-12-17 15:57:16 -0500601 ui->videoWidget->showChatviewIfToggled();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400602 hideMiniSpinner();
603}
604
605void CallWidget::slotShowIncomingCallView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400606 const lrc::api::conversation::Info& convInfo)
607{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400608 Q_UNUSED(accountId);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400609 qDebug() << "slotShowIncomingCallView";
610
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400611 auto callModel = LRCInstance::getCurrentCallModel();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400612
613 if (!callModel->hasCall(convInfo.callId)) {
Nicolas Jager97a21b42015-12-03 16:55:45 -0500614 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400615 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500616
Andreas Traczyk43c08232018-10-31 13:42:09 -0400617 auto convModel = LRCInstance::getCurrentConversationModel();
618 ui->callerPhoto->setPixmap(QPixmap::fromImage(imageForConv(convInfo.uid)));
619 auto bestName = QString::fromStdString(Utils::bestNameForConversation(convInfo, *convModel));
620 auto bestId = QString::fromStdString(Utils::bestIdForConversation(convInfo, *convModel));
621 auto finalBestId = (bestName != bestId) ? bestId : "";
622
623 auto call = callModel->getCall(convInfo.callId);
624 auto isCallSelected = selectedConvUid() == convInfo.uid;
625
626 if (call.isOutgoing) {
627 if (isCallSelected) {
628 miniSpinner_->start();
629 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
630 ui->spinnerLabel->show();
631 ui->callStackWidget->setCurrentWidget(ui->outgoingCallPage);
632 ui->callStackWidget->show();
633 }
634 } else {
635 if (!QApplication::focusWidget()) {
636 auto formattedName = Utils::bestNameForConversation(convInfo, *convModel);
637 Utils::showSystemNotification(this,
638 QString(tr("Call incoming from %1")).arg(QString::fromStdString(formattedName)));
639 }
640 selectSmartlistItem(convInfo.uid);
641 auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
642 auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
643 if (accountProperties.autoAnswer) {
644 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
645 ui->callStackWidget->setCurrentWidget(ui->videoPage);
646 } else if (isCallSelected) {
647 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
648 ui->callStackWidget->setCurrentWidget(ui->incomingCallPage);
649 ui->callStackWidget->show();
650 }
651 }
652
Sébastien Blin93bd2062018-12-17 15:57:16 -0500653 if (ui->messagesWidget->isHidden()) {
654 ui->messagesWidget->show();
655 }
656
Andreas Traczyk43c08232018-10-31 13:42:09 -0400657 // flashing index widget during call
658 for (int row = 0; row < smartListModel_->rowCount(); row++) {
659 QModelIndex index = smartListModel_->index(row);
660 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
661 if (indexUid == convInfo.uid) {
662 auto widget = ui->smartList->indexWidget(index);
663 if (!widget) {
664 auto blinkingWidget = new AnimatedOverlay(RingTheme::urgentOrange_);
665 ui->smartList->setIndexWidget(index, blinkingWidget);
666 blinkingWidget->show();
667 } else {
668 widget->show();
669 }
670 }
671 }
672
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400673 ui->videoWidget->pushRenderer(convInfo.callId);
Andreas Traczykfd0d7c02018-10-30 17:14:06 -0400674
Andreas Traczyk43c08232018-10-31 13:42:09 -0400675 QFontMetrics primaryCallLabelFontMetrics(ui->callingBestNameLabel->font());
676 QFontMetrics sencondaryCallLabelFontMetrics(ui->callingBestIdLabel->font());
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400677
Andreas Traczyk43c08232018-10-31 13:42:09 -0400678 QString elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callerBestNameLabel->width());
679 ui->callerBestNameLabel->setText(elidedLabel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400680
Andreas Traczyk43c08232018-10-31 13:42:09 -0400681 elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callingBestNameLabel->width());
682 ui->callingBestNameLabel->setText(elidedLabel);
683
684 elidedLabel = sencondaryCallLabelFontMetrics.elidedText(finalBestId, Qt::ElideRight, ui->callingBestIdLabel->width());
685 ui->callingBestIdLabel->setText(elidedLabel);
686
687 ui->smartList->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400688}
689
690void CallWidget::slotShowChatView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400691 const lrc::api::conversation::Info& convInfo)
692{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400693 Q_UNUSED(accountId);
694 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400695
696 for (int row = 0; row < smartListModel_->rowCount(); row++) {
697 QModelIndex index = smartListModel_->index(row);
698 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
699 if (indexUid == convInfo.uid) {
700 if (auto widget = ui->smartList->indexWidget(index)) {
701 widget->hide();
702 widget->deleteLater();
703 ui->smartList->setIndexWidget(index, nullptr);
704 }
705 }
706 }
707
708 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400709 showConversationView();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500710}
Edric Milaretab12d022015-12-04 16:09:44 -0500711
712void
Sébastien Blin93bd2062018-12-17 15:57:16 -0500713CallWidget::slotToggleFullScreenClicked()
714{
715 if (ui->mainActivityWidget->isFullScreen()) {
716 ui->stackedWidget->addWidget(ui->mainActivityWidget);
717 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
718 ui->mainActivityWidget->showNormal();
719 } else {
720 ui->stackedWidget->removeWidget(ui->mainActivityWidget);
721 ui->mainActivityWidget->setParent(0);
722 ui->mainActivityWidget->showFullScreen();
723 }
724}
725
726void
727CallWidget::slotVideoViewDestroyed(const std::string& callid)
728{
729 auto convUid = LRCInstance::getSelectedConvUid();
730 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
731 auto callModel = LRCInstance::getCurrentCallModel();
732 auto conversation = Utils::getConversationFromUid(convUid, *currentConversationModel);
733 if (callid != conversation->callId) return;
734 if (ui->mainActivityWidget->isFullScreen()) {
735 ui->stackedWidget->addWidget(ui->mainActivityWidget);
736 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
737 ui->mainActivityWidget->showNormal();
738 }
739 showConversationView();
740}
741
742void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400743CallWidget::setSelectedAccount(const std::string& accountId)
744{
745 LRCInstance::setSelectedAccountId(accountId);
746
747 // First, we get back to the welcome view (except if in call)
748 if (ui->stackedWidget->currentWidget() != ui->videoPage &&
749 ui->stackedWidget->currentWidget() != ui->welcomePage) {
750 Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
751 }
752
753 // We setup the ringIdLabel and the QRCode
754 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
755 auto id = accountInfo.registeredName.empty() ? accountInfo.profileInfo.uri : accountInfo.registeredName;
756 auto isRingAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
757 if (isRingAccount) {
758 ui->ringIdLabel->setText(QString::fromStdString(id));
759 setupQRCode(QString::fromStdString(accountInfo.profileInfo.uri));
760 }
761
762 updateSmartList();
763 currentTypeFilter_ = accountInfo.profileInfo.type;
764 LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
765 updateConversationsFilterWidget();
766 connectConversationModel();
767}
768
769void CallWidget::setConversationFilter(lrc::api::profile::Type filter)
770{
771 if (currentTypeFilter_ == filter) {
772 return;
773 }
774 currentTypeFilter_ = filter;
775 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
776}
777
778void CallWidget::updateConversationsFilterWidget()
779{
780 auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
781 if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
782 currentTypeFilter_ = lrc::api::profile::Type::RING;
783 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
784 }
785 ui->conversationsFilterWidget->setVisible(invites);
Andreas Traczyk1d8159a2018-12-13 15:48:24 -0500786 ui->conversationsFilterWidget->updateBadges();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400787 ui->conversationsFilterWidget->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400788}
789
790void CallWidget::setConversationFilter(const QString & filter)
791{
792 LRCInstance::getCurrentConversationModel()->setFilter(filter.toStdString());
Anthony Léonardd47179c2017-03-28 10:39:10 -0400793}
794
795void
Edric Milaret6b68a482016-02-01 15:23:44 -0500796CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500797{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400798 QString displayName = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayName)).toString();
799 QString displayId = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayID)).toString();
800 QString contactURI = nodeIdx.data(static_cast<int>(SmartListModel::Role::URI)).toString();
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400801
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400802 bool isContact = false;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500803 auto selectedAccountId = LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400804 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);
805 bool isRINGAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
806 try {
807 accountInfo.contactModel->getContact(contactURI.toStdString());
808 isContact = true;
809 }
810 catch (...) {}
811
Olivier SOLDANO31b9aac2017-07-14 15:50:09 -0400812 ui->imNameLabel->setText(QString(tr("%1", "%1 is the contact username"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400813 .arg(displayName));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400814
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400815 if (isRINGAccount && displayName != displayId){
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400816 ui->imIdLabel->show();
817 ui->imIdLabel->setText(QString(tr("%1", "%1 is the contact unique identifier"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400818 .arg(displayId));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400819 } else {
820 ui->imIdLabel->hide();
821 }
822
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400823 bool shouldShowSendContactRequestBtn = !isContact && isRINGAccount;
Andreas Traczyk912242e2018-10-29 14:44:44 -0400824 ui->sendContactRequestButton->setVisible(shouldShowSendContactRequestBtn);
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400825
Andreas Traczyk43c08232018-10-31 13:42:09 -0400826 auto convModel = LRCInstance::getCurrentConversationModel();
827 auto currentConversation = Utils::getConversationFromUid(selectedConvUid(),
828 *convModel);
829 ui->messageView->clear();
830 ui->messageView->printHistory(*convModel, currentConversation->interactions);
831
Andreas Traczyk43c08232018-10-31 13:42:09 -0400832 // Contact Avatars
833 auto accInfo = &LRCInstance::getCurrentAccountInfo();
834 auto contactUri = currentConversation->participants.front();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400835 try {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400836 auto& contact = accInfo->contactModel->getContact(contactUri);
Sébastien Blin942d1022018-12-13 09:49:03 -0500837 auto bestName = Utils::bestNameForConversation(*currentConversation, *convModel);
838 ui->messageView->setInvitation(
839 (contact.profileInfo.type == lrc::api::profile::Type::PENDING),
840 bestName,
841 accInfo->contactModel->getContactProfileId(contact.profileInfo.uri)
842 );
Andreas Traczyk43c08232018-10-31 13:42:09 -0400843 if (!contact.profileInfo.avatar.empty()) {
844 ui->messageView->setSenderImage(
845 accInfo->contactModel->getContactProfileId(contactUri),
846 contact.profileInfo.avatar);
847 } else {
848 auto avatar = Utils::conversationPhoto(selectedConvUid(), *accInfo);
849 QByteArray ba;
850 QBuffer bu(&ba);
851 avatar.save(&bu, "PNG");
852 std::string avatarString = ba.toBase64().toStdString();
853 ui->messageView->setSenderImage(
854 accInfo->contactModel->getContactProfileId(contactUri),
855 avatarString);
856 }
857 } catch (...) { }
Edric Milaretab12d022015-12-04 16:09:44 -0500858}
Edric Milaretfa05d972016-01-13 16:22:04 -0500859
860void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500861CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500862{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400863 Q_UNUSED(text);
864 processContactLineEdit();
Edric Milaretfa05d972016-01-13 16:22:04 -0500865}
Edric Milareta0ebd062016-01-13 12:18:23 -0500866
Nicolas Jagerca850292016-01-17 14:11:10 -0500867void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400868CallWidget::backToWelcomePage()
Edric Milareta0ebd062016-01-13 12:18:23 -0500869{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400870 deselectConversation();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400871 ui->messageView->hideMessages();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400872 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Nicolas Jagerca850292016-01-17 14:11:10 -0500873}
874
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400875void
876CallWidget::hideMiniSpinner()
Olivier SOLDANO19193412017-06-06 12:03:36 -0400877{
878 if(ui->spinnerLabel->isVisible()){
879 miniSpinner_->stop();
880 ui->spinnerLabel->hide();
881 }
882}
883
Nicolas Jagerca850292016-01-17 14:11:10 -0500884void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400885CallWidget::on_imBackButton_clicked()
886{
887 backToWelcomePage();
888}
889
890void
Edric Milaret1e598592016-09-02 10:10:01 -0400891CallWidget::on_qrButton_toggled(bool checked)
892{
893 ui->qrLabel->setVisible(checked);
894}
895
896void
Edric Milaret4097d2f2016-02-09 14:41:50 -0500897CallWidget::on_shareButton_clicked()
898{
Sébastien Blincba5b522018-12-10 12:48:36 -0500899 Utils::InvokeMailto(tr("Contact me on Jami"), tr("My Id is : ") + ui->ringIdLabel->text());
Edric Milaret4097d2f2016-02-09 14:41:50 -0500900}
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400901
902void
Andreas Traczyk912242e2018-10-29 14:44:44 -0400903CallWidget::on_sendContactRequestButton_clicked()
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400904{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400905 LRCInstance::getCurrentConversationModel()->makePermanent(selectedConvUid());
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400906}
907
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400908void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400909CallWidget::on_pendingCRBackButton_clicked()
910{
Olivier SOLDANO8179e992017-07-19 15:59:19 -0400911 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400912}
Anthony Léonard5cc76412017-04-21 16:52:25 -0400913
Andreas Traczyk912242e2018-10-29 14:44:44 -0400914void
915CallWidget::on_btnAudioCall_clicked()
916{
917 auto convUid = LRCInstance::getSelectedConvUid();
918 LRCInstance::getCurrentConversationModel()->placeAudioOnlyCall(convUid);
919 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
920}
921
922void
923CallWidget::on_btnVideoCall_clicked()
924{
925 auto convUid = LRCInstance::getSelectedConvUid();
926 LRCInstance::getCurrentConversationModel()->placeCall(convUid);
927 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
928}
929
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400930bool
931CallWidget::connectConversationModel()
Anthony Léonard5cc76412017-04-21 16:52:25 -0400932{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400933 auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get();
934
935 if (ui->smartList->selectionModel()) {
936 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
Anthony Léonard5cc76412017-04-21 16:52:25 -0400937 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400938
939 QObject::disconnect(modelSortedConnection_);
940 QObject::disconnect(modelUpdatedConnection_);
941 QObject::disconnect(filterChangedConnection_);
942 QObject::disconnect(newConversationConnection_);
943 QObject::disconnect(conversationRemovedConnection_);
944 QObject::disconnect(conversationClearedConnection);
945 QObject::disconnect(interactionStatusUpdatedConnection_);
946 QObject::disconnect(newInteractionConnection_);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400947 QObject::disconnect(interactionRemovedConnection_);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400948
949 modelSortedConnection_ = QObject::connect(
950 currentConversationModel, &lrc::api::ConversationModel::modelSorted,
951 [this]() {
952 updateConversationsFilterWidget();
953 selectSmartlistItem(selectedConvUid());
954 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400955 }
956 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400957 modelUpdatedConnection_ = QObject::connect(
958 currentConversationModel, &lrc::api::ConversationModel::conversationUpdated,
959 [this](const std::string& convUid) {
960 Q_UNUSED(convUid);
961 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400962 }
963 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400964 filterChangedConnection_ = QObject::connect(
965 currentConversationModel, &lrc::api::ConversationModel::filterChanged,
966 [this]() {
967 updateSmartList();
968 updateConversationsFilterWidget();
969 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400970 }
971 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400972 newConversationConnection_ = QObject::connect(
973 currentConversationModel, &lrc::api::ConversationModel::newConversation,
974 [this](const std::string& convUid) {
975 updateSmartList();
976 updateConversationForNewContact(convUid);
977 ui->conversationsFilterWidget->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400978 }
979 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400980 conversationRemovedConnection_ = QObject::connect(
981 currentConversationModel, &lrc::api::ConversationModel::conversationRemoved,
982 [this]() {
983 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400984 }
985 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400986 conversationClearedConnection = QObject::connect(
987 currentConversationModel, &lrc::api::ConversationModel::conversationCleared,
988 [this](const std::string& convUid) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400989 ui->messageView->clear();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400990 // if currently selected,
991 // switch to welcome screen (deselecting current smartlist item )
992 if (convUid != selectedConvUid()) {
993 return;
994 }
995 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400996 }
997 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400998 interactionStatusUpdatedConnection_ = QObject::connect(
999 currentConversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
Andreas Traczyk43c08232018-10-31 13:42:09 -04001000 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001001 if (convUid != selectedConvUid()) {
1002 return;
1003 }
Andreas Traczyk43c08232018-10-31 13:42:09 -04001004 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
1005 auto currentConversationModel = currentAccountInfo.conversationModel.get();
1006 currentConversationModel->clearUnreadInteractions(convUid);
1007 ui->conversationsFilterWidget->update();
1008 ui->messageView->updateInteraction(*currentConversationModel, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -04001009 }
1010 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001011 newInteractionConnection_ = QObject::connect(
1012 currentConversationModel, &lrc::api::ConversationModel::newInteraction,
1013 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
1014 onIncomingMessage(convUid, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -04001015 }
1016 );
Andreas Traczyk43c08232018-10-31 13:42:09 -04001017 interactionRemovedConnection_ = QObject::connect(
1018 currentConversationModel, &lrc::api::ConversationModel::interactionRemoved,
1019 [this](const std::string& convUid, uint64_t interactionId) {
1020 Q_UNUSED(convUid);
1021 ui->messageView->removeInteraction(interactionId);
1022 }
1023 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001024 currentConversationModel->setFilter("");
1025 // clear search field
1026 ui->ringContactLineEdit->setText("");
1027 return true;
1028}
1029
1030void
1031CallWidget::updateConversationView(const std::string& convUid)
1032{
1033 if (convUid != selectedConvUid()) {
1034 return;
1035 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001036}
1037
1038void
1039CallWidget::selectConversation(const QModelIndex& index)
1040{
1041 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1042
1043 if (currentConversationModel == nullptr || !index.isValid()) {
1044 return;
1045 }
1046
1047 const auto item = currentConversationModel->filteredConversation(index.row());
1048
1049 if (selectConversation(item, *currentConversationModel)) {
Andreas Traczyk43c08232018-10-31 13:42:09 -04001050 showIMOutOfCall(index);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001051 auto convUid = selectedConvUid();
1052 if (!lastConvUid_.compare(convUid)) {
1053 return;
1054 }
1055 lastConvUid_.assign(convUid);
1056 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1057 auto callModel = LRCInstance::getCurrentCallModel();
1058 auto conversation = Utils::getConversationFromUid(convUid, *currentConversationModel);
1059 const auto item = currentConversationModel->filteredConversation(index.row());
Andreas Traczyk43c08232018-10-31 13:42:09 -04001060 if (callModel->hasCall(conversation->callId) && item.callId == conversation->callId) {
1061 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
1062 ui->callStackWidget->show();
1063 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001064 }
Andreas Traczyk43c08232018-10-31 13:42:09 -04001065 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001066 }
Anthony Léonard5cc76412017-04-21 16:52:25 -04001067}
Anthony Léonardecfe7422017-05-04 14:14:37 -04001068
Anthony Léonard041ad392017-07-14 16:44:09 -04001069bool
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001070CallWidget::selectConversation( const lrc::api::conversation::Info& item,
1071 lrc::api::ConversationModel& convModel)
Anthony Léonard041ad392017-07-14 16:44:09 -04001072{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001073 if (selectedConvUid() == item.uid) {
1074 return false;
1075 } else if (item.participants.size() > 0) {
1076 convModel.selectConversation(item.uid);
1077 LRCInstance::setSelectedConvId(item.uid);
1078 convModel.clearUnreadInteractions(item.uid);
1079 ui->conversationsFilterWidget->update();
1080 return true;
Anthony Léonard041ad392017-07-14 16:44:09 -04001081 }
Anthony Léonard041ad392017-07-14 16:44:09 -04001082}
1083
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001084void
1085CallWidget::deselectConversation()
Anthony Léonardecfe7422017-05-04 14:14:37 -04001086{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001087 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1088
1089 if (currentConversationModel == nullptr) {
1090 return;
1091 }
1092
1093 currentConversationModel->selectConversation("");
1094 LRCInstance::setSelectedConvId("");
1095
1096 ui->smartList->selectionModel()->clear();
1097 disconnect(imConnection_);
Anthony Léonardecfe7422017-05-04 14:14:37 -04001098}
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001099
1100void
1101CallWidget::updateConversationForNewContact(const std::string& convUid)
1102{
1103 auto convModel = LRCInstance::getCurrentConversationModel();
1104 if (convModel == nullptr) {
1105 return;
1106 }
1107 ui->ringContactLineEdit->setText("");
1108 auto selectedUid = selectedConvUid();
1109 auto it = Utils::getConversationFromUid(convUid, *convModel);
1110 if (it != convModel->allFilteredConversations().end()) {
1111 try {
1112 auto contact = convModel->owner.contactModel->getContact(it->participants[0]);
1113 if (!contact.profileInfo.uri.empty() && contact.profileInfo.uri.compare(selectedUid) == 0) {
1114 LRCInstance::setSelectedConvId(convUid);
1115 convModel->selectConversation(convUid);
1116 }
1117 } catch (...) {
1118 return;
1119 }
1120 }
1121}
1122
1123void
1124CallWidget::updateSmartList()
1125{
1126 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
Andreas Traczykfc33a492018-12-14 13:53:13 -05001127 smartListModel_.reset(new SmartListModel(currentAccountInfo, this));
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001128 ui->smartList->setModel(smartListModel_.get());
1129 ui->smartList->setItemDelegate(new ConversationItemDelegate());
1130
1131 // smartlist selection
1132 QObject::disconnect(smartlistSelectionConnection_);
1133 smartlistSelectionConnection_ = connect(ui->smartList->selectionModel(),
1134 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
1135 this,
1136 SLOT(smartListSelectionChanged(QItemSelection, QItemSelection)));
1137}
1138
1139void
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001140CallWidget::updateComboBox()
1141{
1142 ui->currentAccountComboBox->updateComboBoxDisplay();
1143}
1144
1145void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001146CallWidget::update()
1147{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001148 updateSmartList();
1149 updateConversationsFilterWidget();
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001150 updateComboBox();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001151 connectConversationModel();
Isa Nanic601de1d2018-10-23 11:37:26 -04001152}