blob: 98b64f023b3034788de6c4929496df5bf7f1c046 [file] [log] [blame]
Edric Milaret627500d2015-03-27 16:41:40 -04001/***************************************************************************
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04002 * Copyright (C) 2015-2018 by Savoir-faire Linux *
Edric Milaret627500d2015-03-27 16:41:40 -04003 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -04004 * Author: Anthony Léonard <anthony.leonard@savoirfairelinux.com> *
5 * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04006 * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> *
Isa Nanic37ccc1c2018-10-26 14:16:28 -04007 * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> *
Edric Milaret627500d2015-03-27 16:41:40 -04008 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 3 of the License, or *
12 * (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
21 **************************************************************************/
22
23#include "callwidget.h"
24#include "ui_callwidget.h"
25
Andreas Traczyk912242e2018-10-29 14:44:44 -040026#include <QScrollBar>
Edric Milaret43f3c1e2015-07-16 17:52:47 -040027#include <QClipboard>
Edric Milaret70ae8782016-04-18 16:10:44 -040028#include <QDesktopServices>
Isa Nanic601de1d2018-10-23 11:37:26 -040029#include <QComboBox>
Andreas Traczyk43c08232018-10-31 13:42:09 -040030#include <QWebEngineScript>
Edric Milaret43f3c1e2015-07-16 17:52:47 -040031
Edric Milaret53f57b62015-05-11 11:02:17 -040032#include <memory>
Edric Milaret627500d2015-03-27 16:41:40 -040033
Edric Milarete19c4cd2016-02-12 10:19:44 -050034#include "qrencode.h"
35
Edric Milaret43f3c1e2015-07-16 17:52:47 -040036//ERROR is defined in windows.h
37#include "utils.h"
38#undef ERROR
Edric Milareta0ebd062016-01-13 12:18:23 -050039#undef interface
Edric Milaret43f3c1e2015-07-16 17:52:47 -040040
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040041// lrc
Edric Milareta0ebd062016-01-13 12:18:23 -050042#include "globalinstances.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040043#include "profilemodel.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040044#include "localprofilecollection.h"
Anthony Léonardd47179c2017-03-28 10:39:10 -040045
Andreas Traczykb8b13ba2018-08-21 16:30:16 -040046// client
Edric Milaret559bda52015-04-29 17:02:31 -040047#include "wizarddialog.h"
Edric Milaret83b248c2015-06-02 11:42:23 -040048#include "windowscontactbackend.h"
Edric Milaret43f3c1e2015-07-16 17:52:47 -040049#include "contactpicker.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
Edric Milareted0b2802015-10-01 15:10:02 -040069 QPixmap logo(":/images/logo-ring-standard-coul.png");
70 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
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400189
Andreas Traczyk55f92cb2018-10-23 12:26:25 -0400190 // set first view to welcome view
191 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400192 ui->btnConversations->setChecked(true);
193
194 // chat view
195 ui->messageView->buildView();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500196
197 emit setLeftSizeWidget(ui->currentAccountComboBox->width());
Edric Milaret627500d2015-03-27 16:41:40 -0400198}
199
200CallWidget::~CallWidget()
201{
202 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400203 delete menu_;
Edric Milaret00a32252016-01-19 10:37:13 -0500204}
205
206void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400207CallWidget::onIncomingMessage(const std::string& convUid,
208 uint64_t interactionId,
209 const lrc::api::interaction::Info& interaction)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400210{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400211 Q_UNUSED(interactionId);
Edric Milaret00a32252016-01-19 10:37:13 -0500212 if (!QApplication::focusWidget()) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400213 auto convModel = LRCInstance::getCurrentConversationModel();
214 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
215 auto bestName = Utils::bestNameForConversation(*conversation, *convModel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400216 Utils::showSystemNotification(this,
217 QString(tr("Message incoming from %1"))
Andreas Traczyk43c08232018-10-31 13:42:09 -0400218 .arg(QString::fromStdString(bestName)));
Edric Milaret00a32252016-01-19 10:37:13 -0500219 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400220 if (convUid != selectedConvUid()) {
221 return;
222 }
223
224 auto convModel = LRCInstance::getCurrentConversationModel();
225 convModel->clearUnreadInteractions(convUid);
226 auto currentConversation = Utils::getConversationFromUid(convUid, *convModel);
227 if (currentConversation == convModel->allFilteredConversations().end()) {
228 return;
229 }
230 ui->messageView->printNewInteraction(*convModel, interactionId, interaction);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400231 ui->conversationsFilterWidget->update();
Edric Milareta0ebd062016-01-13 12:18:23 -0500232}
233
234void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400235CallWidget::setupSmartListContextMenu(const QPoint& pos)
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400236{
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400237 QPoint globalPos = ui->smartList->mapToGlobal(pos);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400238 auto index = ui->smartList->indexAt(pos);
239 if (not index.isValid()) {
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400240 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400241 }
242
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400243 auto convModel = LRCInstance::getCurrentConversationModel();
244 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID))
245 .value<QString>()
246 .toStdString();
247 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
248 auto contactUid = (*conversation).participants.at(0);
249 auto contact = LRCInstance::getCurrentAccountInfo().contactModel.get()->getContact(contactUid);
250
251 if (!Utils::isContactValid(contactUid, *convModel)) {
252 return;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400253 }
254
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400255 QMenu menu;
256
257 // video call
258 auto videoCallAction = new QAction(tr("Start video call"), this);
259 menu.addAction(videoCallAction);
260 connect(videoCallAction, &QAction::triggered,
261 [this, convUid, conversation, convModel]() {
262 convModel->placeCall(convUid);
263 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
264 if (convUid != selectedConvUid()) {
265 selectConversation(*conversation, *convModel);
266 }
267 });
268 // audio call
269 auto audioCallAction = new QAction(tr("Start audio call"), this);
270 menu.addAction(audioCallAction);
271 connect(audioCallAction, &QAction::triggered,
272 [this, convUid, conversation, convModel]() {
273 convModel->placeAudioOnlyCall(convUid);
274 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
275 if (convUid != selectedConvUid()) {
276 selectConversation(*conversation, *convModel);
277 }
278 });
279
280 if (contact.profileInfo.type == lrc::api::profile::Type::RING) {
281 // separator
282 menu.addSeparator();
283
284 // clear conversation
285 auto clearConversationAction = new QAction(tr("Clear conversation"), this);
286 menu.addAction(clearConversationAction);
287 connect(clearConversationAction, &QAction::triggered,
288 [convUid]() {
289 LRCInstance::getCurrentConversationModel()->clearHistory(convUid);
290 });
291 // block contact
292 auto blockContactAction = new QAction(tr("Block contact"), this);
293 menu.addAction(blockContactAction);
294 connect(blockContactAction, &QAction::triggered,
295 [convUid]() {
296 LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true);
297 });
298
299 // separator
300 menu.addSeparator();
301
302 // copy number(infohash)
303 auto copyNumberAction = new QAction(tr("Copy number"), this);
304 menu.addAction(copyNumberAction);
305 connect(copyNumberAction, &QAction::triggered,
306 [contact]() {
307 QApplication::clipboard()->setText(
308 QString::fromStdString(contact.profileInfo.uri)
309 );
310 });
311 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400312 smartListModel_->isContextMenuOpen = true;
Olivier SOLDANOcc28a0d2017-07-21 13:53:31 -0400313 menu.exec(globalPos);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400314 smartListModel_->isContextMenuOpen = false;
Edric Milareta0ebd062016-01-13 12:18:23 -0500315}
316
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400317void
318CallWidget::setupQRCode(QString ringID)
Edric Milarete19c4cd2016-02-12 10:19:44 -0500319{
Anthony Léonarda86a8972016-12-15 10:33:47 -0500320 auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
Edric Milaret6d0e5312016-04-04 16:30:22 -0400321 0, //Let the version be decided by libqrencode
322 QR_ECLEVEL_L, // Lowest level of error correction
Edric Milarete19c4cd2016-02-12 10:19:44 -0500323 QR_MODE_8, // 8-bit data mode
324 1);
325 if (not rcode) {
326 qWarning() << "Failed to generate QR code: " << strerror(errno);
327 return;
328 }
329
330 auto margin = 5;
331 int qrwidth = rcode->width + margin * 2;
332 QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono);
333 QPainter painter;
334 painter.begin(&result);
335 painter.setClipRect(QRect(0, 0, qrwidth, qrwidth));
336 painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
337 painter.setBrush(Qt::black);
338 painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
Edric Milaret74474f52016-05-16 13:36:23 -0400339 unsigned char* p;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500340 p = rcode->data;
341 for(int y = 0; y < rcode->width; y++) {
Edric Milaret74474f52016-05-16 13:36:23 -0400342 unsigned char* row = (p + (y * rcode->width));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500343 for(int x = 0; x < rcode->width; x++) {
344 if(*(row + x) & 0x1) {
345 painter.drawRect(margin + x, margin + y, 1, 1);
346 }
347 }
348
349 }
350 painter.end();
351 QRcode_free(rcode);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400352 ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_),
353 Qt::KeepAspectRatio)));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500354}
355
Edric Milaret627500d2015-03-27 16:41:40 -0400356void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400357CallWidget::on_smartList_clicked(const QModelIndex& index)
Edric Milaret00d34f22016-05-09 16:30:29 -0400358{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400359 Q_UNUSED(index);
Edric Milaret627500d2015-03-27 16:41:40 -0400360}
361
362void
363CallWidget::on_acceptButton_clicked()
364{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400365 auto convModel = LRCInstance::getCurrentConversationModel();
366 auto callModel = LRCInstance::getCurrentCallModel();
367 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
368 callModel->accept(conversation->callId);
Edric Milaret627500d2015-03-27 16:41:40 -0400369}
370
371void
372CallWidget::on_refuseButton_clicked()
373{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400374 auto convModel = LRCInstance::getCurrentConversationModel();
375 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
376 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
377 showConversationView();
Edric Milaret6456baa2015-05-21 12:18:07 -0400378}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400379
380void
Edric Milareted0b2802015-10-01 15:10:02 -0400381CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400382{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400383 auto convModel = LRCInstance::getCurrentConversationModel();
384 auto conversation = Utils::getConversationFromUid(selectedConvUid(), *convModel);
385 LRCInstance::getCurrentCallModel()->hangUp(conversation->callId);
386 showConversationView();
Edric Milaretd8528fa2015-07-07 14:13:51 -0400387}
Edric Milareted0b2802015-10-01 15:10:02 -0400388
389void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400390CallWidget::showConversationView()
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400391{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400392 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
393 ui->messageView->setFocus();
394
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400395}
396
397void
398CallWidget::selectSmartlistItem(const std::string & convUid)
399{
400 if (convUid.empty()) {
401 return;
402 }
403 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
404 auto convModel = LRCInstance::getCurrentConversationModel();
405 auto conversation = Utils::getConversationFromUid(convUid, *convModel);
406 if (conversation == convModel->allFilteredConversations().end()) {
407 return;
408 }
409 auto contactURI = QString::fromStdString((*conversation).participants[0]);
410 if (contactURI.isEmpty() ||
411 convModel->owner.contactModel->getContact(contactURI.toStdString()).profileInfo.type == lrc::api::profile::Type::TEMPORARY) {
412 return;
413 }
414 for (int row = 0; row < smartListModel_->rowCount(); row++) {
415 QModelIndex index = smartListModel_->index(row);
416 auto indexContactURI = index.data(SmartListModel::Role::URI).value<QString>();
417 if (indexContactURI == contactURI) {
418 ui->smartList->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
419 return;
420 }
421 }
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400422}
423
424void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500425CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400426{
Olivier SOLDANO70279d32017-07-18 15:21:34 -0400427 if (!index.isValid())
428 return;
429
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400430 LRCInstance::getCurrentConversationModel()->placeCall(selectedConvUid());
Edric Milareted0b2802015-10-01 15:10:02 -0400431
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400432 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(selectedConvUid())));
433}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500434
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400435QImage
436CallWidget::imageForConv(const std::string& convUid)
437{
438 return Utils::conversationPhoto(convUid, LRCInstance::getCurrentAccountInfo());
439}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500440
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400441const std::string&
442CallWidget::selectedAccountId()
443{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500444 return LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400445}
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500446
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400447const std::string&
448CallWidget::selectedConvUid()
449{
450 return LRCInstance::getSelectedConvUid();
Edric Milareted0b2802015-10-01 15:10:02 -0400451}
452
453void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400454CallWidget::smartListSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500455{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400456 Q_UNUSED(deselected);
457 QModelIndexList indices = selected.indexes();
458
459 if (indices.isEmpty()) {
Edric Milareted0b2802015-10-01 15:10:02 -0400460 return;
Anthony Léonardecfe7422017-05-04 14:14:37 -0400461 }
Edric Milareted0b2802015-10-01 15:10:02 -0400462
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400463 auto selectedIndex = indices.at(0);
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500464
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400465 if (not selectedIndex.isValid()) {
466 return;
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400467 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400468
469 selectConversation(selectedIndex);
Edric Milareted0b2802015-10-01 15:10:02 -0400470}
471
472void
473CallWidget::placeCall()
474{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500475 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400476 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500477 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400478 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500479 ui->ringContactLineEdit->clear();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400480 auto photoRect = ui->callingPhoto->frameGeometry();
Edric1bed3f92016-05-19 10:24:48 -0400481 ui->callingPhoto->setPixmap(
482 QPixmap::fromImage(
483 GlobalInstances::pixmapManipulator()
Andreas Traczyk43c08232018-10-31 13:42:09 -0400484 .callPhoto(c, QSize(photoRect.width(), photoRect.height()))
485 .value<QImage>()));
Edric Milareted0b2802015-10-01 15:10:02 -0400486}
487
488void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400489CallWidget::conversationsButtonClicked()
490{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400491 ui->btnConversations->setChecked(true);
492 ui->btnInvites->setChecked(false);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400493 setConversationFilter(lrc::api::profile::Type::RING);
494}
495
496void
497CallWidget::invitationsButtonClicked()
498{
Andreas Traczyk43c08232018-10-31 13:42:09 -0400499 ui->btnConversations->setChecked(false);
500 ui->btnInvites->setChecked(true);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400501 setConversationFilter(lrc::api::profile::Type::PENDING);
502}
503
504void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500505CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400506{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500507 emit setLeftSizeWidget(ui->currentAccountComboBox->width());
Edric Milareted0b2802015-10-01 15:10:02 -0400508 emit NavigationRequested(ScreenEnum::ConfScreen);
509}
510
511void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400512CallWidget::processContactLineEdit()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500513{
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400514 auto contactLineText = ui->ringContactLineEdit->text();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400515 setConversationFilter(contactLineText);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500516}
517
518void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400519CallWidget::on_ringContactLineEdit_returnPressed()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500520{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400521 // select current temporary item and show conversation
522 auto convModel = LRCInstance::getCurrentConversationModel();
523 auto conversations = convModel->allFilteredConversations();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400524 if (!conversations.empty() &&
525 Utils::isContactValid(conversations.at(0).participants.at(0), *convModel)) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400526 selectConversation(smartListModel_->index(0));
527 }
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400528}
529
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400530void CallWidget::slotAcceptInviteClicked(const QModelIndex & index)
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400531{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400532 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
533 LRCInstance::getCurrentConversationModel()->makePermanent(convUid.toStdString());
Nicolas Jager97a21b42015-12-03 16:55:45 -0500534}
535
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400536void CallWidget::slotBlockInviteClicked(const QModelIndex & index)
Nicolas Jager97a21b42015-12-03 16:55:45 -0500537{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400538 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
539 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString(), true);
540}
541
542void CallWidget::slotIgnoreInviteClicked(const QModelIndex & index)
543{
544 auto convUid = index.data(static_cast<int>(SmartListModel::Role::UID)).value<QString>();
545 LRCInstance::getCurrentConversationModel()->removeConversation(convUid.toStdString());
546}
547
548void CallWidget::slotCustomContextMenuRequested(const QPoint& pos)
549{
550 setupSmartListContextMenu(pos);
551}
552
Isa Nanic601de1d2018-10-23 11:37:26 -0400553void CallWidget::slotAccountChanged(int index)
554{
555 auto accountList = LRCInstance::accountModel().getAccountList();
556 setSelectedAccount(accountList.at(index));
557}
558
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400559void CallWidget::slotShowCallView(const std::string& accountId,
560 const lrc::api::conversation::Info& convInfo)
561{
562 Q_UNUSED(accountId);
563 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400564 qDebug() << "slotShowCallView";
565 ui->callStackWidget->show();
566 ui->callStackWidget->setCurrentWidget(ui->videoPage);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400567 hideMiniSpinner();
568}
569
570void CallWidget::slotShowIncomingCallView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400571 const lrc::api::conversation::Info& convInfo)
572{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400573 Q_UNUSED(accountId);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400574 qDebug() << "slotShowIncomingCallView";
575
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400576 auto callModel = LRCInstance::getCurrentCallModel();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400577
578 if (!callModel->hasCall(convInfo.callId)) {
Nicolas Jager97a21b42015-12-03 16:55:45 -0500579 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400580 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500581
Andreas Traczyk43c08232018-10-31 13:42:09 -0400582 auto convModel = LRCInstance::getCurrentConversationModel();
583 ui->callerPhoto->setPixmap(QPixmap::fromImage(imageForConv(convInfo.uid)));
584 auto bestName = QString::fromStdString(Utils::bestNameForConversation(convInfo, *convModel));
585 auto bestId = QString::fromStdString(Utils::bestIdForConversation(convInfo, *convModel));
586 auto finalBestId = (bestName != bestId) ? bestId : "";
587
588 auto call = callModel->getCall(convInfo.callId);
589 auto isCallSelected = selectedConvUid() == convInfo.uid;
590
591 if (call.isOutgoing) {
592 if (isCallSelected) {
593 miniSpinner_->start();
594 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
595 ui->spinnerLabel->show();
596 ui->callStackWidget->setCurrentWidget(ui->outgoingCallPage);
597 ui->callStackWidget->show();
598 }
599 } else {
600 if (!QApplication::focusWidget()) {
601 auto formattedName = Utils::bestNameForConversation(convInfo, *convModel);
602 Utils::showSystemNotification(this,
603 QString(tr("Call incoming from %1")).arg(QString::fromStdString(formattedName)));
604 }
605 selectSmartlistItem(convInfo.uid);
606 auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id;
607 auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId);
608 if (accountProperties.autoAnswer) {
609 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
610 ui->callStackWidget->setCurrentWidget(ui->videoPage);
611 } else if (isCallSelected) {
612 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
613 ui->callStackWidget->setCurrentWidget(ui->incomingCallPage);
614 ui->callStackWidget->show();
615 }
616 }
617
618 // flashing index widget during call
619 for (int row = 0; row < smartListModel_->rowCount(); row++) {
620 QModelIndex index = smartListModel_->index(row);
621 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
622 if (indexUid == convInfo.uid) {
623 auto widget = ui->smartList->indexWidget(index);
624 if (!widget) {
625 auto blinkingWidget = new AnimatedOverlay(RingTheme::urgentOrange_);
626 ui->smartList->setIndexWidget(index, blinkingWidget);
627 blinkingWidget->show();
628 } else {
629 widget->show();
630 }
631 }
632 }
633
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400634 ui->videoWidget->pushRenderer(convInfo.callId);
Andreas Traczykfd0d7c02018-10-30 17:14:06 -0400635
Andreas Traczyk43c08232018-10-31 13:42:09 -0400636 QFontMetrics primaryCallLabelFontMetrics(ui->callingBestNameLabel->font());
637 QFontMetrics sencondaryCallLabelFontMetrics(ui->callingBestIdLabel->font());
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400638
Andreas Traczyk43c08232018-10-31 13:42:09 -0400639 QString elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callerBestNameLabel->width());
640 ui->callerBestNameLabel->setText(elidedLabel);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400641
Andreas Traczyk43c08232018-10-31 13:42:09 -0400642 elidedLabel = primaryCallLabelFontMetrics.elidedText(bestName, Qt::ElideRight, ui->callingBestNameLabel->width());
643 ui->callingBestNameLabel->setText(elidedLabel);
644
645 elidedLabel = sencondaryCallLabelFontMetrics.elidedText(finalBestId, Qt::ElideRight, ui->callingBestIdLabel->width());
646 ui->callingBestIdLabel->setText(elidedLabel);
647
648 ui->smartList->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400649}
650
651void CallWidget::slotShowChatView(const std::string& accountId,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400652 const lrc::api::conversation::Info& convInfo)
653{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400654 Q_UNUSED(accountId);
655 Q_UNUSED(convInfo);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400656
657 for (int row = 0; row < smartListModel_->rowCount(); row++) {
658 QModelIndex index = smartListModel_->index(row);
659 auto indexUid = index.data(SmartListModel::Role::UID).value<QString>().toStdString();
660 if (indexUid == convInfo.uid) {
661 if (auto widget = ui->smartList->indexWidget(index)) {
662 widget->hide();
663 widget->deleteLater();
664 ui->smartList->setIndexWidget(index, nullptr);
665 }
666 }
667 }
668
669 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400670 showConversationView();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500671}
Edric Milaretab12d022015-12-04 16:09:44 -0500672
673void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400674CallWidget::setSelectedAccount(const std::string& accountId)
675{
676 LRCInstance::setSelectedAccountId(accountId);
677
678 // First, we get back to the welcome view (except if in call)
679 if (ui->stackedWidget->currentWidget() != ui->videoPage &&
680 ui->stackedWidget->currentWidget() != ui->welcomePage) {
681 Utils::setStackWidget(ui->stackedWidget, ui->welcomePage);
682 }
683
684 // We setup the ringIdLabel and the QRCode
685 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(accountId);
686 auto id = accountInfo.registeredName.empty() ? accountInfo.profileInfo.uri : accountInfo.registeredName;
687 auto isRingAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
688 if (isRingAccount) {
689 ui->ringIdLabel->setText(QString::fromStdString(id));
690 setupQRCode(QString::fromStdString(accountInfo.profileInfo.uri));
691 }
692
693 updateSmartList();
694 currentTypeFilter_ = accountInfo.profileInfo.type;
695 LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type);
696 updateConversationsFilterWidget();
697 connectConversationModel();
698}
699
700void CallWidget::setConversationFilter(lrc::api::profile::Type filter)
701{
702 if (currentTypeFilter_ == filter) {
703 return;
704 }
705 currentTypeFilter_ = filter;
706 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
707}
708
709void CallWidget::updateConversationsFilterWidget()
710{
711 auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount();
712 if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) {
713 currentTypeFilter_ = lrc::api::profile::Type::RING;
714 LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_);
715 }
716 ui->conversationsFilterWidget->setVisible(invites);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400717 ui->conversationsFilterWidget->update();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400718}
719
720void CallWidget::setConversationFilter(const QString & filter)
721{
722 LRCInstance::getCurrentConversationModel()->setFilter(filter.toStdString());
Anthony Léonardd47179c2017-03-28 10:39:10 -0400723}
724
725void
Edric Milaret6b68a482016-02-01 15:23:44 -0500726CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500727{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400728 QString displayName = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayName)).toString();
729 QString displayId = nodeIdx.data(static_cast<int>(SmartListModel::Role::DisplayID)).toString();
730 QString contactURI = nodeIdx.data(static_cast<int>(SmartListModel::Role::URI)).toString();
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400731
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400732 bool isContact = false;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500733 auto selectedAccountId = LRCInstance::getCurrAccId();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400734 auto& accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId);
735 bool isRINGAccount = accountInfo.profileInfo.type == lrc::api::profile::Type::RING;
736 try {
737 accountInfo.contactModel->getContact(contactURI.toStdString());
738 isContact = true;
739 }
740 catch (...) {}
741
Olivier SOLDANO31b9aac2017-07-14 15:50:09 -0400742 ui->imNameLabel->setText(QString(tr("%1", "%1 is the contact username"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400743 .arg(displayName));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400744
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400745 if (isRINGAccount && displayName != displayId){
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400746 ui->imIdLabel->show();
747 ui->imIdLabel->setText(QString(tr("%1", "%1 is the contact unique identifier"))
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400748 .arg(displayId));
Olivier SOLDANO483f9682017-07-26 11:57:49 -0400749 } else {
750 ui->imIdLabel->hide();
751 }
752
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400753 bool shouldShowSendContactRequestBtn = !isContact && isRINGAccount;
Andreas Traczyk912242e2018-10-29 14:44:44 -0400754 ui->sendContactRequestButton->setVisible(shouldShowSendContactRequestBtn);
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400755
Andreas Traczyk43c08232018-10-31 13:42:09 -0400756 auto convModel = LRCInstance::getCurrentConversationModel();
757 auto currentConversation = Utils::getConversationFromUid(selectedConvUid(),
758 *convModel);
759 ui->messageView->clear();
760 ui->messageView->printHistory(*convModel, currentConversation->interactions);
761
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400762 showConversationView();
Anthony Léonard041ad392017-07-14 16:44:09 -0400763
Andreas Traczyk43c08232018-10-31 13:42:09 -0400764 // Contact Avatars
765 auto accInfo = &LRCInstance::getCurrentAccountInfo();
766 auto contactUri = currentConversation->participants.front();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400767 try {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400768 auto& contact = accInfo->contactModel->getContact(contactUri);
769 if (!contact.profileInfo.avatar.empty()) {
770 ui->messageView->setSenderImage(
771 accInfo->contactModel->getContactProfileId(contactUri),
772 contact.profileInfo.avatar);
773 } else {
774 auto avatar = Utils::conversationPhoto(selectedConvUid(), *accInfo);
775 QByteArray ba;
776 QBuffer bu(&ba);
777 avatar.save(&bu, "PNG");
778 std::string avatarString = ba.toBase64().toStdString();
779 ui->messageView->setSenderImage(
780 accInfo->contactModel->getContactProfileId(contactUri),
781 avatarString);
782 }
783 } catch (...) { }
Edric Milaretab12d022015-12-04 16:09:44 -0500784}
Edric Milaretfa05d972016-01-13 16:22:04 -0500785
786void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500787CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500788{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400789 Q_UNUSED(text);
790 processContactLineEdit();
Edric Milaretfa05d972016-01-13 16:22:04 -0500791}
Edric Milareta0ebd062016-01-13 12:18:23 -0500792
Nicolas Jagerca850292016-01-17 14:11:10 -0500793void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400794CallWidget::backToWelcomePage()
Edric Milareta0ebd062016-01-13 12:18:23 -0500795{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400796 deselectConversation();
Andreas Traczyk43c08232018-10-31 13:42:09 -0400797 ui->messageView->hideMessages();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400798 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Nicolas Jagerca850292016-01-17 14:11:10 -0500799}
800
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400801void
802CallWidget::hideMiniSpinner()
Olivier SOLDANO19193412017-06-06 12:03:36 -0400803{
804 if(ui->spinnerLabel->isVisible()){
805 miniSpinner_->stop();
806 ui->spinnerLabel->hide();
807 }
808}
809
Nicolas Jagerca850292016-01-17 14:11:10 -0500810void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400811CallWidget::on_imBackButton_clicked()
812{
813 backToWelcomePage();
814}
815
816void
Edric Milaret1e598592016-09-02 10:10:01 -0400817CallWidget::on_qrButton_toggled(bool checked)
818{
819 ui->qrLabel->setVisible(checked);
820}
821
822void
Edric Milaret4097d2f2016-02-09 14:41:50 -0500823CallWidget::on_shareButton_clicked()
824{
Edric Milaret1e598592016-09-02 10:10:01 -0400825 Utils::InvokeMailto(tr("Contact me on Ring"), tr("My RingId is : ") + ui->ringIdLabel->text());
Edric Milaret4097d2f2016-02-09 14:41:50 -0500826}
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400827
828void
Andreas Traczyk912242e2018-10-29 14:44:44 -0400829CallWidget::on_sendContactRequestButton_clicked()
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400830{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400831 LRCInstance::getCurrentConversationModel()->makePermanent(selectedConvUid());
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400832}
833
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400834void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400835CallWidget::on_pendingCRBackButton_clicked()
836{
Olivier SOLDANO8179e992017-07-19 15:59:19 -0400837 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400838}
Anthony Léonard5cc76412017-04-21 16:52:25 -0400839
Andreas Traczyk912242e2018-10-29 14:44:44 -0400840void
841CallWidget::on_btnAudioCall_clicked()
842{
843 auto convUid = LRCInstance::getSelectedConvUid();
844 LRCInstance::getCurrentConversationModel()->placeAudioOnlyCall(convUid);
845 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
846}
847
848void
849CallWidget::on_btnVideoCall_clicked()
850{
851 auto convUid = LRCInstance::getSelectedConvUid();
852 LRCInstance::getCurrentConversationModel()->placeCall(convUid);
853 ui->callingPhoto->setPixmap(QPixmap::fromImage(imageForConv(convUid)));
854}
855
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400856bool
857CallWidget::connectConversationModel()
Anthony Léonard5cc76412017-04-21 16:52:25 -0400858{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400859 auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get();
860
861 if (ui->smartList->selectionModel()) {
862 ui->smartList->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Deselect);
Anthony Léonard5cc76412017-04-21 16:52:25 -0400863 }
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400864
865 QObject::disconnect(modelSortedConnection_);
866 QObject::disconnect(modelUpdatedConnection_);
867 QObject::disconnect(filterChangedConnection_);
868 QObject::disconnect(newConversationConnection_);
869 QObject::disconnect(conversationRemovedConnection_);
870 QObject::disconnect(conversationClearedConnection);
871 QObject::disconnect(interactionStatusUpdatedConnection_);
872 QObject::disconnect(newInteractionConnection_);
Andreas Traczyk43c08232018-10-31 13:42:09 -0400873 QObject::disconnect(interactionRemovedConnection_);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400874
875 modelSortedConnection_ = QObject::connect(
876 currentConversationModel, &lrc::api::ConversationModel::modelSorted,
877 [this]() {
878 updateConversationsFilterWidget();
879 selectSmartlistItem(selectedConvUid());
880 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400881 }
882 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400883 modelUpdatedConnection_ = QObject::connect(
884 currentConversationModel, &lrc::api::ConversationModel::conversationUpdated,
885 [this](const std::string& convUid) {
886 Q_UNUSED(convUid);
887 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400888 }
889 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400890 filterChangedConnection_ = QObject::connect(
891 currentConversationModel, &lrc::api::ConversationModel::filterChanged,
892 [this]() {
893 updateSmartList();
894 updateConversationsFilterWidget();
895 ui->smartList->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400896 }
897 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400898 newConversationConnection_ = QObject::connect(
899 currentConversationModel, &lrc::api::ConversationModel::newConversation,
900 [this](const std::string& convUid) {
901 updateSmartList();
902 updateConversationForNewContact(convUid);
903 ui->conversationsFilterWidget->update();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400904 }
905 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400906 conversationRemovedConnection_ = QObject::connect(
907 currentConversationModel, &lrc::api::ConversationModel::conversationRemoved,
908 [this]() {
909 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400910 }
911 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400912 conversationClearedConnection = QObject::connect(
913 currentConversationModel, &lrc::api::ConversationModel::conversationCleared,
914 [this](const std::string& convUid) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400915 ui->messageView->clear();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400916 // if currently selected,
917 // switch to welcome screen (deselecting current smartlist item )
918 if (convUid != selectedConvUid()) {
919 return;
920 }
921 backToWelcomePage();
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400922 }
923 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400924 interactionStatusUpdatedConnection_ = QObject::connect(
925 currentConversationModel, &lrc::api::ConversationModel::interactionStatusUpdated,
Andreas Traczyk43c08232018-10-31 13:42:09 -0400926 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400927 if (convUid != selectedConvUid()) {
928 return;
929 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400930 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
931 auto currentConversationModel = currentAccountInfo.conversationModel.get();
932 currentConversationModel->clearUnreadInteractions(convUid);
933 ui->conversationsFilterWidget->update();
934 ui->messageView->updateInteraction(*currentConversationModel, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400935 }
936 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400937 newInteractionConnection_ = QObject::connect(
938 currentConversationModel, &lrc::api::ConversationModel::newInteraction,
939 [this](const std::string& convUid, uint64_t interactionId, const lrc::api::interaction::Info& interaction) {
940 onIncomingMessage(convUid, interactionId, interaction);
Isa Nanic37ccc1c2018-10-26 14:16:28 -0400941 }
942 );
Andreas Traczyk43c08232018-10-31 13:42:09 -0400943 interactionRemovedConnection_ = QObject::connect(
944 currentConversationModel, &lrc::api::ConversationModel::interactionRemoved,
945 [this](const std::string& convUid, uint64_t interactionId) {
946 Q_UNUSED(convUid);
947 ui->messageView->removeInteraction(interactionId);
948 }
949 );
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400950 currentConversationModel->setFilter("");
951 // clear search field
952 ui->ringContactLineEdit->setText("");
953 return true;
954}
955
956void
957CallWidget::updateConversationView(const std::string& convUid)
958{
959 if (convUid != selectedConvUid()) {
960 return;
961 }
962
Andreas Traczyk43c08232018-10-31 13:42:09 -0400963
964
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400965}
966
967void
968CallWidget::selectConversation(const QModelIndex& index)
969{
970 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
971
972 if (currentConversationModel == nullptr || !index.isValid()) {
973 return;
974 }
975
976 const auto item = currentConversationModel->filteredConversation(index.row());
977
978 if (selectConversation(item, *currentConversationModel)) {
Andreas Traczyk43c08232018-10-31 13:42:09 -0400979 showIMOutOfCall(index);
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400980 auto convUid = selectedConvUid();
981 if (!lastConvUid_.compare(convUid)) {
982 return;
983 }
984 lastConvUid_.assign(convUid);
985 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
986 auto callModel = LRCInstance::getCurrentCallModel();
987 auto conversation = Utils::getConversationFromUid(convUid, *currentConversationModel);
988 const auto item = currentConversationModel->filteredConversation(index.row());
Andreas Traczyk43c08232018-10-31 13:42:09 -0400989 if (callModel->hasCall(conversation->callId) && item.callId == conversation->callId) {
990 ui->stackedWidget->setCurrentWidget(ui->mainActivityWidget);
991 ui->callStackWidget->show();
992 return;
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400993 }
Andreas Traczyk43c08232018-10-31 13:42:09 -0400994 ui->callStackWidget->hide();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400995 }
Anthony Léonard5cc76412017-04-21 16:52:25 -0400996}
Anthony Léonardecfe7422017-05-04 14:14:37 -0400997
Anthony Léonard041ad392017-07-14 16:44:09 -0400998bool
Andreas Traczykb8b13ba2018-08-21 16:30:16 -0400999CallWidget::selectConversation( const lrc::api::conversation::Info& item,
1000 lrc::api::ConversationModel& convModel)
Anthony Léonard041ad392017-07-14 16:44:09 -04001001{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001002 if (selectedConvUid() == item.uid) {
1003 return false;
1004 } else if (item.participants.size() > 0) {
1005 convModel.selectConversation(item.uid);
1006 LRCInstance::setSelectedConvId(item.uid);
1007 convModel.clearUnreadInteractions(item.uid);
1008 ui->conversationsFilterWidget->update();
1009 return true;
Anthony Léonard041ad392017-07-14 16:44:09 -04001010 }
Anthony Léonard041ad392017-07-14 16:44:09 -04001011}
1012
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001013void
1014CallWidget::deselectConversation()
Anthony Léonardecfe7422017-05-04 14:14:37 -04001015{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001016 auto currentConversationModel = LRCInstance::getCurrentConversationModel();
1017
1018 if (currentConversationModel == nullptr) {
1019 return;
1020 }
1021
1022 currentConversationModel->selectConversation("");
1023 LRCInstance::setSelectedConvId("");
1024
1025 ui->smartList->selectionModel()->clear();
1026 disconnect(imConnection_);
Anthony Léonardecfe7422017-05-04 14:14:37 -04001027}
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001028
1029void
1030CallWidget::updateConversationForNewContact(const std::string& convUid)
1031{
1032 auto convModel = LRCInstance::getCurrentConversationModel();
1033 if (convModel == nullptr) {
1034 return;
1035 }
1036 ui->ringContactLineEdit->setText("");
1037 auto selectedUid = selectedConvUid();
1038 auto it = Utils::getConversationFromUid(convUid, *convModel);
1039 if (it != convModel->allFilteredConversations().end()) {
1040 try {
1041 auto contact = convModel->owner.contactModel->getContact(it->participants[0]);
1042 if (!contact.profileInfo.uri.empty() && contact.profileInfo.uri.compare(selectedUid) == 0) {
1043 LRCInstance::setSelectedConvId(convUid);
1044 convModel->selectConversation(convUid);
1045 }
1046 } catch (...) {
1047 return;
1048 }
1049 }
1050}
1051
1052void
1053CallWidget::updateSmartList()
1054{
1055 auto& currentAccountInfo = LRCInstance::getCurrentAccountInfo();
1056 smartListModel_.reset(new SmartListModel(currentAccountInfo, this->parent()));
1057 ui->smartList->setModel(smartListModel_.get());
1058 ui->smartList->setItemDelegate(new ConversationItemDelegate());
1059
1060 // smartlist selection
1061 QObject::disconnect(smartlistSelectionConnection_);
1062 smartlistSelectionConnection_ = connect(ui->smartList->selectionModel(),
1063 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
1064 this,
1065 SLOT(smartListSelectionChanged(QItemSelection, QItemSelection)));
1066}
1067
1068void
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001069CallWidget::updateComboBox()
1070{
1071 ui->currentAccountComboBox->updateComboBoxDisplay();
1072}
1073
1074void
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001075CallWidget::update()
1076{
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001077 updateSmartList();
1078 updateConversationsFilterWidget();
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001079 updateComboBox();
Andreas Traczykb8b13ba2018-08-21 16:30:16 -04001080 connectConversationModel();
Isa Nanic601de1d2018-10-23 11:37:26 -04001081}