blob: 80d133d4f41a7d1ddffd240c41f8b607c0c66488 [file] [log] [blame]
Edric Milaret627500d2015-03-27 16:41:40 -04001/***************************************************************************
Edric Milaretf8048cf2016-05-13 10:21:08 -04002 * Copyright (C) 2015-2016 by Savoir-faire Linux *
Edric Milaret627500d2015-03-27 16:41:40 -04003 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 **************************************************************************/
18
19#include "configurationwidget.h"
20#include "ui_configurationwidget.h"
21
Edric Milaret1eece872015-06-10 13:37:51 -040022#include <QMessageBox>
Edric Milaretfd5a1f22016-02-05 15:30:00 -050023#include <QDir>
24#include <QStandardPaths>
25#include <QFileDialog>
Nicolas Jager74fe46f2016-02-29 14:55:09 -050026#include <QPropertyAnimation>
Edric Milaretce0ea472016-04-12 10:16:56 -040027#include <QtConcurrent/QtConcurrent>
Edric Milaret1eece872015-06-10 13:37:51 -040028
Edric Milaret627500d2015-03-27 16:41:40 -040029#include "video/devicemodel.h"
30#include "video/channel.h"
31#include "video/resolution.h"
32#include "video/rate.h"
Edric Milaret4bba46d2015-04-29 16:33:38 -040033#include "video/previewmanager.h"
Edric Milaret627500d2015-03-27 16:41:40 -040034
Edric Milaret47c40eb2016-03-14 15:06:22 -040035#include "audio/settings.h"
36#include "audio/outputdevicemodel.h"
37#include "audio/inputdevicemodel.h"
38
Edric Milaretfd5a1f22016-02-05 15:30:00 -050039#include "media/recordingmodel.h"
40
Edric Milaret3e6aefe2015-06-05 16:07:26 -040041#include "accountserializationadapter.h"
Edric Milaretb25af972015-06-17 16:55:45 -040042#include "accountstatedelegate.h"
43#include "settingskey.h"
Edric Milaret79d3f682015-12-09 12:32:52 -050044#include "utils.h"
Edric Milaretce0ea472016-04-12 10:16:56 -040045#include "pathpassworddialog.h"
Edric Milaret25236d92016-03-28 09:40:58 -040046#include "photoboothdialog.h"
Edric Milaret3e6aefe2015-06-05 16:07:26 -040047
Edric Milaret627500d2015-03-27 16:41:40 -040048#include "accountmodel.h"
49#include "protocolmodel.h"
50#include "accountdetails.h"
Edric Milaret3aeae3a2015-06-01 17:31:54 -040051#include "callmodel.h"
Edric Milaret1eece872015-06-10 13:37:51 -040052#include "ringtonemodel.h"
53#include "categorizedhistorymodel.h"
Edric Milaret25236d92016-03-28 09:40:58 -040054#include "profilemodel.h"
55#include "profile.h"
56#include "person.h"
Edric Milaret627500d2015-03-27 16:41:40 -040057
Edric Milaret79d3f682015-12-09 12:32:52 -050058#ifdef ENABLE_AUTOUPDATE
59#include "winsparkle.h"
60#endif
Edric Milaret627500d2015-03-27 16:41:40 -040061
62ConfigurationWidget::ConfigurationWidget(QWidget *parent) :
Nicolas Jager74fe46f2016-02-29 14:55:09 -050063 NavWidget(parent),
Edric Milaret627500d2015-03-27 16:41:40 -040064 ui(new Ui::ConfigurationWidget),
Edric Milareta3e47282015-10-23 15:20:30 -040065 accountModel_(&AccountModel::instance()),
66 deviceModel_(&Video::DeviceModel::instance()),
Edric Milaret627500d2015-03-27 16:41:40 -040067 accountDetails_(new AccountDetails())
68{
69 ui->setupUi(this);
70
Nicolas Jager74fe46f2016-02-29 14:55:09 -050071 connect(ui->exitSettingsButton, &QPushButton::clicked, this, [=]() {
72 if (CallModel::instance().getActiveCalls().size() == 0
73 && Video::PreviewManager::instance().isPreviewing()) {
74 Video::PreviewManager::instance().stopPreview();
75 }
76 accountModel_->save();
77 accountDetails_->save();
78 });
79
80 connect(accountDetails_->getDeleteAccountButton(), &QPushButton::clicked, this, [=]() {
81 auto account = accountModel_->getAccountByModelIndex(
82 ui->accountView->currentIndex());
Edric Milaretce0ea472016-04-12 10:16:56 -040083 accountModel_->remove(account);
84 accountModel_->save();
Nicolas Jager74fe46f2016-02-29 14:55:09 -050085 });
86
87 connect(ui->exitSettingsButton, &QPushButton::clicked, this, [=]() {
88 emit NavigationRequested(ScreenEnum::CallScreen);
89 });
90
Edric Milaret627500d2015-03-27 16:41:40 -040091 ui->accountView->setModel(accountModel_);
Edric Milaret01f23842015-06-22 14:46:01 -040092 accountStateDelegate_ = new AccountStateDelegate();
93 ui->accountView->setItemDelegate(accountStateDelegate_);
Edric Milaret627500d2015-03-27 16:41:40 -040094
Edric Milaret627500d2015-03-27 16:41:40 -040095 isLoading_ = true;
96 ui->deviceBox->setModel(deviceModel_);
Edric Milaret94b4aab2015-05-08 12:10:44 -040097 connect(deviceModel_, SIGNAL(currentIndexChanged(int)),
98 this, SLOT(deviceIndexChanged(int)));
Edric Milaret627500d2015-03-27 16:41:40 -040099
Edric Milaretf8048cf2016-05-13 10:21:08 -0400100 AccountModel::instance().selectionModel()->clear();
Edric Milaretce0ea472016-04-12 10:16:56 -0400101 ui->accountView->setSelectionModel(AccountModel::instance().selectionModel());
Edric Milaret627500d2015-03-27 16:41:40 -0400102 connect(ui->accountView->selectionModel(),
Edric Milaret3aeae3a2015-06-01 17:31:54 -0400103 SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
104 this, SLOT(accountSelected(QItemSelection)));
Edric Milaret627500d2015-03-27 16:41:40 -0400105
106 ui->accountView->setCurrentIndex(accountModel_->index(0));
107 ui->accountDetailLayout->addWidget(accountDetails_);
Edric Milaret627500d2015-03-27 16:41:40 -0400108 ui->accountTypeBox->setModel(accountModel_->protocolModel());
Edric Milaret4bba46d2015-04-29 16:33:38 -0400109 ui->startupBox->setChecked(Utils::CheckStartupLink());
Edric Milaret1eece872015-06-10 13:37:51 -0400110
Edric Milaretb25af972015-06-17 16:55:45 -0400111 ui->historyDaySettingsSpinBox->setValue(
Edric Milareta3e47282015-10-23 15:20:30 -0400112 CategorizedHistoryModel::instance().historyLimit());
Edric Milaretb25af972015-06-17 16:55:45 -0400113 ui->closeOrMinCheckBox->setChecked(settings_.value(
114 SettingsKey::closeOrMinimized).toBool());
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500115 connect(ui->stackedWidget, &QStackedWidget::currentChanged, [](int index) {
Edric Milaretfb5fc5c2015-09-24 14:32:49 -0400116 if (index == 1
Edric Milareta3e47282015-10-23 15:20:30 -0400117 && CallModel::instance().getActiveCalls().size() == 0) {
118 Video::PreviewManager::instance().startPreview();
Edric Milaretfb5fc5c2015-09-24 14:32:49 -0400119 } else {
Edric Milareta3e47282015-10-23 15:20:30 -0400120 if (CallModel::instance().getActiveCalls().size() == 0
121 && Video::PreviewManager::instance().isPreviewing()) {
122 Video::PreviewManager::instance().stopPreview();
Edric Milaretfb5fc5c2015-09-24 14:32:49 -0400123 }
124 }
125 });
Edric Milaret0b7fe5d2016-01-27 11:12:43 -0500126
127 ui->videoView->setIsFullPreview(true);
Edric Milaretfd5a1f22016-02-05 15:30:00 -0500128
129 auto recordPath = Media::RecordingModel::instance().recordPath();
130 if (recordPath.isEmpty()) {
131 recordPath = QDir::toNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
132 Media::RecordingModel::instance().setRecordPath(recordPath);
133 }
134 ui->recordPath->setText(Media::RecordingModel::instance().recordPath());
135
136 ui->alwaysRecordCheckBox->setChecked(Media::RecordingModel::instance().isAlwaysRecording());
137 connect(ui->alwaysRecordCheckBox, &QCheckBox::clicked, [](bool checked){
138 Media::RecordingModel::instance().setAlwaysRecording(checked);
139 });
140
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500141 connect(ui->generalTabButton, &QPushButton::toggled, [=] (bool toggled) {
142 if (toggled) {
143 ui->stackedWidget->setCurrentWidget(ui->generalPage);
144 ui->videoTabButton->setChecked(false);
145 ui->accountTabButton->setChecked(false);
146 }
147 });
148
149 connect(ui->videoTabButton, &QPushButton::toggled, [=] (bool toggled) {
150 if (toggled) {
151 ui->stackedWidget->setCurrentWidget(ui->videoPage);
152 ui->accountTabButton->setChecked(false);
153 ui->generalTabButton->setChecked(false);
154 }
155 });
156
157 connect(ui->accountTabButton, &QPushButton::toggled, [=] (bool toggled) {
158 if (toggled) {
159 ui->stackedWidget->setCurrentWidget(ui->accountPage);
160 ui->videoTabButton->setChecked(false);
161 ui->generalTabButton->setChecked(false);
162 }
163 });
164
165 ui->generalTabButton->setChecked(true);
166
Edric Milaret47c40eb2016-03-14 15:06:22 -0400167 auto inputModel = Audio::Settings::instance().inputDeviceModel();
168 auto outputModel = Audio::Settings::instance().outputDeviceModel();
169
170 ui->outputComboBox->setModel(outputModel);
171 ui->inputComboBox->setModel(inputModel);
172 ui->outputComboBox->setCurrentIndex(outputModel->selectionModel()->currentIndex().row());
173 ui->inputComboBox->setCurrentIndex(inputModel->selectionModel()->currentIndex().row());
174 connect(ui->outputComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(outputIndexChanged(int)));
175 connect(ui->inputComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(inputIndexChanged(int)));
176
177
Edric Milaret79d3f682015-12-09 12:32:52 -0500178#ifndef ENABLE_AUTOUPDATE
179 ui->checkUpdateButton->hide();
180 ui->intervalUpdateCheckSpinBox->hide();
181 ui->updateDayLabel->hide();
182 ui->autoUpdateCheckBox->hide();
183#endif
Edric Milaret25236d92016-03-28 09:40:58 -0400184
185 auto profile = ProfileModel::instance().selectedProfile();
186 ui->avatarButton->setIcon(QPixmap::fromImage(Utils::getCirclePhoto(profile->person()->photo().value<QImage>(), ui->avatarButton->width())));
187 ui->profileNameEdit->setText(profile->person()->formattedName());
Edric Milaret627500d2015-03-27 16:41:40 -0400188}
189
Edric Milaretef9b85b2016-02-05 11:47:10 -0500190void ConfigurationWidget::showPreview()
191{
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500192 if (ui->stackedWidget->currentIndex() == 1
Edric Milaretef9b85b2016-02-05 11:47:10 -0500193 && CallModel::instance().getActiveCalls().size() == 0) {
194 ui->previewUnavailable->hide();
195 ui->videoView->show();
196 Video::PreviewManager::instance().startPreview();
197 } else {
198 ui->previewUnavailable->show();
199 ui->videoView->hide();
200 }
201}
202
Edric Milaretfb5fc5c2015-09-24 14:32:49 -0400203void
Edric Milaretf8048cf2016-05-13 10:21:08 -0400204ConfigurationWidget::showEvent(QShowEvent *event)
205{
Edric Milaret79d3f682015-12-09 12:32:52 -0500206#ifdef ENABLE_AUTOUPDATE
207 if (win_sparkle_get_automatic_check_for_updates()) {
208 ui->autoUpdateCheckBox->setChecked(true);
209 }
210 ui->intervalUpdateCheckSpinBox->setValue(win_sparkle_get_update_check_interval() / 86400);
211#endif
Edric Milaretfb5fc5c2015-09-24 14:32:49 -0400212 QWidget::showEvent(event);
Edric Milaretef9b85b2016-02-05 11:47:10 -0500213 showPreview();
Edric Milaretfb5fc5c2015-09-24 14:32:49 -0400214}
215
Edric Milaret627500d2015-03-27 16:41:40 -0400216ConfigurationWidget::~ConfigurationWidget()
217{
218 delete ui;
Edric Milaret01f23842015-06-22 14:46:01 -0400219 delete accountStateDelegate_;
Edric Milaret627500d2015-03-27 16:41:40 -0400220}
221
222void
Edric Milaretf8048cf2016-05-13 10:21:08 -0400223ConfigurationWidget::deviceIndexChanged(int index)
224{
Edric Milaret94b4aab2015-05-08 12:10:44 -0400225 ui->deviceBox->setCurrentIndex(index);
226}
227
228void
Edric Milaret627500d2015-03-27 16:41:40 -0400229ConfigurationWidget::on_deviceBox_currentIndexChanged(int index)
230{
231 if (index < 0)
232 return;
233
234 if (!isLoading_)
235 deviceModel_->setActive(index);
236
237 auto device = deviceModel_->activeDevice();
238
239 ui->sizeBox->clear();
240
241 isLoading_ = true;
242 if (device->channelList().size() > 0) {
243 for (auto resolution : device->channelList()[0]->validResolutions()) {
244 ui->sizeBox->addItem(resolution->name());
245 }
246 }
247 ui->sizeBox->setCurrentIndex(
248 device->channelList()[0]->activeResolution()->relativeIndex());
249 isLoading_ = false;
250}
251
252void
253ConfigurationWidget::on_sizeBox_currentIndexChanged(int index)
254{
255 auto device = deviceModel_->activeDevice();
256
Edric Milaret627500d2015-03-27 16:41:40 -0400257 if (index < 0)
258 return;
259 if (!isLoading_)
260 device->channelList()[0]->setActiveResolution(
261 device->channelList()[0]->validResolutions()[index]);
Edric Milaret627500d2015-03-27 16:41:40 -0400262}
263
264void
Edric Milaretf8048cf2016-05-13 10:21:08 -0400265ConfigurationWidget::accountSelected(QItemSelection itemSel)
266{
267 if (itemSel.size())
268 accountDetails_->show();
269 else
270 accountDetails_->hide();
Edric Milaret3e6aefe2015-06-05 16:07:26 -0400271
Edric Milaretf8048cf2016-05-13 10:21:08 -0400272 if (accountConnection_)
273 disconnect(accountConnection_);
274
Edric Milaret3e6aefe2015-06-05 16:07:26 -0400275 auto account = accountModel_->getAccountByModelIndex(
276 ui->accountView->currentIndex());
277 accountDetails_->setAccount(account);
Edric Milaretf8048cf2016-05-13 10:21:08 -0400278 if (account) {
Edric Milaretce0ea472016-04-12 10:16:56 -0400279 AccountSerializationAdapter adapter(account, accountDetails_);
Edric Milaretf8048cf2016-05-13 10:21:08 -0400280 accountConnection_= connect(account,
281 SIGNAL(propertyChanged(Account*,QString,QString,QString)),
282 this,
283 SLOT(accountPropertyChanged(Account*,QString,QString,QString)));
284 }
285}
286
287void
288ConfigurationWidget::accountPropertyChanged(Account* a,
289 const QString& name,
290 const QString& newVal,
291 const QString& oldVal)
292{
293 Q_UNUSED(name)
294 Q_UNUSED(newVal)
295 Q_UNUSED(oldVal)
296 accountDetails_->setAccount(a);
297 AccountSerializationAdapter adapter(a, accountDetails_);
Edric Milaret627500d2015-03-27 16:41:40 -0400298}
299
300void
Edric Milaret627500d2015-03-27 16:41:40 -0400301ConfigurationWidget::on_addAccountButton_clicked()
302{
Edric Milaret53ac6e52015-09-14 13:37:06 -0400303 auto account = accountModel_->add(tr("New Account"),
Edric Milaret3aeae3a2015-06-01 17:31:54 -0400304 ui->accountTypeBox->model()->index(
305 ui->accountTypeBox->currentIndex(), 0));
Edric Milaret031c3052015-04-29 18:14:18 -0400306 account->setRingtonePath(Utils::GetRingtonePath());
Edric Milaret627500d2015-03-27 16:41:40 -0400307 accountModel_->save();
308}
Edric Milaret4bba46d2015-04-29 16:33:38 -0400309
Edric Milaret3aeae3a2015-06-01 17:31:54 -0400310void
311ConfigurationWidget::on_startupBox_toggled(bool checked)
Edric Milaret4bba46d2015-04-29 16:33:38 -0400312{
313 if (checked)
314 Utils::CreateStartupLink();
315 else
316 Utils::DeleteStartupLink();
317}
Edric Milaret3aeae3a2015-06-01 17:31:54 -0400318
319void
Edric Milaret1eece872015-06-10 13:37:51 -0400320ConfigurationWidget::on_clearHistoryButton_clicked()
321{
322 QMessageBox confirmationDialog;
323
Edric Milaret53ac6e52015-09-14 13:37:06 -0400324 confirmationDialog.setText(tr("Are you sure you want to clear all your history?"));
Edric Milaret1eece872015-06-10 13:37:51 -0400325 confirmationDialog.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
326 auto ret = confirmationDialog.exec();
327
328 if (ret == QMessageBox::Ok)
Edric Milareta3e47282015-10-23 15:20:30 -0400329 CategorizedHistoryModel::instance().clearAllCollections();
Edric Milaret1eece872015-06-10 13:37:51 -0400330}
331
332void
333ConfigurationWidget::on_historyDaySettingsSpinBox_valueChanged(int limit)
334{
Edric Milareta3e47282015-10-23 15:20:30 -0400335 if (CategorizedHistoryModel::instance().historyLimit() != limit)
336 CategorizedHistoryModel::instance().setHistoryLimit(limit);
Edric Milaret1eece872015-06-10 13:37:51 -0400337}
Edric Milaretb25af972015-06-17 16:55:45 -0400338
339void
340ConfigurationWidget::on_closeOrMinCheckBox_toggled(bool checked)
341{
342 settings_.setValue(SettingsKey::closeOrMinimized, checked);
343}
Edric Milaret79d3f682015-12-09 12:32:52 -0500344
345void
346ConfigurationWidget::on_checkUpdateButton_clicked()
347{
348#ifdef ENABLE_AUTOUPDATE
349 win_sparkle_check_update_with_ui();
350#endif
351}
352
353void
354ConfigurationWidget::on_autoUpdateCheckBox_toggled(bool checked)
355{
356#ifdef ENABLE_AUTOUPDATE
357 win_sparkle_set_automatic_check_for_updates(checked);
358#endif
359}
360
361void
362ConfigurationWidget::on_intervalUpdateCheckSpinBox_valueChanged(int arg1)
363{
364#ifdef ENABLE_AUTOUPDATE
365 win_sparkle_set_update_check_interval(arg1 * 86400);
366#endif
367}
Edric Milaretef9b85b2016-02-05 11:47:10 -0500368
369void
Nicolas Jager74fe46f2016-02-29 14:55:09 -0500370ConfigurationWidget::on_stackedWidget_currentChanged(int index)
Edric Milaretef9b85b2016-02-05 11:47:10 -0500371{
372 Q_UNUSED(index)
373 showPreview();
374}
Edric Milaretfd5a1f22016-02-05 15:30:00 -0500375
376void
377ConfigurationWidget::on_recordPath_clicked()
378{
379 QString dir = QFileDialog::getExistingDirectory(this, tr("Choose Directory"),
380 Media::RecordingModel::instance().recordPath(),
381 QFileDialog::ShowDirsOnly
382 | QFileDialog::DontResolveSymlinks);
383 if (not dir.isEmpty()) {
384 Media::RecordingModel::instance().setRecordPath(dir);
385 ui->recordPath->setText(dir);
386 }
387}
Edric Milaret47c40eb2016-03-14 15:06:22 -0400388
389void
390ConfigurationWidget::outputIndexChanged(int index)
391{
392 auto outputModel = Audio::Settings::instance().outputDeviceModel();
393 outputModel->selectionModel()->setCurrentIndex(outputModel->index(index), QItemSelectionModel::ClearAndSelect);
394}
395
396void
397ConfigurationWidget::inputIndexChanged(int index)
398{
399 auto inputModel = Audio::Settings::instance().inputDeviceModel();
400 inputModel->selectionModel()->setCurrentIndex(inputModel->index(index), QItemSelectionModel::ClearAndSelect);
401}
Edric Milaretce0ea472016-04-12 10:16:56 -0400402
403void
404ConfigurationWidget::on_importButton_clicked()
405{
406 PathPasswordDialog dlg;
407 if (dlg.exec() == QDialog::Accepted)
408 if (AccountModel::instance().importAccounts(dlg.path_, dlg.password_) > 0)
409 errorDlg_.showMessage(tr("An error occured while importing account."));
410}
411
412void
413ConfigurationWidget::on_exportButton_clicked()
414{
415 PathPasswordDialog dlg;
416 dlg.exportMode = true;
417 if (dlg.exec() == QDialog::Accepted) {
418 auto func = [](QString path, QString password)
419 {
420 AccountModel::instance().exportAccounts(
421 {AccountModel::instance().selectedAccount()->id()},
422 path,
423 password);
424 };
425 QtConcurrent::run(func, dlg.path_, dlg.password_);
426 }
427}
Edric Milaret25236d92016-03-28 09:40:58 -0400428
429void
430ConfigurationWidget::on_avatarButton_clicked()
431{
432 PhotoBoothDialog dlg;
433 dlg.exec();
434 if (dlg.result() == QDialog::Accepted) {
435 auto image = QImage(dlg.fileName_);
436 auto avatar = image.scaled(100, 100, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
437 ProfileModel::instance().selectedProfile()->person()->setPhoto(avatar);
438 ProfileModel::instance().selectedProfile()->save();
439 ui->avatarButton->setIcon(QPixmap::fromImage(Utils::getCirclePhoto(avatar, ui->avatarButton->width())));
440 }
441}
442
443void
444ConfigurationWidget::on_profileNameEdit_textEdited(const QString& name)
445{
446 ProfileModel::instance().selectedProfile()->person()->setFormattedName(name);
447 ProfileModel::instance().selectedProfile()->save();
448}