blob: 004379866427227bb249278d169ecc4a1c69a386 [file] [log] [blame]
Edric Milaret627500d2015-03-27 16:41:40 -04001/***************************************************************************
Anthony Léonard2fde81d2017-04-17 10:06:55 -04002 * Copyright (C) 2015-2017 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> *
Edric Milaret627500d2015-03-27 16:41:40 -04006 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 **************************************************************************/
20
21#include "callwidget.h"
22#include "ui_callwidget.h"
23
Edric Milaret43f3c1e2015-07-16 17:52:47 -040024#include <QClipboard>
Edric Milaret70ae8782016-04-18 16:10:44 -040025#include <QDesktopServices>
Edric Milaret43f3c1e2015-07-16 17:52:47 -040026
Edric Milaret53f57b62015-05-11 11:02:17 -040027#include <memory>
Edric Milaret627500d2015-03-27 16:41:40 -040028
Edric Milarete19c4cd2016-02-12 10:19:44 -050029#include "qrencode.h"
30
Edric Milaret43f3c1e2015-07-16 17:52:47 -040031//ERROR is defined in windows.h
32#include "utils.h"
33#undef ERROR
Edric Milareta0ebd062016-01-13 12:18:23 -050034#undef interface
Edric Milaret43f3c1e2015-07-16 17:52:47 -040035
Olivier SOLDANO69361192017-04-20 10:32:05 -040036//LRC
Edric Milaret627500d2015-03-27 16:41:40 -040037#include "audio/settings.h"
Olivier SOLDANO9657fd12017-03-27 16:06:53 -040038#include "accountmodel.h"
Edric Milaret627500d2015-03-27 16:41:40 -040039#include "personmodel.h"
Edric Milaret43f3c1e2015-07-16 17:52:47 -040040#include "person.h"
Edric Milaret627500d2015-03-27 16:41:40 -040041#include "fallbackpersoncollection.h"
Edric Milaret67007d12015-05-07 09:40:09 -040042#include "categorizedcontactmodel.h"
Edric Milaret6a642e22015-05-27 15:06:30 -040043#include "localhistorycollection.h"
Edric Milaret1b197eb2015-06-01 15:09:56 -040044#include "media/text.h"
45#include "media/recording.h"
Edric Milaret00a32252016-01-19 10:37:13 -050046#include "media/recordingmodel.h"
Edric Milareted0b2802015-10-01 15:10:02 -040047#include "recentmodel.h"
Edric Milaretab12d022015-12-04 16:09:44 -050048#include "contactmethod.h"
Edric Milareta0ebd062016-01-13 12:18:23 -050049#include "globalinstances.h"
Olivier SOLDANO63178ee2016-11-04 16:50:08 -040050#include <availableaccountmodel.h>
Anthony Léonardd47179c2017-03-28 10:39:10 -040051#include "pendingcontactrequestmodel.h"
Olivier SOLDANO69361192017-04-20 10:32:05 -040052#include "profilemodel.h"
53#include "profile.h"
54#include "peerprofilecollection.h"
55#include "localprofilecollection.h"
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -040056#include "callmodel.h"
Anthony Léonardd47179c2017-03-28 10:39:10 -040057
Olivier SOLDANO69361192017-04-20 10:32:05 -040058//Client
Edric Milaret559bda52015-04-29 17:02:31 -040059#include "wizarddialog.h"
Edric Milaret83b248c2015-06-02 11:42:23 -040060#include "windowscontactbackend.h"
Edric Milaret43f3c1e2015-07-16 17:52:47 -040061#include "contactpicker.h"
Edric Milaret2afd2bf2015-07-21 17:12:25 -040062#include "contactmethodpicker.h"
Edric Milaret2cf34292015-06-22 16:27:03 -040063#include "globalsystemtray.h"
Edric Milareted0b2802015-10-01 15:10:02 -040064#include "smartlistdelegate.h"
Edric Milaretab12d022015-12-04 16:09:44 -050065#include "imdelegate.h"
Edric Milareta0ebd062016-01-13 12:18:23 -050066#include "pixbufmanipulator.h"
Edric Milaret70ae8782016-04-18 16:10:44 -040067#include "settingskey.h"
Anthony Léonardf95f7f62017-04-04 11:01:51 -040068#include "contactrequestitemdelegate.h"
Edric Milaret627500d2015-03-27 16:41:40 -040069
Edric Milaret25236d92016-03-28 09:40:58 -040070
Nicolas Jager97a21b42015-12-03 16:55:45 -050071CallWidget::CallWidget(QWidget* parent) :
Nicolas Jager74fe46f2016-02-29 14:55:09 -050072 NavWidget(parent),
Edric Milaret7d40a4a2015-05-13 13:01:15 -040073 ui(new Ui::CallWidget),
Edric Milaretab12d022015-12-04 16:09:44 -050074 menu_(new QMenu()),
75 imDelegate_(new ImDelegate())
Edric Milaret627500d2015-03-27 16:41:40 -040076{
77 ui->setupUi(this);
78
Edric Milaret6b68a482016-02-01 15:23:44 -050079 pageAnim_ = new QPropertyAnimation(ui->welcomePage, "pos", this);
Nicolas Jagerca850292016-01-17 14:11:10 -050080
Edric Milaret6456baa2015-05-21 12:18:07 -040081 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -040082 videoRenderer_ = nullptr;
83
Nicolas Jager74fe46f2016-02-29 14:55:09 -050084 connect(ui->settingsButton, &QPushButton::clicked, this, &CallWidget::settingsButtonClicked);
85
Edric Milaret3aca8e32015-06-12 10:01:40 -040086 connect(ui->videoWidget, SIGNAL(setChatVisibility(bool)),
87 ui->instantMessagingWidget, SLOT(setVisible(bool)));
88
Edric Milareted0b2802015-10-01 15:10:02 -040089 QPixmap logo(":/images/logo-ring-standard-coul.png");
90 ui->ringLogo->setPixmap(logo.scaledToHeight(100, Qt::SmoothTransformation));
91 ui->ringLogo->setAlignment(Qt::AlignHCenter);
92
Edric Milaret1e598592016-09-02 10:10:01 -040093 ui->qrLabel->hide();
Edric Milarete19c4cd2016-02-12 10:19:44 -050094
Edric Milaret627500d2015-03-27 16:41:40 -040095 try {
Edric Milareta3e47282015-10-23 15:20:30 -040096 callModel_ = &CallModel::instance();
Edric Milaret627500d2015-03-27 16:41:40 -040097
98 connect(callModel_, SIGNAL(incomingCall(Call*)),
99 this, SLOT(callIncoming(Call*)));
Edric Milaret627500d2015-03-27 16:41:40 -0400100 connect(callModel_, SIGNAL(callStateChanged(Call*, Call::State)),
101 this, SLOT(callStateChanged(Call*, Call::State)));
102
Edric Milaretfa05d972016-01-13 16:22:04 -0500103 RecentModel::instance().peopleProxy()->setFilterRole(static_cast<int>(Ring::Role::Name));
104 RecentModel::instance().peopleProxy()->setFilterCaseSensitivity(Qt::CaseInsensitive);
Edric Milareta3e47282015-10-23 15:20:30 -0400105 ui->smartList->setModel(RecentModel::instance().peopleProxy());
Edric Milaret6816fd72016-01-29 16:36:24 -0500106
Edric Milaret25236d92016-03-28 09:40:58 -0400107 PersonModel::instance().addCollection<PeerProfileCollection>(LoadOptions::FORCE_ENABLED);
108 ProfileModel::instance().addCollection<LocalProfileCollection>(LoadOptions::FORCE_ENABLED);
109
Edric Milareta3e47282015-10-23 15:20:30 -0400110 PersonModel::instance().
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400111 addCollection<WindowsContactBackend>(LoadOptions::FORCE_ENABLED);
112
Edric Milaret6b68a482016-02-01 15:23:44 -0500113 connect(ui->smartList, &QTreeView::entered, this, &CallWidget::on_entered);
114
115 smartListDelegate_ = new SmartListDelegate();
116 ui->smartList->setSmartListItemDelegate(smartListDelegate_);
117
Olivier SOLDANO69361192017-04-20 10:32:05 -0400118 ui->contactRequestList->setItemDelegate(new ContactRequestItemDelegate());
119
Edric Milaret627500d2015-03-27 16:41:40 -0400120 findRingAccount();
Edric Milareta0ebd062016-01-13 12:18:23 -0500121 setupOutOfCallIM();
122 setupSmartListMenu();
Edric Milaret627500d2015-03-27 16:41:40 -0400123
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500124 connect(ui->smartList, &SmartList::btnVideoClicked, this, &CallWidget::btnComBarVideoClicked);
Nicolas Jager41e4fcf2016-01-28 11:37:03 -0500125
Edric Milaret6b68a482016-02-01 15:23:44 -0500126 connect(RecentModel::instance().selectionModel(),
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500127 SIGNAL(currentChanged(QModelIndex,QModelIndex)),
128 this,
129 SLOT(smartListCurrentChanged(QModelIndex,QModelIndex)));
130
Olivier SOLDANO70279d32017-07-18 15:21:34 -0400131 //set most recent call to view
Olivier SOLDANOaf8f2822017-07-11 12:15:18 -0400132 connect(&RecentModel::instance(), &QAbstractItemModel::dataChanged, [=](const QModelIndex &topLeft, const QModelIndex &bottomRight,const QVector<int> &vec){
133 Q_UNUSED(bottomRight)
134 Q_UNUSED(vec)
Olivier SOLDANOaf8f2822017-07-11 12:15:18 -0400135
Olivier SOLDANO70279d32017-07-18 15:21:34 -0400136 if (topLeft.isValid() && RecentModel::instance().hasActiveCall(topLeft)){
137 ui->smartList->selectionModel()->setCurrentIndex(topLeft,QItemSelectionModel::ClearAndSelect);
Olivier SOLDANOaf8f2822017-07-11 12:15:18 -0400138 }
139 });
140
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500141 connect(RecentModel::instance().selectionModel(), &QItemSelectionModel::selectionChanged, [=](const QItemSelection &selected, const QItemSelection &deselected) {
142 // lambda used to focus on the correct smartList element when switching automatically between two calls
143 Q_UNUSED(deselected)
144 if (selected.size()) {
145 auto idx = selected.indexes().first();
146 auto realIdx = RecentModel::instance().peopleProxy()->mapFromSource(idx);
147 ui->smartList->selectionModel()->setCurrentIndex(realIdx, QItemSelectionModel::ClearAndSelect);
Anthony Léonardecfe7422017-05-04 14:14:37 -0400148 } else {
149 RecentModel::instance().selectionModel()->clearCurrentIndex();
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500150 ui->smartList->clearSelection();
Anthony Léonardecfe7422017-05-04 14:14:37 -0400151 ui->smartList->selectionModel()->clearCurrentIndex();
152 }
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500153 });
154
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400155 connect(&NameDirectory::instance(), SIGNAL(registeredNameFound(Account*,NameDirectory::LookupStatus,const QString&,const QString&)),
156 this, SLOT(contactLineEdit_registeredNameFound(Account*,NameDirectory::LookupStatus,const QString&,const QString&)));
157
158 connect(&AccountModel::instance(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
159 ui->currentAccountWidget, SLOT(update()));
160
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400161 connect(ui->searchBtn, SIGNAL(clicked(bool)), this, SLOT(searchBtnClicked()));
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400162
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400163 connect(ui->sendContactRequestWidget, &SendContactRequestWidget::sendCRclicked, [=]{slidePage(ui->messagingPage);});
164
Anthony Léonardd47179c2017-03-28 10:39:10 -0400165 connect(ui->contactRequestWidget, &ContactRequestWidget::choiceMade, [this]() {
Anthony Léonardecfe7422017-05-04 14:14:37 -0400166 if (getSelectedAccount()->pendingContactRequestModel()->rowCount() == 0)
167 ui->mainTabMenu->setCurrentWidget(ui->mainTabMenuPage1);
168 else
169 ui->contactRequestList->selectionModel()->clear();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400170 });
171
Anthony Léonard2d99df02017-04-19 16:35:19 -0400172 connect(AvailableAccountModel::instance().selectionModel(), &QItemSelectionModel::currentChanged,
Anthony Léonardd47179c2017-03-28 10:39:10 -0400173 this, &CallWidget::selectedAccountChanged);
174
175 // It needs to be called manually once to initialize the ui with the account selected at start.
176 // The second argument (previous) is set to an invalid QModelIndex as it is the first selection.
Anthony Léonard2d99df02017-04-19 16:35:19 -0400177 selectedAccountChanged(AvailableAccountModel::instance().selectionModel()->currentIndex(), QModelIndex());
178
179 // This connect() is used to initialise and track changes of profile's picture
180 connect(&ProfileModel::instance(), &ProfileModel::dataChanged,
181 ui->currentAccountWidget, &CurrentAccountWidget::setPhoto);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400182
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400183 connect(ui->videoWidget, &VideoView::videoSettingsClicked, this, &CallWidget::settingsButtonClicked);
Olivier SOLDANO5cb1a422017-07-26 11:16:50 -0400184
Olivier SOLDANO19193412017-06-06 12:03:36 -0400185 // setup searchingfor mini spinner
186 miniSpinner_ = new QMovie(":/images/waiting.gif");
187 ui->spinnerLabel->setMovie(miniSpinner_);
188 ui->spinnerLabel->hide();
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400189
Edric Milaret80e0b212015-10-16 10:07:43 -0400190 } catch (const std::exception& e) {
191 qDebug() << "INIT ERROR" << e.what();
Edric Milaret627500d2015-03-27 16:41:40 -0400192 }
193}
194
195CallWidget::~CallWidget()
196{
197 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400198 delete menu_;
Edric Milaretab12d022015-12-04 16:09:44 -0500199 delete imDelegate_;
Edric Milaret6b68a482016-02-01 15:23:44 -0500200 delete pageAnim_;
201 delete smartListDelegate_;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500202 delete shareMenu_;
203}
204
205void
Edric Milareta0ebd062016-01-13 12:18:23 -0500206CallWidget::setupOutOfCallIM()
207{
208 ui->listMessageView->setItemDelegate(imDelegate_);
209 ui->listMessageView->setContextMenuPolicy(Qt::ActionsContextMenu);
210
211 auto copyAction = new QAction(tr("Copy"), this);
212 ui->listMessageView->addAction(copyAction);
213 connect(copyAction, &QAction::triggered, [=]() {
214 auto idx = ui->listMessageView->currentIndex();
215 if (idx.isValid()) {
216 auto text = ui->listMessageView->model()->data(idx);
217 QApplication::clipboard()->setText(text.value<QString>());
218 }
219 });
Edric Milaret70ae8782016-04-18 16:10:44 -0400220 QSettings settings;
Edric Milareta0ebd062016-01-13 12:18:23 -0500221 auto displayDate = new QAction(tr("Display date"), this);
222 displayDate->setCheckable(true);
Edric Milaret70ae8782016-04-18 16:10:44 -0400223 displayDate->setChecked(settings.value(SettingsKey::imShowDate).toBool());
Edric Milareta0ebd062016-01-13 12:18:23 -0500224 ui->listMessageView->addAction(displayDate);
225 auto displayAuthor = new QAction(tr("Display author"), this);
226 displayAuthor->setCheckable(true);
Edric Milaret70ae8782016-04-18 16:10:44 -0400227 displayAuthor->setChecked(settings.value(SettingsKey::imShowAuthor).toBool());
Edric Milareta0ebd062016-01-13 12:18:23 -0500228 ui->listMessageView->addAction(displayAuthor);
229 auto lamdba = [=](){
Edric Milaret70ae8782016-04-18 16:10:44 -0400230 QSettings settings;
231 settings.setValue(SettingsKey::imShowAuthor, displayAuthor->isChecked());
232 settings.setValue(SettingsKey::imShowDate, displayDate->isChecked());
233 emit imDelegate_->sizeHintChanged(QModelIndex());
Edric Milareta0ebd062016-01-13 12:18:23 -0500234 };
235 connect(displayAuthor, &QAction::triggered, lamdba);
236 connect(displayDate, &QAction::triggered, lamdba);
Edric Milaret00a32252016-01-19 10:37:13 -0500237
238 connect(&::Media::RecordingModel::instance(),
239 SIGNAL(newTextMessage(::Media::TextRecording*, ContactMethod*)),
240 this,
241 SLOT(onIncomingMessage(::Media::TextRecording*, ContactMethod*)));
242}
243
244void
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400245CallWidget::onIncomingMessage(::Media::TextRecording* t, ContactMethod* cm)
246{
Edric Milaret00a32252016-01-19 10:37:13 -0500247 Q_UNUSED(cm)
248
249 if (!QApplication::focusWidget()) {
250 auto idx = t->instantTextMessagingModel()->
251 index(t->instantTextMessagingModel()->rowCount()-1, 0);
252 GlobalSystemTray::instance()
253 .showMessage("Ring",
254 QString(tr("Message incoming from %1")).arg(
255 idx.data((int)Media::TextRecording::Role::AuthorDisplayname).toString()));
256 QApplication::alert(this, 5000);
257 }
Edric Milareta0ebd062016-01-13 12:18:23 -0500258}
259
260void
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400261CallWidget::setupSmartListMenu()
262{
Edric Milareta0ebd062016-01-13 12:18:23 -0500263 ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
264 connect(ui->smartList, &QListView::customContextMenuRequested, [=](const QPoint& pos){
265 auto idx = ui->smartList->currentIndex();
266 if (not idx.isValid())
267 return;
268 QPoint globalPos = ui->smartList->mapToGlobal(pos);
269 QMenu menu;
270
Edric Milaret9949b342016-02-02 12:25:08 -0500271 QVector<ContactMethod*> contactMethods = RecentModel::instance()
272 .getContactMethods(RecentModel::instance().peopleProxy()->mapToSource(idx));
273 if (contactMethods.isEmpty())
Edric Milareta0ebd062016-01-13 12:18:23 -0500274 return;
Edric Milaret9949b342016-02-02 12:25:08 -0500275
276 if (contactMethods.size() == 1) {
277 auto contactMethod = contactMethods.at(0);
278 auto copyAction = new QAction(tr("Copy number"), this);
279 menu.addAction(copyAction);
280 connect(copyAction, &QAction::triggered, [contactMethod]() {
281 QApplication::clipboard()->setText(contactMethod->uri());
Edric Milareta0ebd062016-01-13 12:18:23 -0500282 });
Edric Milaretac21b3d2016-09-01 12:45:49 -0400283 auto copyNameAction = new QAction(tr("Copy name"), this);
284 menu.addAction(copyNameAction);
285 connect(copyNameAction, &QAction::triggered, [contactMethod]() {
286 QApplication::clipboard()->setText(contactMethod->primaryName());
287 });
Edric Milaret9949b342016-02-02 12:25:08 -0500288 if (not contactMethod->contact() || contactMethod->contact()->isPlaceHolder()) {
289 auto addExisting = new QAction(tr("Add to contact"), this);
290 menu.addAction(addExisting);
291 connect(addExisting, &QAction::triggered, [globalPos, contactMethod]() {
292 ContactPicker contactPicker(contactMethod);
293 contactPicker.move(globalPos.x(), globalPos.y() - (contactPicker.height()/2));
294 contactPicker.exec();
295 });
296 }
297 }
298 else {
299 auto callMenu = menu.addMenu(tr("Call Number"));
300 auto copyMenu = menu.addMenu(tr("Copy Number"));
301 for (auto cM : contactMethods) {
302 auto uri = cM->uri();
303 auto copyAction = new QAction(tr("Copy %1").arg(uri), this);
304 copyMenu->addAction(copyAction);
305 connect(copyAction, &QAction::triggered, [uri]() {
306 QApplication::clipboard()->setText(uri);
307 });
308 auto callAction = new QAction(tr("Call %1").arg(uri), this);
309 callMenu->addAction(callAction);
310 connect(callAction, &QAction::triggered, [cM]() {
311 Call* c = CallModel::instance().dialingCall(cM);
312 c->performAction(Call::Action::ACCEPT);
313 });
314 }
Edric Milareta0ebd062016-01-13 12:18:23 -0500315 }
316 menu.exec(globalPos);
317 });
318}
319
Anthony Léonarda86a8972016-12-15 10:33:47 -0500320void CallWidget::setupQRCode(QString ringID)
Edric Milarete19c4cd2016-02-12 10:19:44 -0500321{
Anthony Léonarda86a8972016-12-15 10:33:47 -0500322 auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
Edric Milaret6d0e5312016-04-04 16:30:22 -0400323 0, //Let the version be decided by libqrencode
324 QR_ECLEVEL_L, // Lowest level of error correction
Edric Milarete19c4cd2016-02-12 10:19:44 -0500325 QR_MODE_8, // 8-bit data mode
326 1);
327 if (not rcode) {
328 qWarning() << "Failed to generate QR code: " << strerror(errno);
329 return;
330 }
331
332 auto margin = 5;
333 int qrwidth = rcode->width + margin * 2;
334 QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono);
335 QPainter painter;
336 painter.begin(&result);
337 painter.setClipRect(QRect(0, 0, qrwidth, qrwidth));
338 painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
339 painter.setBrush(Qt::black);
340 painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
Edric Milaret74474f52016-05-16 13:36:23 -0400341 unsigned char* p;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500342 p = rcode->data;
343 for(int y = 0; y < rcode->width; y++) {
Edric Milaret74474f52016-05-16 13:36:23 -0400344 unsigned char* row = (p + (y * rcode->width));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500345 for(int x = 0; x < rcode->width; x++) {
346 if(*(row + x) & 0x1) {
347 painter.drawRect(margin + x, margin + y, 1, 1);
348 }
349 }
350
351 }
352 painter.end();
353 QRcode_free(rcode);
Edric Milaret6d0e5312016-04-04 16:30:22 -0400354 ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_), Qt::KeepAspectRatio)));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500355}
356
Edric Milaret67007d12015-05-07 09:40:09 -0400357void
358CallWidget::findRingAccount()
359{
Anthony Léonard266dd302017-03-31 14:38:32 -0400360 bool ringAccountFound = false;
Edric Milaret57467842016-08-30 13:06:11 -0400361
Edric Milareta3e47282015-10-23 15:20:30 -0400362 auto a_count = AccountModel::instance().rowCount();
Edric Milaret627500d2015-03-27 16:41:40 -0400363 for (int i = 0; i < a_count; ++i) {
Edric Milareta3e47282015-10-23 15:20:30 -0400364 auto idx = AccountModel::instance().index(i, 0);
Edric Milaret627500d2015-03-27 16:41:40 -0400365 auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
Edric Milaret74474f52016-05-16 13:36:23 -0400366 if (static_cast<Account::Protocol>(protocol.toUInt()) == Account::Protocol::RING) {
Anthony Léonard266dd302017-03-31 14:38:32 -0400367 ringAccountFound = true;
Edric Milareta3e47282015-10-23 15:20:30 -0400368 auto account = AccountModel::instance().getAccountByModelIndex(idx);
Edric Milaret68779c42015-07-09 16:53:03 -0400369 if (account->displayName().isEmpty())
370 account->displayName() = account->alias();
Edric Milaret57467842016-08-30 13:06:11 -0400371 if (account->needsMigration()) {
372 WizardDialog dlg(WizardDialog::MIGRATION, account);
373 dlg.exec();
374 }
Edric Milaret627500d2015-03-27 16:41:40 -0400375 }
376 }
Anthony Léonard266dd302017-03-31 14:38:32 -0400377 if (!ringAccountFound) {
Edric Milaret57467842016-08-30 13:06:11 -0400378 WizardDialog wizardDialog;
379 wizardDialog.exec();
380 }
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400381
382 ui->currentAccountWidget->update();
383
Edric Milaret627500d2015-03-27 16:41:40 -0400384}
385
386void
Edric Milaret00d34f22016-05-09 16:30:29 -0400387CallWidget::callChangedSlot()
388{
389 if (not actualCall_)
390 return;
Olivier SOLDANO2c03dc72017-05-25 11:17:13 -0400391
Edric Milaret41941582016-09-14 12:59:04 -0400392 ui->callerIdLabel->setText(QString("%1")
Edric Milaret00d34f22016-05-09 16:30:29 -0400393 .arg(actualCall_->formattedName()));
394 ui->callerPhoto->setPixmap(
395 QPixmap::fromImage(
396 GlobalInstances::pixmapManipulator()
397 .callPhoto(actualCall_, QSize(130,130)).value<QImage>()));
Olivier SOLDANO2c03dc72017-05-25 11:17:13 -0400398 ui->callerBestIdLabel->setText(actualCall_->peerContactMethod()->bestId());
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400399
Olivier SOLDANO02971ce2016-11-04 15:38:29 -0400400 if(actualCall_->state() == Call::State::OVER || actualCall_->state() == Call::State::FAILURE){
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400401 ui->outboundCallLabel->setText(actualCall_->toHumanStateName(Call::State::INITIALIZATION));
402 } else {
403 ui->outboundCallLabel->setText(actualCall_->toHumanStateName());
404 }
Edric Milaret00d34f22016-05-09 16:30:29 -0400405}
406
407void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500408CallWidget::callIncoming(Call* call)
Edric Milaret627500d2015-03-27 16:41:40 -0400409{
Edric Milaret00a32252016-01-19 10:37:13 -0500410 if (!QApplication::focusWidget()) {
411 GlobalSystemTray::instance()
412 .showMessage("Ring",
413 QString(tr("Call incoming from %1")).arg(call->formattedName()));
Edric Milaret2cf34292015-06-22 16:27:03 -0400414 QApplication::alert(this, 5000);
415 }
416
Edric Milaret6456baa2015-05-21 12:18:07 -0400417 setActualCall(call);
Edric Milaret627500d2015-03-27 16:41:40 -0400418}
419
420void
421CallWidget::on_acceptButton_clicked()
422{
423 if (actualCall_ != nullptr)
Edric Milaret53f57b62015-05-11 11:02:17 -0400424 actualCall_->performAction(Call::Action::ACCEPT);
Edric Milaret627500d2015-03-27 16:41:40 -0400425}
426
427void
428CallWidget::on_refuseButton_clicked()
429{
430 if (actualCall_ == nullptr)
431 return;
432 actualCall_->performAction(Call::Action::REFUSE);
Nicolas Jager13745062016-02-12 18:56:40 -0500433 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Edric Milaret6456baa2015-05-21 12:18:07 -0400434 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -0400435}
436
437void
Edric Milaret67007d12015-05-07 09:40:09 -0400438CallWidget::callStateChanged(Call* call, Call::State previousState)
439{
Edric Milaret627500d2015-03-27 16:41:40 -0400440 Q_UNUSED(previousState)
Edric Milaret4b1be4a2016-01-15 16:49:20 -0500441 if (call == nullptr
442 || call != actualCall_)
Edric Milaretb5b49072015-05-08 11:56:07 -0400443 return;
Edric Milareted0b2802015-10-01 15:10:02 -0400444
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500445 callStateToView(call);
446
Edric Milaret4b1be4a2016-01-15 16:49:20 -0500447 if (call->state() == Call::State::OVER) {
Edric Milaret6456baa2015-05-21 12:18:07 -0400448 setActualCall(nullptr);
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500449 ui->smartList->clearSelection();
Edric Milaret6b68a482016-02-01 15:23:44 -0500450 RecentModel::instance().selectionModel()->clear();
Edric Milaret627500d2015-03-27 16:41:40 -0400451 }
Edric Milaret627500d2015-03-27 16:41:40 -0400452}
453
454void
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400455CallWidget::atExit()
456{
Edric Milaret627500d2015-03-27 16:41:40 -0400457}
Edric Milaret67007d12015-05-07 09:40:09 -0400458
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400459void
460CallWidget::callStateToView(Call* value)
Edric Milaret6b68a482016-02-01 15:23:44 -0500461{
462 if (value) {
463 switch (value->state()) {
464 case Call::State::INCOMING:
465 if (not value->account()->isAutoAnswer())
466 ui->stackedWidget->setCurrentWidget(ui->callInvitePage);
467 else
468 ui->stackedWidget->setCurrentWidget(ui->videoPage);
469 break;
470 case Call::State::CURRENT:
Edric Milareta86e3f52016-03-14 16:28:57 -0400471 case Call::State::CONFERENCE:
Edric Milaret854c6b44d2016-03-08 11:00:48 -0500472 case Call::State::HOLD:
Edric Milaret6b68a482016-02-01 15:23:44 -0500473 ui->stackedWidget->setCurrentWidget(ui->videoPage);
Olivier SOLDANO19193412017-06-06 12:03:36 -0400474 hideMiniSpinner();
Edric Milaret6b68a482016-02-01 15:23:44 -0500475 break;
Olivier SOLDANO02971ce2016-11-04 15:38:29 -0400476 case Call::State::OVER:
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500477 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Olivier SOLDANO02971ce2016-11-04 15:38:29 -0400478 break;
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400479 case Call::State::FAILURE:
480 case Call::State::ERROR:
Olivier SOLDANO02971ce2016-11-04 15:38:29 -0400481 on_cancelButton_clicked();
Olivier SOLDANO19193412017-06-06 12:03:36 -0400482 hideMiniSpinner();
Edric Milaret6b68a482016-02-01 15:23:44 -0500483 break;
484 case Call::State::INITIALIZATION:
485 case Call::State::CONNECTED:
486 case Call::State::RINGING:
Olivier SOLDANO19193412017-06-06 12:03:36 -0400487 miniSpinner_->start();
488 ui->spinnerLabel->show();
Edric Milaret6b68a482016-02-01 15:23:44 -0500489 ui->stackedWidget->setCurrentWidget(ui->outboundCallPage);
490 break;
491 default:
Edric Milaret854c6b44d2016-03-08 11:00:48 -0500492 qWarning() << "Call state not handled doing nothing : "
493 << value->toHumanStateName();
Edric Milaret6b68a482016-02-01 15:23:44 -0500494 break;
495 }
Nicolas Jager13745062016-02-12 18:56:40 -0500496 }
Edric Milaret6b68a482016-02-01 15:23:44 -0500497}
498
Edric Milaret6456baa2015-05-21 12:18:07 -0400499void
500CallWidget::setActualCall(Call* value)
501{
502 actualCall_ = value;
Edric Milaret80e0b212015-10-16 10:07:43 -0400503 CallModel::instance().selectCall(value);
504 ui->videoWidget->pushRenderer(value);
Edric Milareta86e3f52016-03-14 16:28:57 -0400505 ui->instantMessagingWidget->setMediaText(actualCall_);
Edric Milaret6b68a482016-02-01 15:23:44 -0500506 callStateToView(value);
Edric Milaret00d34f22016-05-09 16:30:29 -0400507 if (actualCall_) {
508 callChangedConnection_ = connect(actualCall_,
509 SIGNAL(changed()),
510 this,
511 SLOT(callChangedSlot()));
512 } else
513 disconnect(callChangedConnection_);
514
Edric Milaret6456baa2015-05-21 12:18:07 -0400515}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400516
517void
Edric Milareted0b2802015-10-01 15:10:02 -0400518CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400519{
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400520 if (actualCall_){
Edric Milaretd8528fa2015-07-07 14:13:51 -0400521 actualCall_->performAction(Call::Action::REFUSE);
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400522 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
523 }
Edric Milaretd8528fa2015-07-07 14:13:51 -0400524}
Edric Milareted0b2802015-10-01 15:10:02 -0400525
526void
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400527CallWidget::on_smartList_clicked(const QModelIndex& index)
528{
529 RecentModel::instance().selectionModel()->setCurrentIndex(
530 RecentModel::instance().peopleProxy()->mapToSource(index),
531 QItemSelectionModel::ClearAndSelect);
532}
533
534void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500535CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400536{
Olivier SOLDANO70279d32017-07-18 15:21:34 -0400537 if (!index.isValid())
538 return;
539
Edric Milareta3e47282015-10-23 15:20:30 -0400540 auto realIndex = RecentModel::instance().peopleProxy()->mapToSource(index);
541 if (RecentModel::instance().hasActiveCall(realIndex))
Edric Milareted0b2802015-10-01 15:10:02 -0400542 return;
543
544 ContactMethod* m = nullptr;
545 if (auto cm = realIndex.data((int)Call::Role::ContactMethod).value<ContactMethod*>()) {
546 m = cm;
547 } else {
548 if (auto person = realIndex.data((int)Person::Role::Object).value<Person*>()) {
549 m = person->phoneNumbers().first();
550 }
551 }
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500552
Edric Milareta3e47282015-10-23 15:20:30 -0400553 if (m && !RecentModel::instance().index(0, 0, realIndex).isValid()) {
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500554
555 QPixmap map = QPixmap::fromImage(
556 GlobalInstances::pixmapManipulator().callPhoto(m, QSize(130,130)).value<QImage>());
557 ui->callingPhoto->setPixmap(map);
558
Edric Milareta3e47282015-10-23 15:20:30 -0400559 Call* c = CallModel::instance().dialingCall(m);
Edric Milareted0b2802015-10-01 15:10:02 -0400560 c->performAction(Call::Action::ACCEPT);
Edric Milaret6b68a482016-02-01 15:23:44 -0500561 setActualCall(c);
Edric Milareted0b2802015-10-01 15:10:02 -0400562 }
563}
564
565void
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500566CallWidget::smartListCurrentChanged(const QModelIndex &currentIdx, const QModelIndex &previousIdx)
567{
568 Q_UNUSED(previousIdx);
Anthony Léonardecfe7422017-05-04 14:14:37 -0400569 if (not currentIdx.isValid()) {
570 auto widget = ui->stackedWidget->currentWidget();
571 if (widget == ui->messagingPage || widget == ui->videoPage)
572 slidePage(ui->welcomePage);
573 if(actualCall_)
574 setActualCall(nullptr);
Edric Milareted0b2802015-10-01 15:10:02 -0400575 return;
Anthony Léonardecfe7422017-05-04 14:14:37 -0400576 }
Edric Milareted0b2802015-10-01 15:10:02 -0400577
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500578 //catch call of current index
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500579 auto currentIdxCall = RecentModel::instance().getActiveCall(currentIdx);
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500580
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400581 if (currentIdxCall) {
582 if (currentIdxCall != actualCall_) //if it is different from actual call, switch between the two
583 setActualCall(currentIdxCall);
584 } else { // if there is no call attached to this smartlist index (contact tab)
Edric Milareta0ebd062016-01-13 12:18:23 -0500585 setActualCall(nullptr);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400586 showIMOutOfCall(currentIdx); // change page to contact request of messaging page with correct behaviour
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400587 }
588 /*
589 else { // if non defined behaviour disconnect instant messaging and return to welcome page
Edric Milareted0b2802015-10-01 15:10:02 -0400590 setActualCall(nullptr);
Edric Milaret7ef617b2016-02-01 15:40:57 -0500591 if (imConnection_)
592 disconnect(imConnection_);
Edric Milareted0b2802015-10-01 15:10:02 -0400593 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
594 }
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400595 */
Edric Milareted0b2802015-10-01 15:10:02 -0400596}
597
598void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400599CallWidget::contactReqListCurrentChanged(const QModelIndex &currentIdx, const QModelIndex &previousIdx)
600{
601 Q_UNUSED(previousIdx)
602
Anthony Léonardecfe7422017-05-04 14:14:37 -0400603 if (currentIdx.isValid()) {
604 ui->contactRequestWidget->setCurrentContactRequest(currentIdx);
605 ui->stackedWidget->setCurrentWidget(ui->contactRequestPage);
606 } else {
607 ui->contactRequestWidget->setCurrentContactRequest(QModelIndex());
608 if (ui->stackedWidget->currentWidget() == ui->contactRequestPage)
609 slidePage(ui->welcomePage);
610 }
Anthony Léonardd47179c2017-03-28 10:39:10 -0400611}
612
613void
Edric Milareted0b2802015-10-01 15:10:02 -0400614CallWidget::placeCall()
615{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500616 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400617 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500618 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400619 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500620 ui->ringContactLineEdit->clear();
Edric1bed3f92016-05-19 10:24:48 -0400621 ui->callingPhoto->setPixmap(
622 QPixmap::fromImage(
623 GlobalInstances::pixmapManipulator()
624 .callPhoto(c, QSize(130,130)).value<QImage>()));
Edric Milareted0b2802015-10-01 15:10:02 -0400625}
626
627void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500628CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400629{
630 emit NavigationRequested(ScreenEnum::ConfScreen);
631}
632
633void
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400634CallWidget::searchContactLineEditEntry(const URI &uri)
635{
Olivier SOLDANO73573642017-06-16 11:22:12 -0400636 auto cm = PhoneDirectoryModel::instance().getNumber(uri, getSelectedAccount());
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400637 // if its a new CM, bring it to the top
638 if (cm->lastUsed() == 0)
639 cm->setLastUsed(QDateTime::currentDateTime().toTime_t());
640
641 // select cm
642 RecentModel::instance().selectionModel()->setCurrentIndex(RecentModel::instance().getIndex(cm),
643 QItemSelectionModel::ClearAndSelect);
644 ui->ringContactLineEdit->clear();
Anthony Léonard5cc76412017-04-21 16:52:25 -0400645 cm->setAccount(AvailableAccountModel::instance().currentDefaultAccount(cm));
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400646}
647
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400648bool
649CallWidget::uriNeedNameLookup(const URI uri_passed)
650{
651 if (uri_passed.protocolHint() == URI::ProtocolHint::RING_USERNAME ) {
652 return TRUE;
653 } else if (
654 uri_passed.protocolHint() != URI::ProtocolHint::RING && // not a RingID
655 uri_passed.schemeType() == URI::SchemeType::NONE // scheme type not specified
656 ){
Anthony Léonard2d99df02017-04-19 16:35:19 -0400657 // if no scheme type has been specified, determine ring vs sip by the current selected account
658 auto idx = AvailableAccountModel::instance().selectionModel()->currentIndex();
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400659 if (idx.isValid()) {
660 auto account = idx.data((int)Ring::Role::Object).value<Account *>();
661 if (account && account->protocol() == Account::Protocol::RING)
662 return TRUE;
663 }
664 }
665
666 return FALSE;
667}
668
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400669void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400670CallWidget::processContactLineEdit()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500671{
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400672 auto contactLineText = ui->ringContactLineEdit->text();
673 URI uri_passed = URI(contactLineText);
Anthony Léonard5cc76412017-04-21 16:52:25 -0400674 Account* ac = getSelectedAccount();
Nicolas Jager5e845d52016-02-18 13:26:12 -0500675
Olivier SOLDANO63178ee2016-11-04 16:50:08 -0400676 if (!contactLineText.isNull() && !contactLineText.isEmpty()){
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400677 if (uriNeedNameLookup(uri_passed)){
Anthony Léonard2d99df02017-04-19 16:35:19 -0400678 NameDirectory::instance().lookupName(ac, QString(), uri_passed);
Olivier SOLDANO63178ee2016-11-04 16:50:08 -0400679 } else {
680 searchContactLineEditEntry(uri_passed);
681 }
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400682 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500683}
684
685void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400686CallWidget::on_ringContactLineEdit_returnPressed()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500687{
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400688 processContactLineEdit();
689}
690
691void
692CallWidget::searchBtnClicked()
693{
694 processContactLineEdit();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500695}
696
697void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500698CallWidget::btnComBarVideoClicked()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500699{
700 if (not highLightedIndex_.isValid())
701 return;
702
703 on_smartList_doubleClicked(highLightedIndex_);
704}
Edric Milaretab12d022015-12-04 16:09:44 -0500705
706void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400707CallWidget::selectedAccountChanged(const QModelIndex &current, const QModelIndex &previous)
708{
709 Q_UNUSED(previous)
710
711 if (current.isValid()) {
Olivier SOLDANO97c4c2d2017-05-08 13:22:44 -0400712 if (ui->selectBar->isHidden()){
713 ui->selectBar->show();
714 }
Anthony Léonard2d99df02017-04-19 16:35:19 -0400715 auto ac = current.data(static_cast<int>(Account::Role::Object)).value<Account*>();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400716
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400717 // First, we get back to the welcome view (except if in call)
718
719 if (ui->stackedWidget->currentWidget() != ui->videoPage &&
720 ui->stackedWidget->currentWidget() != ui->welcomePage) {
Anthony Léonardd47179c2017-03-28 10:39:10 -0400721 slidePage(ui->welcomePage);
722 }
723
Anthony Léonard266dd302017-03-31 14:38:32 -0400724 // We setup the ringIdLabel and the QRCode
725 auto protocol = ac->protocol();
726 if (protocol == Account::Protocol::RING) {
727 ui->ringIdLabel->setText((ac->registeredName().isEmpty())?ac->username():ac->registeredName());
728 setupQRCode(ac->username());
729 } else {
730 ui->ringIdLabel->setText(tr("NO RING ACCOUNT FOUND"));
731 }
732
Anthony Léonardd47179c2017-03-28 10:39:10 -0400733 // Then, we update the pending CR list with those from the newly selected account
734 if (disconnect(crListSelectionConnection_)) {
Anthony Léonardecfe7422017-05-04 14:14:37 -0400735 ui->contactRequestList->selectionModel()->clear();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400736 // The selection model must be deleted by the application (see QT doc).
Olivier SOLDANO69361192017-04-20 10:32:05 -0400737 QItemSelectionModel* sMod = ui->contactRequestList->selectionModel();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400738 delete sMod;
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400739 RecentModel::instance().selectionModel()->clear();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400740 }
741
Olivier SOLDANO69361192017-04-20 10:32:05 -0400742 ui->contactRequestList->setItemModel(ac->pendingContactRequestModel());
Anthony Léonard2d99df02017-04-19 16:35:19 -0400743
744 // We modify the currentAccountWidget to reflect the new selected account
745 // if the event wasn't triggered by this widget
746 ui->currentAccountWidget->changeSelectedIndex(current.row());
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400747
748 if (actualCall_){
749 // keep call on foreground
750 callStateToView(actualCall_);
751 }
Olivier SOLDANO97c4c2d2017-05-08 13:22:44 -0400752 } else {
753 ui->selectBar->hide();
754 ui->ringIdLabel->setText("");
Anthony Léonardd47179c2017-03-28 10:39:10 -0400755 }
756}
757
758void
Edric Milaret6b68a482016-02-01 15:23:44 -0500759CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500760{
Edric Milaretab12d022015-12-04 16:09:44 -0500761 ui->contactMethodComboBox->clear();
Olivier SOLDANO31b9aac2017-07-14 15:50:09 -0400762 ui->imNameLabel->setText(QString(tr("%1", "%1 is the contact username"))
763 .arg(nodeIdx.data(static_cast<int>(Ring::Role::Name)).toString()));
764 ui->imIdLabel->setText(QString(tr("%1", "%1 is the contact unique identifier"))
765 .arg(nodeIdx.data(static_cast<int>(Ring::Role::Number)).toString()));
Edric Milaretab12d022015-12-04 16:09:44 -0500766 auto cmVector = RecentModel::instance().getContactMethods(nodeIdx);
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400767 ui->contactMethodComboBox->setVisible(cmVector.size() > 1);
Edric Milaretab12d022015-12-04 16:09:44 -0500768 foreach (const ContactMethod* cm, cmVector) {
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400769 ui->contactMethodComboBox->addItem(cm->bestId());
Edric Milaretab12d022015-12-04 16:09:44 -0500770 }
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400771
Anthony Léonard041ad392017-07-14 16:44:09 -0400772 ui->sendContactRequestPageButton->setVisible(shouldDisplayInviteButton(*cmVector[0]));
773
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500774 ui->stackedWidget->setCurrentWidget(ui->messagingPage);
Edric Milaret70ae8782016-04-18 16:10:44 -0400775 disconnect(imClickedConnection_);
776 imClickedConnection_ = connect(ui->listMessageView, &QListView::clicked, [this](const QModelIndex& index) {
777 auto urlList = index.data(static_cast<int>(Media::TextRecording::Role::LinkList)).value<QList<QUrl>>();
778 if (urlList.size() == 1)
779 QDesktopServices::openUrl(urlList.at(0));
780 else if (urlList.size()) {
781 //TODO Handle multiple url in one message
782 }
783 });
Edric Milaretab12d022015-12-04 16:09:44 -0500784}
785
786void
Edric Milaret6a785af2016-03-07 15:39:30 -0500787CallWidget::on_sendIMButton_clicked()
Edric Milaretab12d022015-12-04 16:09:44 -0500788{
Edric Milaret6a785af2016-03-07 15:39:30 -0500789 if (ui->imMessageEdit->text().trimmed().isEmpty())
Edric Milaretab12d022015-12-04 16:09:44 -0500790 return;
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400791
792 auto idx = RecentModel::instance().selectionModel()->currentIndex();
793 auto cmVec = RecentModel::instance().getContactMethods(idx);
794 if (cmVec.size() > 0) {
795 auto cm = cmVec[0];
796 if(!cm) {
797 qWarning() << "Contact Method not found";
798 return;
799 }
800 QMap<QString, QString> msg;
801 msg["text/plain"] = ui->imMessageEdit->text();
802 cm->sendOfflineTextMessage(msg);
803 ui->imMessageEdit->clear();
Edric Milaretab12d022015-12-04 16:09:44 -0500804 } else {
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400805 qWarning() << "No contact method found for messaging";
Edric Milaretab12d022015-12-04 16:09:44 -0500806 }
807}
808
809void
Edric Milaret6a785af2016-03-07 15:39:30 -0500810CallWidget::on_imMessageEdit_returnPressed()
Edric Milaretab12d022015-12-04 16:09:44 -0500811{
Edric Milaret6a785af2016-03-07 15:39:30 -0500812 on_sendIMButton_clicked();
Edric Milaretab12d022015-12-04 16:09:44 -0500813}
814
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400815void CallWidget::on_contactMethodComboBox_currentIndexChanged(int index)
Edric Milaretab12d022015-12-04 16:09:44 -0500816{
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400817 auto idx = RecentModel::instance().selectionModel()->currentIndex();
818 auto cmVec = RecentModel::instance().getContactMethods(idx);
819 ContactMethod* cm {};
820
821 if (index < cmVec.size() && index >= 0 ){
822 cm = cmVec[index];
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400823 }
824
825 if (cm){
Anthony Léonard041ad392017-07-14 16:44:09 -0400826 ui->sendContactRequestPageButton->setVisible(shouldDisplayInviteButton(*cm));
Olivier SOLDANO815d92f2017-07-13 14:05:36 -0400827 if (auto txtRecording = cm->textRecording()) {
828 ui->listMessageView->setModel(txtRecording->instantMessagingModel());
829 if (imConnection_)
830 disconnect(imConnection_);
831 imConnection_ = connect(txtRecording,
832 SIGNAL(messageInserted(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)),
833 this,
834 SLOT(slotAccountMessageReceived(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)));
835 auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
836 if (messagesPresent) {
837 ui->listMessageView->scrollToBottom();
838 txtRecording->setAllRead();
839 }
840 ui->listMessageView->setVisible(messagesPresent);
841 ui->noMessagesLabel->setVisible(!messagesPresent);
842 if (not messagesPresent) {
843 imVisibleConnection_ = connect(txtRecording->instantMessagingModel(),
844 &QAbstractItemModel::rowsInserted,
845 [this, txtRecording]() {
846 if (imVisibleConnection_)
847 disconnect(imVisibleConnection_);
848 auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
849 ui->listMessageView->setVisible(messagesPresent);
850 ui->noMessagesLabel->setVisible(!messagesPresent);
851 });
852 }
Edric Milaret4be72022016-01-19 10:24:13 -0500853 }
Edric Milaretab12d022015-12-04 16:09:44 -0500854 }
855}
856
857void
858CallWidget::slotAccountMessageReceived(const QMap<QString,QString> message,
859 ContactMethod* cm,
860 Media::Media::Direction dir)
861{
862 Q_UNUSED(message)
Edric Milaretab12d022015-12-04 16:09:44 -0500863 Q_UNUSED(dir)
864
865 ui->listMessageView->scrollToBottom();
Edric Milaret23fd3fa2016-01-15 15:37:35 -0500866 cm->textRecording()->setAllRead();
Edric Milaretab12d022015-12-04 16:09:44 -0500867}
Edric Milaretfa05d972016-01-13 16:22:04 -0500868
869void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500870CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500871{
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400872 RecentModel::instance().peopleProxy()->setFilterRegExp(QRegExp(text, Qt::CaseInsensitive, QRegExp::FixedString));
Edric Milaretfa05d972016-01-13 16:22:04 -0500873}
Edric Milareta0ebd062016-01-13 12:18:23 -0500874
Nicolas Jagerca850292016-01-17 14:11:10 -0500875void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400876CallWidget::backToWelcomePage()
Edric Milareta0ebd062016-01-13 12:18:23 -0500877{
Edric Milaret6b68a482016-02-01 15:23:44 -0500878 RecentModel::instance().selectionModel()->clear();
Anthony Léonard7c630322017-05-03 15:51:14 -0400879 disconnect(imConnection_);
Nicolas Jagerca850292016-01-17 14:11:10 -0500880}
881
Olivier SOLDANO19193412017-06-06 12:03:36 -0400882void CallWidget::hideMiniSpinner()
883{
884 if(ui->spinnerLabel->isVisible()){
885 miniSpinner_->stop();
886 ui->spinnerLabel->hide();
887 }
888}
889
Nicolas Jagerca850292016-01-17 14:11:10 -0500890void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400891CallWidget::on_imBackButton_clicked()
892{
893 backToWelcomePage();
894}
895
896void
Edric Milaret6b68a482016-02-01 15:23:44 -0500897CallWidget::slidePage(QWidget* widget, bool toRight)
Nicolas Jagerca850292016-01-17 14:11:10 -0500898{
Edric Milaret6b68a482016-02-01 15:23:44 -0500899 short dir = (toRight ? -1 : 1);
Nicolas Jagerca850292016-01-17 14:11:10 -0500900 ui->stackedWidget->setCurrentWidget(widget);
Edric Milaret6b68a482016-02-01 15:23:44 -0500901 pageAnim_->setTargetObject(widget);
902 pageAnim_->setDuration(animDuration_);
903 pageAnim_->setStartValue(QPoint(widget->width() * dir, widget->y()));
904 pageAnim_->setEndValue(QPoint(widget->x(), widget->y()));
905 pageAnim_->setEasingCurve(QEasingCurve::OutQuad);
906 pageAnim_->start();
Nicolas Jagerca850292016-01-17 14:11:10 -0500907}
908
909void
Edric Milaret1e598592016-09-02 10:10:01 -0400910CallWidget::on_qrButton_toggled(bool checked)
911{
912 ui->qrLabel->setVisible(checked);
913}
914
915void
Edric Milaret4097d2f2016-02-09 14:41:50 -0500916CallWidget::on_shareButton_clicked()
917{
Edric Milaret1e598592016-09-02 10:10:01 -0400918 Utils::InvokeMailto(tr("Contact me on Ring"), tr("My RingId is : ") + ui->ringIdLabel->text());
Edric Milaret4097d2f2016-02-09 14:41:50 -0500919}
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400920
921void
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400922CallWidget::contactLineEdit_registeredNameFound(Account* account,NameDirectory::LookupStatus status,
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400923 const QString& address,const QString& name)
924{
925 URI uri = URI(ui->ringContactLineEdit->text());
926 QString username_to_lookup = uri.userinfo();
927
928 if (username_to_lookup.compare(name) != 0){
929 return;
930 }
931
932 switch (status)
933 {
934 case NameDirectory::LookupStatus::SUCCESS:
935 {
936 uri = URI("ring:" + address);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400937 qDebug() << "contactLineEdit username to search: " << username_to_lookup;
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400938 qDebug() << uri;
939 searchContactLineEditEntry(uri);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400940 auto cm = PhoneDirectoryModel::instance().getNumber(uri);
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400941 cm->setAccount(account);
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400942 break;
943 }
944 case NameDirectory::LookupStatus::INVALID_NAME:
945 {
946 qDebug() << "Invalid Ring username";
947 break;
948 }
949 case NameDirectory::LookupStatus::ERROR:
950 case NameDirectory::LookupStatus::NOT_FOUND:
951 default:
952 {
953 qDebug() << "Could not resolve Ring username";
954 break;
955 }
956 }
957}
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400958
959void
960CallWidget::on_sendContactRequestPageButton_clicked()
961{
962 ui->sendContactRequestWidget->sendCR(RecentModel::instance().selectionModel()->currentIndex());
Olivier SOLDANO5d4a1ff2017-05-08 13:12:47 -0400963 // temporarly changed comportment waiting for message in payload implementation
964 /*ui->sendContactRequestWidget->setup(RecentModel::instance().selectionModel()->currentIndex());
965 slidePage(ui->sendContactRequestPage);*/
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400966}
967
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400968void
969CallWidget::on_sendCRBackButton_clicked()
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400970{
Anthony Léonardecfe7422017-05-04 14:14:37 -0400971 ui->stackedWidget->setCurrentWidget(ui->messagingPage);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400972}
Anthony Léonardd47179c2017-03-28 10:39:10 -0400973
974void
975CallWidget::on_pendingCRBackButton_clicked()
976{
Olivier SOLDANO69361192017-04-20 10:32:05 -0400977 ui->contactRequestList->selectionModel()->clear();
Olivier SOLDANO8179e992017-07-19 15:59:19 -0400978 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400979}
Anthony Léonard5cc76412017-04-21 16:52:25 -0400980
981Account*
982CallWidget::getSelectedAccount()
983{
984 auto idx = AvailableAccountModel::instance().selectionModel()->currentIndex();
985 if (idx.isValid()) {
986 auto ac = idx.data(static_cast<int>(Ring::Role::Object)).value<Account*>();
987 return ac;
988 }
989 return nullptr;
990}
Anthony Léonardecfe7422017-05-04 14:14:37 -0400991
Anthony Léonard041ad392017-07-14 16:44:09 -0400992bool
993CallWidget::shouldDisplayInviteButton(ContactMethod &cm)
994{
995 // Displaying the button for a SIP ContactMethod is a nonsense
996 if (cm.protocolHint() == URI::ProtocolHint::RING) {
997 // If we know that the other accepted us
998 if (cm.isConfirmed())
999 return false;
1000
1001 // If not sure, we still check if the contact method is linked to a
1002 // Ring account or if the selected account is a RING one.
1003 if(auto linkedAccount = cm.account())
1004 return linkedAccount->protocol() == Account::Protocol::RING;
1005 else if (auto acc = getSelectedAccount())
1006 return acc->protocol() == Account::Protocol::RING;
1007 }
1008 return false;
1009}
1010
Olivier SOLDANO8179e992017-07-19 15:59:19 -04001011void CallWidget::on_contactRequestList_clicked(const QModelIndex &index)
Anthony Léonardecfe7422017-05-04 14:14:37 -04001012{
Olivier SOLDANO8179e992017-07-19 15:59:19 -04001013 RecentModel::instance().selectionModel()->clear();
1014 contactReqListCurrentChanged(index, QModelIndex());
Anthony Léonardecfe7422017-05-04 14:14:37 -04001015}