blob: effcfaa01807832da306425d22f134773854809d [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 SOLDANOea6d71b2016-11-16 15:56:59 -0500131 connect(RecentModel::instance().selectionModel(), &QItemSelectionModel::selectionChanged, [=](const QItemSelection &selected, const QItemSelection &deselected) {
132 // lambda used to focus on the correct smartList element when switching automatically between two calls
133 Q_UNUSED(deselected)
134 if (selected.size()) {
135 auto idx = selected.indexes().first();
136 auto realIdx = RecentModel::instance().peopleProxy()->mapFromSource(idx);
137 ui->smartList->selectionModel()->setCurrentIndex(realIdx, QItemSelectionModel::ClearAndSelect);
Anthony Léonardecfe7422017-05-04 14:14:37 -0400138 } else {
139 RecentModel::instance().selectionModel()->clearCurrentIndex();
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500140 ui->smartList->clearSelection();
Anthony Léonardecfe7422017-05-04 14:14:37 -0400141 ui->smartList->selectionModel()->clearCurrentIndex();
142 }
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500143 });
144
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400145 connect(&NameDirectory::instance(), SIGNAL(registeredNameFound(Account*,NameDirectory::LookupStatus,const QString&,const QString&)),
146 this, SLOT(contactLineEdit_registeredNameFound(Account*,NameDirectory::LookupStatus,const QString&,const QString&)));
147
148 connect(&AccountModel::instance(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
149 ui->currentAccountWidget, SLOT(update()));
150
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400151 connect(ui->searchBtn, SIGNAL(clicked(bool)), this, SLOT(searchBtnClicked()));
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400152
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400153 connect(ui->sendContactRequestWidget, &SendContactRequestWidget::sendCRclicked, [=]{slidePage(ui->messagingPage);});
154
Anthony Léonardd47179c2017-03-28 10:39:10 -0400155 connect(ui->contactRequestWidget, &ContactRequestWidget::choiceMade, [this]() {
Anthony Léonardecfe7422017-05-04 14:14:37 -0400156 if (getSelectedAccount()->pendingContactRequestModel()->rowCount() == 0)
157 ui->mainTabMenu->setCurrentWidget(ui->mainTabMenuPage1);
158 else
159 ui->contactRequestList->selectionModel()->clear();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400160 });
161
Anthony Léonard2d99df02017-04-19 16:35:19 -0400162 connect(AvailableAccountModel::instance().selectionModel(), &QItemSelectionModel::currentChanged,
Anthony Léonardd47179c2017-03-28 10:39:10 -0400163 this, &CallWidget::selectedAccountChanged);
164
165 // It needs to be called manually once to initialize the ui with the account selected at start.
166 // The second argument (previous) is set to an invalid QModelIndex as it is the first selection.
Anthony Léonard2d99df02017-04-19 16:35:19 -0400167 selectedAccountChanged(AvailableAccountModel::instance().selectionModel()->currentIndex(), QModelIndex());
168
169 // This connect() is used to initialise and track changes of profile's picture
170 connect(&ProfileModel::instance(), &ProfileModel::dataChanged,
171 ui->currentAccountWidget, &CurrentAccountWidget::setPhoto);
Anthony Léonardd47179c2017-03-28 10:39:10 -0400172
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400173 connect(ui->videoWidget, &VideoView::videoSettingsClicked, this, &CallWidget::settingsButtonClicked);
174 connect(ui->videoWidget, &VideoView::videoBackClicked, [=]{setActualCall(nullptr);
175 backToWelcomePage();});
176
Edric Milaret80e0b212015-10-16 10:07:43 -0400177 } catch (const std::exception& e) {
178 qDebug() << "INIT ERROR" << e.what();
Edric Milaret627500d2015-03-27 16:41:40 -0400179 }
180}
181
182CallWidget::~CallWidget()
183{
184 delete ui;
Edric Milaretc7ab5502015-06-15 11:18:02 -0400185 delete menu_;
Edric Milaretab12d022015-12-04 16:09:44 -0500186 delete imDelegate_;
Edric Milaret6b68a482016-02-01 15:23:44 -0500187 delete pageAnim_;
188 delete smartListDelegate_;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500189 delete shareMenu_;
190}
191
192void
Edric Milareta0ebd062016-01-13 12:18:23 -0500193CallWidget::setupOutOfCallIM()
194{
195 ui->listMessageView->setItemDelegate(imDelegate_);
196 ui->listMessageView->setContextMenuPolicy(Qt::ActionsContextMenu);
197
198 auto copyAction = new QAction(tr("Copy"), this);
199 ui->listMessageView->addAction(copyAction);
200 connect(copyAction, &QAction::triggered, [=]() {
201 auto idx = ui->listMessageView->currentIndex();
202 if (idx.isValid()) {
203 auto text = ui->listMessageView->model()->data(idx);
204 QApplication::clipboard()->setText(text.value<QString>());
205 }
206 });
Edric Milaret70ae8782016-04-18 16:10:44 -0400207 QSettings settings;
Edric Milareta0ebd062016-01-13 12:18:23 -0500208 auto displayDate = new QAction(tr("Display date"), this);
209 displayDate->setCheckable(true);
Edric Milaret70ae8782016-04-18 16:10:44 -0400210 displayDate->setChecked(settings.value(SettingsKey::imShowDate).toBool());
Edric Milareta0ebd062016-01-13 12:18:23 -0500211 ui->listMessageView->addAction(displayDate);
212 auto displayAuthor = new QAction(tr("Display author"), this);
213 displayAuthor->setCheckable(true);
Edric Milaret70ae8782016-04-18 16:10:44 -0400214 displayAuthor->setChecked(settings.value(SettingsKey::imShowAuthor).toBool());
Edric Milareta0ebd062016-01-13 12:18:23 -0500215 ui->listMessageView->addAction(displayAuthor);
216 auto lamdba = [=](){
Edric Milaret70ae8782016-04-18 16:10:44 -0400217 QSettings settings;
218 settings.setValue(SettingsKey::imShowAuthor, displayAuthor->isChecked());
219 settings.setValue(SettingsKey::imShowDate, displayDate->isChecked());
220 emit imDelegate_->sizeHintChanged(QModelIndex());
Edric Milareta0ebd062016-01-13 12:18:23 -0500221 };
222 connect(displayAuthor, &QAction::triggered, lamdba);
223 connect(displayDate, &QAction::triggered, lamdba);
Edric Milaret00a32252016-01-19 10:37:13 -0500224
225 connect(&::Media::RecordingModel::instance(),
226 SIGNAL(newTextMessage(::Media::TextRecording*, ContactMethod*)),
227 this,
228 SLOT(onIncomingMessage(::Media::TextRecording*, ContactMethod*)));
229}
230
231void
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400232CallWidget::onIncomingMessage(::Media::TextRecording* t, ContactMethod* cm)
233{
Edric Milaret00a32252016-01-19 10:37:13 -0500234 Q_UNUSED(cm)
235
236 if (!QApplication::focusWidget()) {
237 auto idx = t->instantTextMessagingModel()->
238 index(t->instantTextMessagingModel()->rowCount()-1, 0);
239 GlobalSystemTray::instance()
240 .showMessage("Ring",
241 QString(tr("Message incoming from %1")).arg(
242 idx.data((int)Media::TextRecording::Role::AuthorDisplayname).toString()));
243 QApplication::alert(this, 5000);
244 }
Edric Milareta0ebd062016-01-13 12:18:23 -0500245}
246
247void
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400248CallWidget::setupSmartListMenu()
249{
Edric Milareta0ebd062016-01-13 12:18:23 -0500250 ui->smartList->setContextMenuPolicy(Qt::CustomContextMenu);
251 connect(ui->smartList, &QListView::customContextMenuRequested, [=](const QPoint& pos){
252 auto idx = ui->smartList->currentIndex();
253 if (not idx.isValid())
254 return;
255 QPoint globalPos = ui->smartList->mapToGlobal(pos);
256 QMenu menu;
257
Edric Milaret9949b342016-02-02 12:25:08 -0500258 QVector<ContactMethod*> contactMethods = RecentModel::instance()
259 .getContactMethods(RecentModel::instance().peopleProxy()->mapToSource(idx));
260 if (contactMethods.isEmpty())
Edric Milareta0ebd062016-01-13 12:18:23 -0500261 return;
Edric Milaret9949b342016-02-02 12:25:08 -0500262
263 if (contactMethods.size() == 1) {
264 auto contactMethod = contactMethods.at(0);
265 auto copyAction = new QAction(tr("Copy number"), this);
266 menu.addAction(copyAction);
267 connect(copyAction, &QAction::triggered, [contactMethod]() {
268 QApplication::clipboard()->setText(contactMethod->uri());
Edric Milareta0ebd062016-01-13 12:18:23 -0500269 });
Edric Milaretac21b3d2016-09-01 12:45:49 -0400270 auto copyNameAction = new QAction(tr("Copy name"), this);
271 menu.addAction(copyNameAction);
272 connect(copyNameAction, &QAction::triggered, [contactMethod]() {
273 QApplication::clipboard()->setText(contactMethod->primaryName());
274 });
Edric Milaret9949b342016-02-02 12:25:08 -0500275 if (not contactMethod->contact() || contactMethod->contact()->isPlaceHolder()) {
276 auto addExisting = new QAction(tr("Add to contact"), this);
277 menu.addAction(addExisting);
278 connect(addExisting, &QAction::triggered, [globalPos, contactMethod]() {
279 ContactPicker contactPicker(contactMethod);
280 contactPicker.move(globalPos.x(), globalPos.y() - (contactPicker.height()/2));
281 contactPicker.exec();
282 });
283 }
284 }
285 else {
286 auto callMenu = menu.addMenu(tr("Call Number"));
287 auto copyMenu = menu.addMenu(tr("Copy Number"));
288 for (auto cM : contactMethods) {
289 auto uri = cM->uri();
290 auto copyAction = new QAction(tr("Copy %1").arg(uri), this);
291 copyMenu->addAction(copyAction);
292 connect(copyAction, &QAction::triggered, [uri]() {
293 QApplication::clipboard()->setText(uri);
294 });
295 auto callAction = new QAction(tr("Call %1").arg(uri), this);
296 callMenu->addAction(callAction);
297 connect(callAction, &QAction::triggered, [cM]() {
298 Call* c = CallModel::instance().dialingCall(cM);
299 c->performAction(Call::Action::ACCEPT);
300 });
301 }
Edric Milareta0ebd062016-01-13 12:18:23 -0500302 }
303 menu.exec(globalPos);
304 });
305}
306
Anthony Léonarda86a8972016-12-15 10:33:47 -0500307void CallWidget::setupQRCode(QString ringID)
Edric Milarete19c4cd2016-02-12 10:19:44 -0500308{
Anthony Léonarda86a8972016-12-15 10:33:47 -0500309 auto rcode = QRcode_encodeString(ringID.toStdString().c_str(),
Edric Milaret6d0e5312016-04-04 16:30:22 -0400310 0, //Let the version be decided by libqrencode
311 QR_ECLEVEL_L, // Lowest level of error correction
Edric Milarete19c4cd2016-02-12 10:19:44 -0500312 QR_MODE_8, // 8-bit data mode
313 1);
314 if (not rcode) {
315 qWarning() << "Failed to generate QR code: " << strerror(errno);
316 return;
317 }
318
319 auto margin = 5;
320 int qrwidth = rcode->width + margin * 2;
321 QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono);
322 QPainter painter;
323 painter.begin(&result);
324 painter.setClipRect(QRect(0, 0, qrwidth, qrwidth));
325 painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
326 painter.setBrush(Qt::black);
327 painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white);
Edric Milaret74474f52016-05-16 13:36:23 -0400328 unsigned char* p;
Edric Milarete19c4cd2016-02-12 10:19:44 -0500329 p = rcode->data;
330 for(int y = 0; y < rcode->width; y++) {
Edric Milaret74474f52016-05-16 13:36:23 -0400331 unsigned char* row = (p + (y * rcode->width));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500332 for(int x = 0; x < rcode->width; x++) {
333 if(*(row + x) & 0x1) {
334 painter.drawRect(margin + x, margin + y, 1, 1);
335 }
336 }
337
338 }
339 painter.end();
340 QRcode_free(rcode);
Edric Milaret6d0e5312016-04-04 16:30:22 -0400341 ui->qrLabel->setPixmap(QPixmap::fromImage(result.scaled(QSize(qrSize_, qrSize_), Qt::KeepAspectRatio)));
Edric Milarete19c4cd2016-02-12 10:19:44 -0500342}
343
Edric Milaret67007d12015-05-07 09:40:09 -0400344void
345CallWidget::findRingAccount()
346{
Anthony Léonard266dd302017-03-31 14:38:32 -0400347 bool ringAccountFound = false;
Edric Milaret57467842016-08-30 13:06:11 -0400348
Edric Milareta3e47282015-10-23 15:20:30 -0400349 auto a_count = AccountModel::instance().rowCount();
Edric Milaret627500d2015-03-27 16:41:40 -0400350 for (int i = 0; i < a_count; ++i) {
Edric Milareta3e47282015-10-23 15:20:30 -0400351 auto idx = AccountModel::instance().index(i, 0);
Edric Milaret627500d2015-03-27 16:41:40 -0400352 auto protocol = idx.data(static_cast<int>(Account::Role::Proto));
Edric Milaret74474f52016-05-16 13:36:23 -0400353 if (static_cast<Account::Protocol>(protocol.toUInt()) == Account::Protocol::RING) {
Anthony Léonard266dd302017-03-31 14:38:32 -0400354 ringAccountFound = true;
Edric Milareta3e47282015-10-23 15:20:30 -0400355 auto account = AccountModel::instance().getAccountByModelIndex(idx);
Edric Milaret68779c42015-07-09 16:53:03 -0400356 if (account->displayName().isEmpty())
357 account->displayName() = account->alias();
Edric Milaret57467842016-08-30 13:06:11 -0400358 if (account->needsMigration()) {
359 WizardDialog dlg(WizardDialog::MIGRATION, account);
360 dlg.exec();
361 }
Edric Milaret627500d2015-03-27 16:41:40 -0400362 }
363 }
Anthony Léonard266dd302017-03-31 14:38:32 -0400364 if (!ringAccountFound) {
Edric Milaret57467842016-08-30 13:06:11 -0400365 WizardDialog wizardDialog;
366 wizardDialog.exec();
367 }
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400368
369 ui->currentAccountWidget->update();
370
Edric Milaret627500d2015-03-27 16:41:40 -0400371}
372
373void
Edric Milaret00d34f22016-05-09 16:30:29 -0400374CallWidget::callChangedSlot()
375{
376 if (not actualCall_)
377 return;
Edric Milaret41941582016-09-14 12:59:04 -0400378 ui->callerIdLabel->setText(QString("%1")
Edric Milaret00d34f22016-05-09 16:30:29 -0400379 .arg(actualCall_->formattedName()));
380 ui->callerPhoto->setPixmap(
381 QPixmap::fromImage(
382 GlobalInstances::pixmapManipulator()
383 .callPhoto(actualCall_, QSize(130,130)).value<QImage>()));
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400384
Olivier SOLDANO02971ce2016-11-04 15:38:29 -0400385 if(actualCall_->state() == Call::State::OVER || actualCall_->state() == Call::State::FAILURE){
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400386 ui->outboundCallLabel->setText(actualCall_->toHumanStateName(Call::State::INITIALIZATION));
387 } else {
388 ui->outboundCallLabel->setText(actualCall_->toHumanStateName());
389 }
Edric Milaret00d34f22016-05-09 16:30:29 -0400390}
391
392void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500393CallWidget::callIncoming(Call* call)
Edric Milaret627500d2015-03-27 16:41:40 -0400394{
Edric Milaret00a32252016-01-19 10:37:13 -0500395 if (!QApplication::focusWidget()) {
396 GlobalSystemTray::instance()
397 .showMessage("Ring",
398 QString(tr("Call incoming from %1")).arg(call->formattedName()));
Edric Milaret2cf34292015-06-22 16:27:03 -0400399 QApplication::alert(this, 5000);
400 }
401
Edric Milaret6456baa2015-05-21 12:18:07 -0400402 setActualCall(call);
Edric Milaret627500d2015-03-27 16:41:40 -0400403}
404
405void
406CallWidget::on_acceptButton_clicked()
407{
408 if (actualCall_ != nullptr)
Edric Milaret53f57b62015-05-11 11:02:17 -0400409 actualCall_->performAction(Call::Action::ACCEPT);
Edric Milaret627500d2015-03-27 16:41:40 -0400410}
411
412void
413CallWidget::on_refuseButton_clicked()
414{
415 if (actualCall_ == nullptr)
416 return;
417 actualCall_->performAction(Call::Action::REFUSE);
Nicolas Jager13745062016-02-12 18:56:40 -0500418 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Edric Milaret6456baa2015-05-21 12:18:07 -0400419 setActualCall(nullptr);
Edric Milaret627500d2015-03-27 16:41:40 -0400420}
421
422void
Edric Milaret67007d12015-05-07 09:40:09 -0400423CallWidget::callStateChanged(Call* call, Call::State previousState)
424{
Edric Milaret627500d2015-03-27 16:41:40 -0400425 Q_UNUSED(previousState)
Edric Milaret4b1be4a2016-01-15 16:49:20 -0500426 if (call == nullptr
427 || call != actualCall_)
Edric Milaretb5b49072015-05-08 11:56:07 -0400428 return;
Edric Milareted0b2802015-10-01 15:10:02 -0400429
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500430 callStateToView(call);
431
Edric Milaret4b1be4a2016-01-15 16:49:20 -0500432 if (call->state() == Call::State::OVER) {
Edric Milaret6456baa2015-05-21 12:18:07 -0400433 setActualCall(nullptr);
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500434 ui->smartList->clearSelection();
Edric Milaret6b68a482016-02-01 15:23:44 -0500435 RecentModel::instance().selectionModel()->clear();
Edric Milaret627500d2015-03-27 16:41:40 -0400436 }
Edric Milaret627500d2015-03-27 16:41:40 -0400437}
438
439void
Edric Milaret43f3c1e2015-07-16 17:52:47 -0400440CallWidget::atExit()
441{
Edric Milaret627500d2015-03-27 16:41:40 -0400442}
Edric Milaret67007d12015-05-07 09:40:09 -0400443
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400444void
445CallWidget::callStateToView(Call* value)
Edric Milaret6b68a482016-02-01 15:23:44 -0500446{
447 if (value) {
448 switch (value->state()) {
449 case Call::State::INCOMING:
450 if (not value->account()->isAutoAnswer())
451 ui->stackedWidget->setCurrentWidget(ui->callInvitePage);
452 else
453 ui->stackedWidget->setCurrentWidget(ui->videoPage);
454 break;
455 case Call::State::CURRENT:
Edric Milareta86e3f52016-03-14 16:28:57 -0400456 case Call::State::CONFERENCE:
Edric Milaret854c6b44d2016-03-08 11:00:48 -0500457 case Call::State::HOLD:
Edric Milaret6b68a482016-02-01 15:23:44 -0500458 ui->stackedWidget->setCurrentWidget(ui->videoPage);
459 break;
Olivier SOLDANO02971ce2016-11-04 15:38:29 -0400460 case Call::State::OVER:
Olivier SOLDANOea6d71b2016-11-16 15:56:59 -0500461 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
Olivier SOLDANO02971ce2016-11-04 15:38:29 -0400462 break;
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400463 case Call::State::FAILURE:
464 case Call::State::ERROR:
Olivier SOLDANO02971ce2016-11-04 15:38:29 -0400465 on_cancelButton_clicked();
Edric Milaret6b68a482016-02-01 15:23:44 -0500466 break;
467 case Call::State::INITIALIZATION:
468 case Call::State::CONNECTED:
469 case Call::State::RINGING:
Edric Milaret6b68a482016-02-01 15:23:44 -0500470 ui->stackedWidget->setCurrentWidget(ui->outboundCallPage);
471 break;
472 default:
Edric Milaret854c6b44d2016-03-08 11:00:48 -0500473 qWarning() << "Call state not handled doing nothing : "
474 << value->toHumanStateName();
Edric Milaret6b68a482016-02-01 15:23:44 -0500475 break;
476 }
Nicolas Jager13745062016-02-12 18:56:40 -0500477 }
Edric Milaret6b68a482016-02-01 15:23:44 -0500478}
479
Edric Milaret6456baa2015-05-21 12:18:07 -0400480void
481CallWidget::setActualCall(Call* value)
482{
483 actualCall_ = value;
Edric Milaret80e0b212015-10-16 10:07:43 -0400484 CallModel::instance().selectCall(value);
485 ui->videoWidget->pushRenderer(value);
Edric Milareta86e3f52016-03-14 16:28:57 -0400486 ui->instantMessagingWidget->setMediaText(actualCall_);
Edric Milaret6b68a482016-02-01 15:23:44 -0500487 callStateToView(value);
Edric Milaret00d34f22016-05-09 16:30:29 -0400488 if (actualCall_) {
489 callChangedConnection_ = connect(actualCall_,
490 SIGNAL(changed()),
491 this,
492 SLOT(callChangedSlot()));
493 } else
494 disconnect(callChangedConnection_);
495
Edric Milaret6456baa2015-05-21 12:18:07 -0400496}
Edric Milaretc7ab5502015-06-15 11:18:02 -0400497
498void
Edric Milareted0b2802015-10-01 15:10:02 -0400499CallWidget::on_cancelButton_clicked()
Edric Milaretd8528fa2015-07-07 14:13:51 -0400500{
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400501 if (actualCall_){
Edric Milaretd8528fa2015-07-07 14:13:51 -0400502 actualCall_->performAction(Call::Action::REFUSE);
Olivier SOLDANO2f9e6702016-11-02 14:20:57 -0400503 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
504 }
Edric Milaretd8528fa2015-07-07 14:13:51 -0400505}
Edric Milareted0b2802015-10-01 15:10:02 -0400506
507void
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400508CallWidget::on_smartList_clicked(const QModelIndex& index)
509{
510 RecentModel::instance().selectionModel()->setCurrentIndex(
511 RecentModel::instance().peopleProxy()->mapToSource(index),
512 QItemSelectionModel::ClearAndSelect);
513}
514
515void
Nicolas Jager97a21b42015-12-03 16:55:45 -0500516CallWidget::on_smartList_doubleClicked(const QModelIndex& index)
Edric Milareted0b2802015-10-01 15:10:02 -0400517{
Edric Milareta3e47282015-10-23 15:20:30 -0400518 auto realIndex = RecentModel::instance().peopleProxy()->mapToSource(index);
519 if (RecentModel::instance().hasActiveCall(realIndex))
Edric Milareted0b2802015-10-01 15:10:02 -0400520 return;
521
522 ContactMethod* m = nullptr;
523 if (auto cm = realIndex.data((int)Call::Role::ContactMethod).value<ContactMethod*>()) {
524 m = cm;
525 } else {
526 if (auto person = realIndex.data((int)Person::Role::Object).value<Person*>()) {
527 m = person->phoneNumbers().first();
528 }
529 }
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500530
Edric Milareta3e47282015-10-23 15:20:30 -0400531 if (m && !RecentModel::instance().index(0, 0, realIndex).isValid()) {
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500532
533 QPixmap map = QPixmap::fromImage(
534 GlobalInstances::pixmapManipulator().callPhoto(m, QSize(130,130)).value<QImage>());
535 ui->callingPhoto->setPixmap(map);
536
Edric Milareta3e47282015-10-23 15:20:30 -0400537 Call* c = CallModel::instance().dialingCall(m);
Edric Milareted0b2802015-10-01 15:10:02 -0400538 c->performAction(Call::Action::ACCEPT);
Edric Milaret6b68a482016-02-01 15:23:44 -0500539 setActualCall(c);
Edric Milareted0b2802015-10-01 15:10:02 -0400540 }
541}
542
543void
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500544CallWidget::smartListCurrentChanged(const QModelIndex &currentIdx, const QModelIndex &previousIdx)
545{
546 Q_UNUSED(previousIdx);
Anthony Léonardecfe7422017-05-04 14:14:37 -0400547 if (not currentIdx.isValid()) {
548 auto widget = ui->stackedWidget->currentWidget();
549 if (widget == ui->messagingPage || widget == ui->videoPage)
550 slidePage(ui->welcomePage);
551 if(actualCall_)
552 setActualCall(nullptr);
Edric Milareted0b2802015-10-01 15:10:02 -0400553 return;
Anthony Léonardecfe7422017-05-04 14:14:37 -0400554 }
Edric Milareted0b2802015-10-01 15:10:02 -0400555
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500556 //catch call of current index
Olivier SOLDANO61065ec2016-11-11 16:31:34 -0500557 auto currentIdxCall = RecentModel::instance().getActiveCall(currentIdx);
Olivier SOLDANO703caba2016-11-15 16:18:55 -0500558
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400559 if (currentIdxCall) {
560 if (currentIdxCall != actualCall_) //if it is different from actual call, switch between the two
561 setActualCall(currentIdxCall);
562 } else { // if there is no call attached to this smartlist index (contact tab)
Edric Milareta0ebd062016-01-13 12:18:23 -0500563 setActualCall(nullptr);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400564 showIMOutOfCall(currentIdx); // change page to contact request of messaging page with correct behaviour
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400565 }
566 /*
567 else { // if non defined behaviour disconnect instant messaging and return to welcome page
Edric Milareted0b2802015-10-01 15:10:02 -0400568 setActualCall(nullptr);
Edric Milaret7ef617b2016-02-01 15:40:57 -0500569 if (imConnection_)
570 disconnect(imConnection_);
Edric Milareted0b2802015-10-01 15:10:02 -0400571 ui->stackedWidget->setCurrentWidget(ui->welcomePage);
572 }
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400573 */
Edric Milareted0b2802015-10-01 15:10:02 -0400574}
575
576void
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400577CallWidget::configureSendCRPageButton(const QModelIndex& currentIdx)
578{
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400579 if (currentIdx.isValid()){
580 QVector<ContactMethod*> cmVector = RecentModel::instance().getContactMethods(currentIdx);
581 if (cmVector.size() == 0){
582 ui->sendContactRequestPageButton->hide();
583 return;
584 }
585
586 URI cmUri = cmVector[0]->uri();
587 if (cmUri.protocolHint() == URI::ProtocolHint::RING || uriNeedNameLookup(cmUri)) {
588 ui->sendContactRequestPageButton->show();
589 } else {
590 ui->sendContactRequestPageButton->hide();
591 }
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400592 } else {
593 ui->sendContactRequestPageButton->hide();
594 }
595}
596
597void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400598CallWidget::contactReqListCurrentChanged(const QModelIndex &currentIdx, const QModelIndex &previousIdx)
599{
600 Q_UNUSED(previousIdx)
601
Anthony Léonardecfe7422017-05-04 14:14:37 -0400602 if (currentIdx.isValid()) {
603 ui->contactRequestWidget->setCurrentContactRequest(currentIdx);
604 ui->stackedWidget->setCurrentWidget(ui->contactRequestPage);
605 } else {
606 ui->contactRequestWidget->setCurrentContactRequest(QModelIndex());
607 if (ui->stackedWidget->currentWidget() == ui->contactRequestPage)
608 slidePage(ui->welcomePage);
609 }
Anthony Léonardd47179c2017-03-28 10:39:10 -0400610}
611
612void
Edric Milareted0b2802015-10-01 15:10:02 -0400613CallWidget::placeCall()
614{
Nicolas Jager97a21b42015-12-03 16:55:45 -0500615 if (ui->ringContactLineEdit->text().isEmpty())
Edric Milareted0b2802015-10-01 15:10:02 -0400616 return;
Nicolas Jager97a21b42015-12-03 16:55:45 -0500617 Call* c = CallModel::instance().dialingCall(PhoneDirectoryModel::instance().getNumber(ui->ringContactLineEdit->text()));
Edric Milareted0b2802015-10-01 15:10:02 -0400618 c->performAction(Call::Action::ACCEPT);
Nicolas Jager97a21b42015-12-03 16:55:45 -0500619 ui->ringContactLineEdit->clear();
Edric1bed3f92016-05-19 10:24:48 -0400620 ui->callingPhoto->setPixmap(
621 QPixmap::fromImage(
622 GlobalInstances::pixmapManipulator()
623 .callPhoto(c, QSize(130,130)).value<QImage>()));
Edric Milareted0b2802015-10-01 15:10:02 -0400624}
625
626void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500627CallWidget::settingsButtonClicked()
Edric Milareted0b2802015-10-01 15:10:02 -0400628{
629 emit NavigationRequested(ScreenEnum::ConfScreen);
630}
631
632void
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400633CallWidget::searchContactLineEditEntry(const URI &uri)
634{
635 auto cm = PhoneDirectoryModel::instance().getNumber(uri);
636 // if its a new CM, bring it to the top
637 if (cm->lastUsed() == 0)
638 cm->setLastUsed(QDateTime::currentDateTime().toTime_t());
639
640 // select cm
641 RecentModel::instance().selectionModel()->setCurrentIndex(RecentModel::instance().getIndex(cm),
642 QItemSelectionModel::ClearAndSelect);
643 ui->ringContactLineEdit->clear();
Anthony Léonard5cc76412017-04-21 16:52:25 -0400644 cm->setAccount(AvailableAccountModel::instance().currentDefaultAccount(cm));
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400645}
646
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400647bool
648CallWidget::uriNeedNameLookup(const URI uri_passed)
649{
650 if (uri_passed.protocolHint() == URI::ProtocolHint::RING_USERNAME ) {
651 return TRUE;
652 } else if (
653 uri_passed.protocolHint() != URI::ProtocolHint::RING && // not a RingID
654 uri_passed.schemeType() == URI::SchemeType::NONE // scheme type not specified
655 ){
Anthony Léonard2d99df02017-04-19 16:35:19 -0400656 // if no scheme type has been specified, determine ring vs sip by the current selected account
657 auto idx = AvailableAccountModel::instance().selectionModel()->currentIndex();
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400658 if (idx.isValid()) {
659 auto account = idx.data((int)Ring::Role::Object).value<Account *>();
660 if (account && account->protocol() == Account::Protocol::RING)
661 return TRUE;
662 }
663 }
664
665 return FALSE;
666}
667
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400668void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400669CallWidget::processContactLineEdit()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500670{
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400671 auto contactLineText = ui->ringContactLineEdit->text();
672 URI uri_passed = URI(contactLineText);
Anthony Léonard5cc76412017-04-21 16:52:25 -0400673 Account* ac = getSelectedAccount();
Nicolas Jager5e845d52016-02-18 13:26:12 -0500674
Olivier SOLDANO63178ee2016-11-04 16:50:08 -0400675 if (!contactLineText.isNull() && !contactLineText.isEmpty()){
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400676 if (uriNeedNameLookup(uri_passed)){
Anthony Léonard2d99df02017-04-19 16:35:19 -0400677 NameDirectory::instance().lookupName(ac, QString(), uri_passed);
Olivier SOLDANO63178ee2016-11-04 16:50:08 -0400678 } else {
679 searchContactLineEditEntry(uri_passed);
680 }
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400681 }
Nicolas Jager97a21b42015-12-03 16:55:45 -0500682}
683
684void
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400685CallWidget::on_ringContactLineEdit_returnPressed()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500686{
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400687 processContactLineEdit();
688}
689
690void
691CallWidget::searchBtnClicked()
692{
693 processContactLineEdit();
Nicolas Jager97a21b42015-12-03 16:55:45 -0500694}
695
696void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500697CallWidget::btnComBarVideoClicked()
Nicolas Jager97a21b42015-12-03 16:55:45 -0500698{
699 if (not highLightedIndex_.isValid())
700 return;
701
702 on_smartList_doubleClicked(highLightedIndex_);
703}
Edric Milaretab12d022015-12-04 16:09:44 -0500704
705void
Anthony Léonardd47179c2017-03-28 10:39:10 -0400706CallWidget::selectedAccountChanged(const QModelIndex &current, const QModelIndex &previous)
707{
708 Q_UNUSED(previous)
709
710 if (current.isValid()) {
Olivier SOLDANO97c4c2d2017-05-08 13:22:44 -0400711 if (ui->selectBar->isHidden()){
712 ui->selectBar->show();
713 }
Anthony Léonard2d99df02017-04-19 16:35:19 -0400714 auto ac = current.data(static_cast<int>(Account::Role::Object)).value<Account*>();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400715
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400716 // First, we get back to the welcome view (except if in call)
717
718 if (ui->stackedWidget->currentWidget() != ui->videoPage &&
719 ui->stackedWidget->currentWidget() != ui->welcomePage) {
Anthony Léonardd47179c2017-03-28 10:39:10 -0400720 slidePage(ui->welcomePage);
721 }
722
Anthony Léonard266dd302017-03-31 14:38:32 -0400723 // We setup the ringIdLabel and the QRCode
724 auto protocol = ac->protocol();
725 if (protocol == Account::Protocol::RING) {
726 ui->ringIdLabel->setText((ac->registeredName().isEmpty())?ac->username():ac->registeredName());
727 setupQRCode(ac->username());
728 } else {
729 ui->ringIdLabel->setText(tr("NO RING ACCOUNT FOUND"));
730 }
731
Anthony Léonardd47179c2017-03-28 10:39:10 -0400732 // Then, we update the pending CR list with those from the newly selected account
733 if (disconnect(crListSelectionConnection_)) {
Anthony Léonardecfe7422017-05-04 14:14:37 -0400734 ui->contactRequestList->selectionModel()->clear();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400735 // The selection model must be deleted by the application (see QT doc).
Olivier SOLDANO69361192017-04-20 10:32:05 -0400736 QItemSelectionModel* sMod = ui->contactRequestList->selectionModel();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400737 delete sMod;
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400738 RecentModel::instance().selectionModel()->clear();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400739 }
740
Olivier SOLDANO69361192017-04-20 10:32:05 -0400741 ui->contactRequestList->setItemModel(ac->pendingContactRequestModel());
742 crListSelectionConnection_ = connect(ui->contactRequestList->selectionModel(), &QItemSelectionModel::currentChanged,
Anthony Léonardd47179c2017-03-28 10:39:10 -0400743 this, &CallWidget::contactReqListCurrentChanged);
Anthony Léonard2d99df02017-04-19 16:35:19 -0400744
745 // We modify the currentAccountWidget to reflect the new selected account
746 // if the event wasn't triggered by this widget
747 ui->currentAccountWidget->changeSelectedIndex(current.row());
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400748
749 if (actualCall_){
750 // keep call on foreground
751 callStateToView(actualCall_);
752 }
Olivier SOLDANO97c4c2d2017-05-08 13:22:44 -0400753 } else {
754 ui->selectBar->hide();
755 ui->ringIdLabel->setText("");
Anthony Léonardd47179c2017-03-28 10:39:10 -0400756 }
757}
758
759void
Edric Milaret6b68a482016-02-01 15:23:44 -0500760CallWidget::showIMOutOfCall(const QModelIndex& nodeIdx)
Edric Milaretab12d022015-12-04 16:09:44 -0500761{
Edric Milaretab12d022015-12-04 16:09:44 -0500762 ui->contactMethodComboBox->clear();
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400763 configureSendCRPageButton(nodeIdx);
Edric Milareta0ebd062016-01-13 12:18:23 -0500764 ui->imNameLabel->setText(QString(tr("Conversation with %1", "%1 is the contact name"))
765 .arg(nodeIdx.data(static_cast<int>(Ring::Role::Name)).toString()));
Edric Milaretab12d022015-12-04 16:09:44 -0500766 auto cmVector = RecentModel::instance().getContactMethods(nodeIdx);
Edric Milareta0ebd062016-01-13 12:18:23 -0500767 ui->contactMethodComboBox->setEnabled(cmVector.size() > 1);
Edric Milaretab12d022015-12-04 16:09:44 -0500768 foreach (const ContactMethod* cm, cmVector) {
Edric Milareta0ebd062016-01-13 12:18:23 -0500769 ui->contactMethodComboBox->addItem(cm->uri());
Edric Milaretab12d022015-12-04 16:09:44 -0500770 }
Olivier SOLDANOad0fabb2016-11-25 09:08:01 -0500771 ui->stackedWidget->setCurrentWidget(ui->messagingPage);
Edric Milaret70ae8782016-04-18 16:10:44 -0400772 disconnect(imClickedConnection_);
773 imClickedConnection_ = connect(ui->listMessageView, &QListView::clicked, [this](const QModelIndex& index) {
774 auto urlList = index.data(static_cast<int>(Media::TextRecording::Role::LinkList)).value<QList<QUrl>>();
775 if (urlList.size() == 1)
776 QDesktopServices::openUrl(urlList.at(0));
777 else if (urlList.size()) {
778 //TODO Handle multiple url in one message
779 }
780 });
Edric Milaretab12d022015-12-04 16:09:44 -0500781}
782
783void
Edric Milaret6a785af2016-03-07 15:39:30 -0500784CallWidget::on_sendIMButton_clicked()
Edric Milaretab12d022015-12-04 16:09:44 -0500785{
Edric Milaret6a785af2016-03-07 15:39:30 -0500786 if (ui->imMessageEdit->text().trimmed().isEmpty())
Edric Milaretab12d022015-12-04 16:09:44 -0500787 return;
788 auto number = ui->contactMethodComboBox->currentText();
789 if (auto cm = PhoneDirectoryModel::instance().getNumber(number)) {
790 QMap<QString, QString> msg;
Edric Milaret6a785af2016-03-07 15:39:30 -0500791 msg["text/plain"] = ui->imMessageEdit->text();
Edric Milaretab12d022015-12-04 16:09:44 -0500792 cm->sendOfflineTextMessage(msg);
Edric Milaret6a785af2016-03-07 15:39:30 -0500793 ui->imMessageEdit->clear();
Edric Milaretab12d022015-12-04 16:09:44 -0500794 } else {
795 qWarning() << "Contact Method not found for " << number;
796 }
797}
798
799void
Edric Milaret6a785af2016-03-07 15:39:30 -0500800CallWidget::on_imMessageEdit_returnPressed()
Edric Milaretab12d022015-12-04 16:09:44 -0500801{
Edric Milaret6a785af2016-03-07 15:39:30 -0500802 on_sendIMButton_clicked();
Edric Milaretab12d022015-12-04 16:09:44 -0500803}
804
805void
806CallWidget::on_contactMethodComboBox_currentIndexChanged(const QString& number)
807{
808 auto cm = PhoneDirectoryModel::instance().getNumber(number);
809 if (auto txtRecording = cm->textRecording()) {
810 ui->listMessageView->setModel(txtRecording->instantMessagingModel());
Edric Milaret7ef617b2016-02-01 15:40:57 -0500811 if (imConnection_)
812 disconnect(imConnection_);
Edric Milaretab12d022015-12-04 16:09:44 -0500813 imConnection_ = connect(txtRecording,
Edric Milareta0ebd062016-01-13 12:18:23 -0500814 SIGNAL(messageInserted(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)),
815 this,
816 SLOT(slotAccountMessageReceived(QMap<QString,QString>,ContactMethod*,Media::Media::Direction)));
Edric Milaret4be72022016-01-19 10:24:13 -0500817 auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
818 if (messagesPresent) {
819 ui->listMessageView->scrollToBottom();
820 txtRecording->setAllRead();
821 }
822 ui->listMessageView->setVisible(messagesPresent);
823 ui->noMessagesLabel->setVisible(!messagesPresent);
824 if (not messagesPresent) {
Edric Milaret49130472016-01-22 10:39:37 -0500825 imVisibleConnection_ = connect(txtRecording->instantMessagingModel(),
826 &QAbstractItemModel::rowsInserted,
827 [this, txtRecording]() {
828 if (imVisibleConnection_)
829 disconnect(imVisibleConnection_);
830 auto messagesPresent = txtRecording->instantMessagingModel()->rowCount() > 0;
Edric Milaret4be72022016-01-19 10:24:13 -0500831 ui->listMessageView->setVisible(messagesPresent);
832 ui->noMessagesLabel->setVisible(!messagesPresent);
Edric Milaret4be72022016-01-19 10:24:13 -0500833 });
834 }
Edric Milaretab12d022015-12-04 16:09:44 -0500835 }
836}
837
838void
839CallWidget::slotAccountMessageReceived(const QMap<QString,QString> message,
840 ContactMethod* cm,
841 Media::Media::Direction dir)
842{
843 Q_UNUSED(message)
Edric Milaretab12d022015-12-04 16:09:44 -0500844 Q_UNUSED(dir)
845
846 ui->listMessageView->scrollToBottom();
Edric Milaret23fd3fa2016-01-15 15:37:35 -0500847 cm->textRecording()->setAllRead();
Edric Milaretab12d022015-12-04 16:09:44 -0500848}
Edric Milaretfa05d972016-01-13 16:22:04 -0500849
850void
Edric Milaret8001f6f2016-01-27 09:55:12 -0500851CallWidget::on_ringContactLineEdit_textChanged(const QString& text)
Edric Milaretfa05d972016-01-13 16:22:04 -0500852{
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400853 RecentModel::instance().peopleProxy()->setFilterRegExp(QRegExp(text, Qt::CaseInsensitive, QRegExp::FixedString));
Edric Milaretfa05d972016-01-13 16:22:04 -0500854}
Edric Milareta0ebd062016-01-13 12:18:23 -0500855
Nicolas Jagerca850292016-01-17 14:11:10 -0500856void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400857CallWidget::backToWelcomePage()
Edric Milareta0ebd062016-01-13 12:18:23 -0500858{
Edric Milaret6b68a482016-02-01 15:23:44 -0500859 RecentModel::instance().selectionModel()->clear();
Anthony Léonard7c630322017-05-03 15:51:14 -0400860 disconnect(imConnection_);
Nicolas Jagerca850292016-01-17 14:11:10 -0500861}
862
863void
Olivier SOLDANO2bcdfd72017-05-02 14:37:19 -0400864CallWidget::on_imBackButton_clicked()
865{
866 backToWelcomePage();
867}
868
869void
Edric Milaret6b68a482016-02-01 15:23:44 -0500870CallWidget::slidePage(QWidget* widget, bool toRight)
Nicolas Jagerca850292016-01-17 14:11:10 -0500871{
Edric Milaret6b68a482016-02-01 15:23:44 -0500872 short dir = (toRight ? -1 : 1);
Nicolas Jagerca850292016-01-17 14:11:10 -0500873 ui->stackedWidget->setCurrentWidget(widget);
Edric Milaret6b68a482016-02-01 15:23:44 -0500874 pageAnim_->setTargetObject(widget);
875 pageAnim_->setDuration(animDuration_);
876 pageAnim_->setStartValue(QPoint(widget->width() * dir, widget->y()));
877 pageAnim_->setEndValue(QPoint(widget->x(), widget->y()));
878 pageAnim_->setEasingCurve(QEasingCurve::OutQuad);
879 pageAnim_->start();
Nicolas Jagerca850292016-01-17 14:11:10 -0500880}
881
882void
Edric Milaret7cf39e22016-02-02 12:44:03 -0500883CallWidget::on_copyCMButton_clicked()
884{
885 auto text = ui->contactMethodComboBox->currentText();
886 QApplication::clipboard()->setText(text);
887}
Edric Milaret4097d2f2016-02-09 14:41:50 -0500888
889void
Edric Milaret1e598592016-09-02 10:10:01 -0400890CallWidget::on_qrButton_toggled(bool checked)
891{
892 ui->qrLabel->setVisible(checked);
893}
894
895void
Edric Milaret4097d2f2016-02-09 14:41:50 -0500896CallWidget::on_shareButton_clicked()
897{
Edric Milaret1e598592016-09-02 10:10:01 -0400898 Utils::InvokeMailto(tr("Contact me on Ring"), tr("My RingId is : ") + ui->ringIdLabel->text());
Edric Milaret4097d2f2016-02-09 14:41:50 -0500899}
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400900
901void
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400902CallWidget::contactLineEdit_registeredNameFound(Account* account,NameDirectory::LookupStatus status,
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400903 const QString& address,const QString& name)
904{
905 URI uri = URI(ui->ringContactLineEdit->text());
906 QString username_to_lookup = uri.userinfo();
907
908 if (username_to_lookup.compare(name) != 0){
909 return;
910 }
911
912 switch (status)
913 {
914 case NameDirectory::LookupStatus::SUCCESS:
915 {
916 uri = URI("ring:" + address);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400917 qDebug() << "contactLineEdit username to search: " << username_to_lookup;
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400918 qDebug() << uri;
919 searchContactLineEditEntry(uri);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400920 auto cm = PhoneDirectoryModel::instance().getNumber(uri);
Olivier SOLDANO9657fd12017-03-27 16:06:53 -0400921 cm->setAccount(account);
Anthony Léonardaa90e1a2016-10-12 11:24:17 -0400922 break;
923 }
924 case NameDirectory::LookupStatus::INVALID_NAME:
925 {
926 qDebug() << "Invalid Ring username";
927 break;
928 }
929 case NameDirectory::LookupStatus::ERROR:
930 case NameDirectory::LookupStatus::NOT_FOUND:
931 default:
932 {
933 qDebug() << "Could not resolve Ring username";
934 break;
935 }
936 }
937}
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400938
939void
940CallWidget::on_sendContactRequestPageButton_clicked()
941{
942 ui->sendContactRequestWidget->sendCR(RecentModel::instance().selectionModel()->currentIndex());
943 // temporarly changed comportment waiting for message in payload implementation
944 /*ui->sendContactRequestWidget->setup(RecentModel::instance().selectionModel()->currentIndex());
945 slidePage(ui->sendContactRequestPage);*/
946}
947
Olivier SOLDANO47aa97f2017-04-04 10:40:00 -0400948void
949CallWidget::on_sendCRBackButton_clicked()
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400950{
Anthony Léonardecfe7422017-05-04 14:14:37 -0400951 ui->stackedWidget->setCurrentWidget(ui->messagingPage);
Olivier SOLDANOdd878662017-03-27 16:00:06 -0400952}
Anthony Léonardd47179c2017-03-28 10:39:10 -0400953
954void
955CallWidget::on_pendingCRBackButton_clicked()
956{
Olivier SOLDANO69361192017-04-20 10:32:05 -0400957 ui->contactRequestList->selectionModel()->clear();
Anthony Léonardd47179c2017-03-28 10:39:10 -0400958}
Anthony Léonard5cc76412017-04-21 16:52:25 -0400959
960Account*
961CallWidget::getSelectedAccount()
962{
963 auto idx = AvailableAccountModel::instance().selectionModel()->currentIndex();
964 if (idx.isValid()) {
965 auto ac = idx.data(static_cast<int>(Ring::Role::Object)).value<Account*>();
966 return ac;
967 }
968 return nullptr;
969}
Anthony Léonardecfe7422017-05-04 14:14:37 -0400970
971void CallWidget::on_mainTabMenu_currentChanged(int index)
972{
973 Q_UNUSED(index)
974
975 auto current = ui->mainTabMenu->currentWidget();
976
977 if(current == ui->mainTabMenuPage1)
978 ui->contactRequestList->selectionModel()->clear();
979 else if (current == ui->mainTabMenuPage2)
980 RecentModel::instance().selectionModel()->clear();
981}