blob: 5eb000b9d547d819486af3e51024fb71cb4e3e23 [file] [log] [blame]
Isa Nanic6e4a39a2018-12-04 14:26:02 -05001/***************************************************************************
2 * Copyright (C) 2018 by Savoir-faire Linux *
3 * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> *
4 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
5 * Author: Anthony LĂ©onard <anthony.leonard@savoirfairelinux.com> *
6 * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <https://www.gnu.org/licenses/>. *
20 **************************************************************************/
21#include <QPixmap>
22#include <QTimer>
23#include <QModelIndex>
24#include <QFileDialog>
25#include <QInputDialog>
26#include <QStandardPaths>
27#include <QMessageBox>
28
29// account settings
30#include "api/newdevicemodel.h"
31#include "settingsitemwidget.h"
32
33#include "settingswidget.h"
34#include "ui_settingswidget.h"
35
36#include "ui_advancedsettingswidget.h"
37
38#include "passworddialog.h"
39
40#include "regnamedialog.h"
41#include "ui_regnamedialog.h"
42
43#include "setavatardialog.h"
44#include "ui_setavatardialog.h"
45
46#include "deleteaccountdialog.h"
47#include "ui_deleteaccountdialog.h"
48
49
50// general Settings
51#include "winsparkle.h"
52#include "media/recordingmodel.h"
53
54// av setttings
55#include "audio/settings.h"
56#include "audio/outputdevicemodel.h"
57#include "audio/inputdevicemodel.h"
58
59#include "video/devicemodel.h"
60#include "video/channel.h"
61#include "video/resolution.h"
62#include "video/rate.h"
63#include "video/previewmanager.h"
64
65#include "callmodel.h"
66
Isa Nanic6e4a39a2018-12-04 14:26:02 -050067SettingsWidget::SettingsWidget(QWidget* parent)
68 : NavWidget(parent),
69 ui(new Ui::SettingsWidget),
Andreas Traczykb81281e2018-12-13 13:13:28 -050070 scrollArea_(new QScrollArea(this)),
Isa Nanic6e4a39a2018-12-04 14:26:02 -050071 deviceModel_(&Video::DeviceModel::instance()),
72 gif(new QMovie(":/images/ajax-loader.gif"))
73{
74 ui->setupUi(this);
75
76 ui->accountSettingsButton->setAutoFillBackground(true);
77 ui->generalSettingsButton->setAutoFillBackground(true);
78 ui->avSettingsButton->setAutoFillBackground(true);
79
80 ui->accountSettingsButton->setChecked(true);
81
82 ui->exitSettingsButton->setIconSize(QSize(24, 24));
83 ui->exitSettingsButton->setIcon(QPixmap(":/images/icons/round-close-24px.svg"));
84
85
86 // display name (aka alias)
87 ui->displayNameLineEdit->setAlignment(Qt::AlignHCenter);
88 ui->displayNameLineEdit->setPlaceholderText(tr("Enter the displayed name"));
89
90
91 setSelected(Button::accountSettingsButton);
92
93 ui->currentRegisteredID->setReadOnly(true);
94 ui->currentRegisteredID->setStyleSheet("border : 0px;");
95
96 ui->currentRingID->setReadOnly(true);
97
98 avatarSize_ = ui->currentAccountAvatar->width();
99
100 ui->currentAccountAvatar->setIconSize(QSize(avatarSize_, avatarSize_));
101
102 // create ellipse-selectable avatar image
103 QRegion avatarClickableRegion(-1, -1,
104 ui->currentAccountAvatar->width() + 2, ui->currentAccountAvatar->height() + 2, QRegion::Ellipse);
105 ui->currentAccountAvatar->setMask(avatarClickableRegion);
106
107 QString styleS(
108 "QPushButton{"
109 " background-color: rgb(245, 245, 245);"
110 " border: 0px;"
111 "}"
112 " QPushButton:hover{"
113 " background-color: rgb(250, 250, 250);"
114 " border: 0px;"
115 " }"
116
117 "QPushButton:checked{"
118 " background-color: white;"
119 " border: 0px;"
120 "}"
121 );
122
123 ui->accountSettingsButton->setStyleSheet(styleS);
124 ui->generalSettingsButton->setStyleSheet(styleS);
125 ui->avSettingsButton->setStyleSheet(styleS);
126
127 ui->advancedAccountSettingsPButton->setIcon(QPixmap(":/images/icons/round-arrow_drop_down-24px.svg"));
128 ui->linkDevPushButton->setIcon(QPixmap(":/images/icons/round-add-24px.svg"));
129 ui->blockedContactsBtn->setIcon(QPixmap(":/images/icons/round-arrow_drop_up-24px.svg"));
130
131 ui->advancedSettingsOffsetLabel->show();
132
Isa Nanic054ef9a2018-12-11 11:56:28 -0500133 setConnections();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500134}
135
136void
137SettingsWidget::leaveSettingsSlot()
138{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500139 if (advancedSettingsDropped_) {
140 toggleAdvancedSettings();
141 }
142
Isa Nanic054ef9a2018-12-11 11:56:28 -0500143 Video::PreviewManager::instance().stopPreview();
144 saveSizeIndex();
145
146 emit NavigationRequested(ScreenEnum::CallScreen);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500147}
148
149SettingsWidget::~SettingsWidget()
150{
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500151 delete ui;
152}
153
154// called at every callwidget -> settingsWidget navigation
155void
156SettingsWidget::updateSettings(int size)
157{
158 setSelected(Button::accountSettingsButton);
159 resize(size);
160 updateAccountInfoDisplayed();
161}
162
163void
164SettingsWidget::resize(int size)
165{
166 ui->rightSettingsWidget->setGeometry(size, 0, this->width() - size, this->height());
167 ui->accountSettingsButton->setFixedWidth(size);
168}
169
170void
171SettingsWidget::setSelected(Button sel)
172{
Isa Nanic054ef9a2018-12-11 11:56:28 -0500173 saveSizeIndex();
174
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500175 switch (sel)
176 {
177 case Button::accountSettingsButton:
Isa Nanic054ef9a2018-12-11 11:56:28 -0500178 Video::PreviewManager::instance().stopPreview();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500179
Isa Nanic054ef9a2018-12-11 11:56:28 -0500180 if (advancedSettingsDropped_) { toggleAdvancedSettings(); }
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500181 ui->stackedWidget->setCurrentWidget(ui->currentAccountSettingsScrollWidget);
182 if (pastButton_ == Button::generalSettingsButton) {
183 ui->accountSettingsButton->setChecked(true);
184 ui->generalSettingsButton->setChecked(false);
185 break;
186 }
187 else {
188 ui->accountSettingsButton->setChecked(true);
189 ui->avSettingsButton->setChecked(false);
190 break;
191 }
192 case Button::generalSettingsButton:
Isa Nanic054ef9a2018-12-11 11:56:28 -0500193 Video::PreviewManager::instance().stopPreview();
194
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500195 ui->stackedWidget->setCurrentWidget(ui->generalSettings);
196 populateGeneralSettings();
197 if (pastButton_ == Button::avSettingsButton) {
198 ui->generalSettingsButton->setChecked(true);
199 ui->avSettingsButton->setChecked(false);
200 break;
201 }
202 else {
203 ui->generalSettingsButton->setChecked(true);
204 ui->accountSettingsButton->setChecked(false);
205 break;
206 }
207 case Button::avSettingsButton:
208 ui->stackedWidget->setCurrentWidget(ui->avSettings);
Isa Nanic054ef9a2018-12-11 11:56:28 -0500209 populateAVSettings();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500210 if (pastButton_ == Button::accountSettingsButton) {
211 ui->avSettingsButton->setChecked(true);
212 ui->accountSettingsButton->setChecked(false);
213 break;
214 }
215 else {
216 ui->avSettingsButton->setChecked(true);
217 ui->generalSettingsButton->setChecked(false);
218 break;
219 }
220 }
221 pastButton_ = sel;
222}
223
224// called to update current settings information when navigating to settingsWidget
225void
226SettingsWidget::updateAccountInfoDisplayed()
227{
228 ui->currentRegisteredID->setText(QString::fromStdString(LRCInstance::getCurrentAccountInfo().registeredName));
229 ui->currentRingID->setText(QString::fromStdString(LRCInstance::getCurrentAccountInfo().profileInfo.uri));
230
231 ui->currentRegisteredID->setReadOnly(true);
232
233// if no registered name is found for account
234 if (LRCInstance::getCurrentAccountInfo().registeredName.empty()) {
235 ui->currentRegisteredID->setReadOnly(false);
236 }
237 else {
238 ui->currentRegisteredID->setReadOnly(true);
239 setRegNameUi(RegName::BLANK);
240 }
241
242 ui->currentAccountAvatar->setIcon(LRCInstance::getCurrAccPixmap().
243 scaledToHeight(avatarSize_, Qt::SmoothTransformation));
244
245 ui->accountEnableCheckBox->setChecked(LRCInstance::getCurrentAccountInfo().enabled);
246
247 ui->displayNameLineEdit->setText(QString::fromStdString(LRCInstance::getCurrentAccountInfo().profileInfo.alias));
248
249 updateAndShowDevicesSlot();
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500250 bannedContactsShown_ = false;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500251 if (!LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts().size()){
252 ui->blockedContactsBtn->hide();
253 } else {
254 ui->blockedContactsBtn->show();
255 }
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500256}
257
258void
259SettingsWidget::passwordClicked()
260{
261 PasswordDialog passwdDialog(this);
262 passwdDialog.exec();
263}
264
265void
266SettingsWidget::toggleAdvancedSettings()
267{
268 if (advancedSettingsDropped_) {
269 ui->advancedAccountSettingsPButton->setIcon(QPixmap(":/images/icons/round-arrow_drop_down-24px.svg"));
270 ui->currentAccountSettingsScrollLayout->removeWidget(advancedSettingsWidget_);
271 ui->scrollBarLabel->show();
272 ui->advancedSettingsOffsetLabel->hide();
273 delete advancedSettingsWidget_;
274 }
275 else { // will show advanced settings next
276 ui->advancedAccountSettingsPButton->setIcon(QPixmap(":/images/icons/round-arrow_drop_up-24px.svg"));
Andreas Traczykb81281e2018-12-13 13:13:28 -0500277 advancedSettingsWidget_ = new AdvancedSettingsWidget(this);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500278 advancedSettingsWidget_->setMaximumWidth(ui->scrollAreaWidgetContents->width() - 10);
279 ui->currentAccountSettingsScrollLayout->addWidget(advancedSettingsWidget_);
280 ui->advancedSettingsOffsetLabel->show();
281 ui->scrollBarLabel->hide();
282 }
283 advancedSettingsDropped_ = !advancedSettingsDropped_;
284}
285
286void
287SettingsWidget::toggleBannedContacts()
288{
289 if (bannedContactsShown_) { // will show linked devices next
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500290 bannedContactsShown_ = false;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500291 updateAndShowDevicesSlot();
292 }
293 else { // will show banned contacts next
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500294 bannedContactsShown_ = true;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500295 updateAndShowBannedContactsSlot();
296 }
297}
298
299void
300SettingsWidget::resizeEvent(QResizeEvent* event)
301{
302 QWidget::resizeEvent(event);
303 scrollArea_->resize(ui->currentAccountSettingsScrollWidget->width(), this->height());
304}
305
306void
307SettingsWidget::avatarClicked()
308{
309 SetAvatarDialog avatarDialog(this);
310
311 // return new avatar pixmap from setAvatarDialog
312 connect(&avatarDialog, &SetAvatarDialog::pixmapSignal, [&](const std::string& pixString) {
313 if (!pixString.empty()) {
314 LRCInstance::setCurrAccAvatar(pixString);
315 updateAccountInfoDisplayed();
316 }
317 }
318 );
319 avatarDialog.exec();
320}
321
322void
323SettingsWidget::verifyRegisteredNameSlot()
324{
325 if (!LRCInstance::getCurrentAccountInfo().registeredName.empty()) {
326 setRegNameUi(RegName::BLANK);
327 }
328 else {
329 registeredName_ = ui->currentRegisteredID->text().simplified();
330
331 if (!registeredName_.isEmpty()) {
332 if (validateRegNameForm(registeredName_)) { // name has valid form
333 setRegNameUi(RegName::SEARCHING);
334 QTimer::singleShot(300, this, SLOT(beforeNameLookup()));
335 } else { // name does not have valid form
336 setRegNameUi(RegName::INVALIDFORM);
337 }
338 } else {
339 setRegNameUi(RegName::BLANK);
340 }
341 }
342}
343
344// returns true if name is valid registered name
345bool
346SettingsWidget::validateRegNameForm(const QString& regName)
347{
348 QRegularExpression regExp(" ");
349 if (regName.size() > 2 && !regName.contains(regExp)) {
350 return true;
351 }
352 else {
353 return false;
354 }
355}
356
357void
358SettingsWidget::receiveRegNameSlot(const std::string& accountID,
359 lrc::api::account::LookupStatus status, const std::string& address, const std::string& name)
360{
361 Q_UNUSED(accountID); Q_UNUSED(address);
362 afterNameLookup(status, name);
363}
364
365void
366SettingsWidget::beforeNameLookup()
367{
368 NameDirectory::instance().lookupName(nullptr, QString(), registeredName_);
369}
370
371void
372SettingsWidget::afterNameLookup(lrc::api::account::LookupStatus status, const std::string& regName)
373{
374 if (registeredName_.toStdString() == regName && regName.length() > 2) {
375 if (status == lrc::api::account::LookupStatus::NOT_FOUND) {
376 setRegNameUi(RegName::FREE);
377 }
378 else {
379 setRegNameUi(RegName::TAKEN);
380 }
381 }
382 else {
383 setRegNameUi(RegName::BLANK);
384 }
385}
386
387void SettingsWidget::setRegNameUi(RegName stat)
388{
389 disconnect(gif, SIGNAL(frameChanged(int)), this, SLOT(setButtonIconSlot(int)));
390 disconnect(ui->regNameButton, &QPushButton::clicked, this, &SettingsWidget::regNameRegisteredSlot);
391
392 switch (stat) {
393 case RegName::BLANK:
394 ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 0px; border-radius: 3px; border: 1px solid rgb(245, 245, 245);");
395 regNameBtn_ = false;
396 ui->currentRegisteredID->setToolTip(tr(""));
397 ui->regNameButton->setIcon(QPixmap());
398 ui->regNameButton->setEnabled(false);
399 break;
400
401 case RegName::INVALIDFORM:
402 ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 1px solid red; border-radius: 3px;");
403 regNameBtn_ = false;
404 ui->currentRegisteredID->setToolTip(tr("A registered name should not have any spaces and must be at least three letters long"));
405 ui->regNameButton->setIcon(QPixmap(":/images/icons/round-error-24px.svg"));
406 ui->regNameButton->setToolTip(tr("A registered name should not have any spaces and must be at least three letters long"));
407 ui->regNameButton->setEnabled(true);
408 break;
409
410 case RegName::TAKEN:
411 ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 1px solid orange; border-radius: 3px;");
412 regNameBtn_ = false;
413 ui->currentRegisteredID->setToolTip(tr("This name is already taken"));
414 ui->regNameButton->setIcon(QPixmap(":/images/icons/round-error-24px.svg"));
415 ui->regNameButton->setToolTip(tr("This registered name is already taken"));
416 ui->regNameButton->setEnabled(true);
417 break;
418
419 case RegName::FREE:
420 ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 1px solid green; border-radius: 3px;");
421 regNameBtn_ = true;
422 ui->currentRegisteredID->setToolTip(tr("This name is available"));
423 ui->regNameButton->setIcon(QPixmap(":/images/icons/round-check_circle-24px.svg"));
424 ui->regNameButton->setToolTip(tr("Register this name"));
425 ui->regNameButton->setEnabled(true);
426
427 connect(ui->regNameButton, &QPushButton::clicked, this, &SettingsWidget::regNameRegisteredSlot);
428
429 break;
430
431 case RegName::SEARCHING:
432 ui->currentRegisteredID->setStyleSheet("padding-left: 5px; border: 1px solid rgb(2, 187, 213); border-radius: 3px;");
433 regNameBtn_ = false;
434 ui->currentRegisteredID->setToolTip(tr(""));
435
436 connect(gif, SIGNAL(frameChanged(int)), this, SLOT(setButtonIconSlot(int)));
437 gif->start();
438 ui->regNameButton->setEnabled(false);
439
440 break;
441 }
442}
443void SettingsWidget::setButtonIconSlot(int frame)
444{
445 Q_UNUSED(frame);
446 ui->regNameButton->setIcon(QIcon(gif->currentPixmap()));
447}
448
449void
450SettingsWidget::regNameRegisteredSlot()
451{
452 if (!regNameBtn_) { return; }
453
454 RegNameDialog regNameDialog(registeredName_, this);
455 if (regNameDialog.exec() == QDialog::Accepted) { // if user confirms regName choice
456 ui->currentRegisteredID->setReadOnly(true);
457 }
458 else {
459 ui->currentRegisteredID->setText("");
460 registeredName_ = "";
461 }
462 setRegNameUi(RegName::BLANK);
463}
464
465void
466SettingsWidget::setAccEnableSlot(int state)
467{
468 LRCInstance::editableAccountModel()->enableAccount(LRCInstance::getCurrAccId(), (bool)state);
469
470 auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId());
471 LRCInstance::editableAccountModel()->setAccountConfig(LRCInstance::getCurrAccId(), confProps);
472}
473
474void
475SettingsWidget::delAccountSlot()
476{
477 DeleteAccountDialog delDialog(this);
478 delDialog.exec();
479
480 if (!LRCInstance::accountModel().getAccountList().size()) {
Andreas Traczyk9b1b7d42018-12-13 14:44:24 -0500481 LRCInstance::setSelectedAccountId("");
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500482 emit NavigationRequested(ScreenEnum::WizardScreen);
483 }
484}
485
486void
487SettingsWidget::removeDeviceSlot(int index)
488{
489 if (!index) { return; }
490
491 auto deviceList = LRCInstance::getCurrentAccountInfo().deviceModel->getAllDevices();
492 auto it = deviceList.begin();
493
494 std::advance(it, index);
495 QString psswd;
496
497 bool ok = false;
498 if (LRCInstance::getCurrAccConfig().archiveHasPassword) {
499 psswd = QInputDialog::getText(this, tr("Remove Device"),
Isa Nanic100368f2018-12-11 16:43:01 -0500500 tr("Enter this account's password to confirm the removal of this device"), QLineEdit::Password,
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500501 QDir::home().dirName(), &ok);
502 }
503 else {
504 psswd = "";
505 QMessageBox devDel;
506 devDel.setText(tr("Please confirm that you wish to remove this device"));
507 devDel.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
508 devDel.setDefaultButton(QMessageBox::Cancel);
509 if (devDel.exec() == QMessageBox::Ok) { goto delete_; }
510 }
511
512 if (ok) {
513 delete_:
514 LRCInstance::getCurrentAccountInfo().deviceModel->revokeDevice(it->id, psswd.toStdString());
515 updateAndShowDevicesSlot();
516 }
517}
518
519void
520SettingsWidget::unban(int index)
521{
522 auto bannedContactList = LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts();
523 auto it = bannedContactList.begin();
524 std::advance(it, index);
525
526 auto contactInfo = LRCInstance::getCurrentAccountInfo().contactModel->getContact(*it);
527
528 LRCInstance::getCurrentAccountInfo().contactModel->addContact(contactInfo);
529 updateAndShowBannedContactsSlot();
530}
531
532void
533SettingsWidget::exportAccountSlot()
534{
535 QFileDialog dialog(this);
536 QString dir = QFileDialog::getExistingDirectory(this, tr("Export Account Here"),
537 QDir::homePath() + "/Desktop", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
538
539 if (!dir.isEmpty()) {
540 LRCInstance::accountModel().exportToFile(LRCInstance::getCurrAccId(), (dir + "/export.gz").toStdString());
541 }
542}
543
544void
545SettingsWidget::updateAndShowDevicesSlot()
546{
547 ui->settingsListWidget->clear();
548
549 ui->label->setText(tr("Linked Devices"));
550 ui->blockedContactsBtn->setText(tr("Blocked Contacts"));
551 ui->linkDevPushButton->show();
552
553 auto deviceList = LRCInstance::getCurrentAccountInfo().deviceModel->getAllDevices();
554
555 int i = 0;
556
557 for (auto it = deviceList.begin(); it != deviceList.end(); ++it, ++i) {
558 SettingsItemWidget* item = new SettingsItemWidget(itemHeight_, i, false, ui->settingsListWidget);
559 item->setSizeHint(QSize(ui->settingsListWidget->width(), itemHeight_));
560 ui->settingsListWidget->addItem(item);
561
562 if (i) {
563 connect(item->button_, &QPushButton::clicked, [this, i]() {
564 removeDeviceSlot(i);
565 }
566 );
567 }
568 }
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500569}
570
571void
572SettingsWidget::updateAndShowBannedContactsSlot()
573{
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500574 if (bannedContactsShown_) {
575 ui->settingsListWidget->clear();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500576
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500577 ui->label->setText(tr("Blocked Contacts"));
578 ui->blockedContactsBtn->setText(tr("Linked Devices"));
579 ui->linkDevPushButton->hide();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500580
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500581 auto bannedContactList = LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500582
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500583 int i = 0;
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500584
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500585 for (auto it = bannedContactList.begin(); it != bannedContactList.end(); ++it, ++i) {
586 SettingsItemWidget* item = new SettingsItemWidget(itemHeight_, i, true, ui->settingsListWidget);
587 item->setSizeHint(QSize(ui->settingsListWidget->width(), itemHeight_));
588 ui->settingsListWidget->addItem(item);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500589
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500590 connect(item->button_, &QPushButton::clicked, [this, i]() {
591 unban(i);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500592 }
Isa Nanic3a9c6e22018-12-11 17:07:20 -0500593 );
594 }
595 if (!bannedContactList.size()) { updateAndShowDevicesSlot(); ui->blockedContactsBtn->hide(); }
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500596 }
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500597}
598
599void
600SettingsWidget::showLinkDevSlot()
601{
602 if (!advancedSettingsWidget_) { delete advancedSettingsWidget_; }
603
604 linkDevWidget = new LinkDevWidget(ui->scrollAreaWidgetContents);
605 linkDevWidget->setMinimumWidth(600);
606
607 ui->accountHorLayout->insertWidget(1, linkDevWidget);
608
609 linkDevWidget->show();
610 ui->centralWidget->hide();
611
612 connect(linkDevWidget->cancelBtn(), &QPushButton::clicked, this, &SettingsWidget::showCurrentAccountSlot);
613 connect(linkDevWidget->endCancelBtn(), &QPushButton::clicked, this, &SettingsWidget::showCurrentAccountSlot);
614}
615
616void
617SettingsWidget::showCurrentAccountSlot()
618{
619 disconnect(linkDevWidget);
620
621 delete linkDevWidget;
622 ui->centralWidget->show();
623}
624
625void
626SettingsWidget::setConnections()
627{
628 // exitSettingsButton
629 connect(ui->exitSettingsButton, &QPushButton::clicked, this, &SettingsWidget::leaveSettingsSlot);
630
631 connect(ui->accountSettingsButton, &QPushButton::clicked, [this]() {
632 setSelected(Button::accountSettingsButton); }
633 );
634
635 connect(ui->generalSettingsButton, &QPushButton::clicked, [this]() {
636 setSelected(Button::generalSettingsButton); }
637 );
638
639 connect(ui->avSettingsButton, &QPushButton::clicked, [this]() {
640 setSelected(Button::avSettingsButton); }
641 );
642
643 connect(ui->passwdPushButton, &QPushButton::clicked, [this]() {
644 passwordClicked(); }
645 );
646
647 connect(ui->currentAccountAvatar, &QPushButton::clicked, [this]() {
648 avatarClicked(); }
649 );
650
651 connect(ui->advancedAccountSettingsPButton, &QPushButton::clicked, this, &SettingsWidget::toggleAdvancedSettings);
652
653 connect(ui->currentRegisteredID, &QLineEdit::textChanged, this, &SettingsWidget::verifyRegisteredNameSlot);
654
655 connect(&LRCInstance::accountModel(), &lrc::api::NewAccountModel::registeredNameFound,
656 this, &SettingsWidget::receiveRegNameSlot);
657
658 //connect "export account" button
659 connect(ui->btnExportAccount, &QPushButton::clicked, this, &SettingsWidget::exportAccountSlot);
660
661 // connect "delete account" button
662 connect(ui->btnDeletAccount, &QPushButton::clicked, this, &SettingsWidget::delAccountSlot);
663
664 // connect "banned contacts" button
665 connect(ui->blockedContactsBtn, &QPushButton::clicked, this, &SettingsWidget::toggleBannedContacts);
666
667 // connect "link device" button
668 connect(ui->linkDevPushButton, &QPushButton::clicked, this, &SettingsWidget::showLinkDevSlot);
669
670 // update banned accounts automatically
671 connect(LRCInstance::getCurrentAccountInfo().contactModel.get(), &lrc::api::ContactModel::modelUpdated,
672 this, &SettingsWidget::updateAndShowBannedContactsSlot);
673
674 // update linked devices automatically
675 QObject::connect(LRCInstance::getCurrentAccountInfo().deviceModel.get(), &lrc::api::NewDeviceModel::deviceUpdated,
676 this, &SettingsWidget::updateAndShowDevicesSlot);
677
678 // account settings setters {
Isa Nanic100368f2018-12-11 16:43:01 -0500679 connect(ui->accountEnableCheckBox, &QAbstractButton::clicked, this, &SettingsWidget::setAccEnableSlot);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500680
681 connect(ui->displayNameLineEdit, &QLineEdit::textChanged, [this](const QString& displayName) {
682 LRCInstance::setCurrAccDisplayName(displayName.toStdString());
683 }
684 );
685
686 // general settings
687
Isa Nanic100368f2018-12-11 16:43:01 -0500688 connect(ui->notificationCheckBox, &QAbstractButton::clicked, this, &SettingsWidget::setNotificationsSlot);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500689
Isa Nanic100368f2018-12-11 16:43:01 -0500690 connect(ui->closeOrMinCheckBox, &QAbstractButton::clicked, this, &SettingsWidget::setClosedOrMinSlot);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500691
Isa Nanic100368f2018-12-11 16:43:01 -0500692 connect(ui->downloadButton, &QAbstractButton::clicked, this, &SettingsWidget::openDownloadFolderSlot);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500693
Isa Nanic100368f2018-12-11 16:43:01 -0500694 connect(ui->alwaysRecordingCheckBox, &QAbstractButton::clicked, this, &SettingsWidget::setAlwaysRecordingSlot);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500695
Isa Nanic100368f2018-12-11 16:43:01 -0500696 connect(ui->checkUpdateButton, &QAbstractButton::clicked, this, &SettingsWidget::checkForUpdateSlot);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500697
698 connect(ui->intervalUpdateCheckSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsWidget::setUpdateIntervalSlot);
699
Isa Nanic100368f2018-12-11 16:43:01 -0500700 connect(ui->autoUpdateCheckBox, &QAbstractButton::clicked, this, &SettingsWidget::setUpdateAutomaticSlot);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500701
702 // audio / visual settings
703
704 connect(ui->recordPathButton, &QPushButton::clicked, this, &SettingsWidget::openRecordFolderSlot);
705}
706
707
708// ************************* General Settings *************************
709
710void SettingsWidget::populateGeneralSettings()
711{
712 settings_ = new QSettings;
713
714 // settings
Isa Nanic7a3dfa42018-12-12 12:34:42 -0500715 ui->downloadButton->setText(settings_->value(SettingsKey::downloadPath).toString());
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500716 ui->closeOrMinCheckBox->setChecked(settings_->value(SettingsKey::closeOrMinimized).toBool());
717 ui->notificationCheckBox->setChecked(settings_->value(SettingsKey::enableNotifications).toBool());
718
719 //recordings
720 ui->alwaysRecordingCheckBox->setChecked(media::RecordingModel::instance().isAlwaysRecording());
721
722 if (media::RecordingModel::instance().recordPath().isEmpty()) {
723 QString recordPath = QDir::toNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
724 media::RecordingModel::instance().setRecordPath(recordPath);
725 }
726 ui->recordPathButton->setText(media::RecordingModel::instance().recordPath());
727
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500728 ui->autoUpdateCheckBox->setChecked(win_sparkle_get_automatic_check_for_updates());
729 ui->intervalUpdateCheckSpinBox->setValue(win_sparkle_get_update_check_interval() / 86400);
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500730}
731
732void
733SettingsWidget::setNotificationsSlot(int state)
734{
735 if (state == Qt::CheckState::Unchecked) {
736 settings_->setValue(SettingsKey::enableNotifications, false);
737 } else {
738 settings_->setValue(SettingsKey::enableNotifications, true);
739 }
740}
741
742void
743SettingsWidget::setClosedOrMinSlot(int state)
744{
745 if (state == Qt::CheckState::Unchecked) {
746 settings_->setValue(SettingsKey::closeOrMinimized, false);
747 }
748 else {
749 settings_->setValue(SettingsKey::closeOrMinimized, true);
750 }
751}
752
753void
754SettingsWidget::checkForUpdateSlot()
755{
756 win_sparkle_check_update_with_ui();
757}
758
759void
760SettingsWidget::setUpdateIntervalSlot(int value)
761{
762 win_sparkle_set_update_check_interval(value * 86400);
763}
764
765void
766SettingsWidget::setUpdateAutomaticSlot(int state)
767{
768 if (state == Qt::CheckState::Unchecked) {
769 win_sparkle_set_automatic_check_for_updates(false);
770 ui->intervalUpdateCheckSpinBox->setEnabled(false);
771 } else {
772 win_sparkle_set_automatic_check_for_updates(true);
773 ui->intervalUpdateCheckSpinBox->setEnabled(true);
774 }
775}
776
777void
778SettingsWidget::openDownloadFolderSlot()
779{
780 QString dir = QFileDialog::getExistingDirectory(this, tr("Select A Folder For Your Downloads"),
781 QStandardPaths::writableLocation(QStandardPaths::DownloadLocation), QFileDialog::ShowDirsOnly
782 | QFileDialog::DontResolveSymlinks);
783
784 if (!dir.isEmpty()) {
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500785 ui->downloadButton->setText(dir);
Isa Nanic7a3dfa42018-12-12 12:34:42 -0500786 settings_->setValue(SettingsKey::downloadPath, dir);
787 LRCInstance::editableDataTransferModel()->downloadDirectory = dir.toStdString() + "/";
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500788 }
789}
790
791void
792SettingsWidget::setAlwaysRecordingSlot(int state)
793{
794 if (state == Qt::CheckState::Unchecked) {
795 media::RecordingModel::instance().setAlwaysRecording(false);
796 } else {
797 media::RecordingModel::instance().setAlwaysRecording(true);
798 }
799}
800
801void
802SettingsWidget::openRecordFolderSlot()
803{
804 QString dir = QFileDialog::getExistingDirectory(this, tr("Select A Folder For Your Recordings"),
805 media::RecordingModel::instance().recordPath(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
806
807 if (!dir.isEmpty()) {
808 media::RecordingModel::instance().setRecordPath(dir);
809 ui->recordPathButton->setText(media::RecordingModel::instance().recordPath());
810 }
811}
812
813
814// ************************* Audio/Visual Settings *************************
815
816void
817SettingsWidget::populateAVSettings()
818{
819 ui->deviceBox->setModel(deviceModel_);
820 connect(deviceModel_, SIGNAL(currentIndexChanged(int)),
821 this, SLOT(deviceIndexChanged(int)));
822
823 if (ui->deviceBox->count() > 0) {
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500824 deviceBoxCurrentIndexChangedSlot(0);
825 }
826
Isa Nanic054ef9a2018-12-11 11:56:28 -0500827 if (currentResIndex >= 0) {
828 ui->sizeBox->setCurrentIndex(currentResIndex);
829 }
830
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500831 // Audio settings
832 auto inputModel = Audio::Settings::instance().inputDeviceModel();
833 auto outputModel = Audio::Settings::instance().outputDeviceModel();
834
835 ui->outputComboBox->setModel(outputModel);
836 ui->inputComboBox->setModel(inputModel);
837 if (ui->outputComboBox->count() > 0) {
838 ui->outputComboBox->setCurrentIndex(0);
839 }
840 if (ui->inputComboBox->count() > 0) {
841 ui->inputComboBox->setCurrentIndex(0);
842 }
843
Isa Nanic054ef9a2018-12-11 11:56:28 -0500844 isLoading_ = true;
845
846 showPreview();
847
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500848 connect(ui->outputComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
849 this, &SettingsWidget::outputDevIndexChangedSlot);
850 connect(ui->inputComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
851 this, &SettingsWidget::inputdevIndexChangedSlot);
852
853 connect(ui->deviceBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
854 &SettingsWidget::deviceBoxCurrentIndexChangedSlot);
855 connect(ui->sizeBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
856 &SettingsWidget::sizeBoxCurrentIndexChangedSlot);
Isa Nanic054ef9a2018-12-11 11:56:28 -0500857}
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500858
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500859
Isa Nanic054ef9a2018-12-11 11:56:28 -0500860void
861SettingsWidget::saveSizeIndex()
862{
863 currentResIndex = ui->sizeBox->currentIndex();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500864}
865
866void
867SettingsWidget::showPreview()
868{
869 if (!CallModel::instance().getActiveCalls().size()) {
870 ui->previewUnavailableLabel->hide();
871 ui->videoWidget->show();
Isa Nanic054ef9a2018-12-11 11:56:28 -0500872 startVideo();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500873 ui->videoWidget->setIsFullPreview(true);
874 } else {
875 ui->previewUnavailableLabel->show();
876 ui->videoWidget->hide();
877 }
878}
879
880void
881SettingsWidget::deviceBoxCurrentIndexChangedSlot(int index)
882{
883 if (index < 0) {
884 return;
885 }
886
887 if (!isLoading_)
888 deviceModel_->setActive(index);
889
890 auto device = deviceModel_->activeDevice();
891
892 ui->sizeBox->clear();
893
894 isLoading_ = true;
895 if (device->channelList().size() > 0) {
896 for (auto resolution : device->channelList()[0]->validResolutions()) {
897 ui->sizeBox->addItem(resolution->name());
898 }
899 }
900 ui->sizeBox->setCurrentIndex(
901 device->channelList()[0]->activeResolution()->relativeIndex());
902 isLoading_ = false;
903}
904
905void
906SettingsWidget::sizeBoxCurrentIndexChangedSlot(int index)
907{
908 auto device = deviceModel_->activeDevice();
909
910 if (index < 0) return;
911
912 device->channelList()[0]->setActiveResolution(device->channelList()[0]->validResolutions()[index]);
913}
914
915void
916SettingsWidget::deviceIndexChanged(int index)
917{
918 ui->deviceBox->setCurrentIndex(index);
919
920 ui->videoLayout->update();
921}
922
923void
924SettingsWidget::outputDevIndexChangedSlot(int index)
925{
926 auto outputModel = Audio::Settings::instance().outputDeviceModel();
927 outputModel->selectionModel()->setCurrentIndex(outputModel->index(index), QItemSelectionModel::ClearAndSelect);
928}
929
930void
931SettingsWidget::inputdevIndexChangedSlot(int index)
932{
933 auto inputModel = Audio::Settings::instance().inputDeviceModel();
934 inputModel->selectionModel()->setCurrentIndex(inputModel->index(index), QItemSelectionModel::ClearAndSelect);
Isa Nanic054ef9a2018-12-11 11:56:28 -0500935}
936
937void
938SettingsWidget::startVideo()
939{
940 Video::PreviewManager::instance().stopPreview();
941 Video::PreviewManager::instance().startPreview();
942}
943
944void
945SettingsWidget::stopVideo()
946{
947 Video::PreviewManager::instance().stopPreview();
Isa Nanic6e4a39a2018-12-04 14:26:02 -0500948}